Aspect-Oriented Programming (AOP)은 컴퓨터 프로그래밍에서 중요한 패러다임으로, 소프트웨어 모듈화를 더욱 강화하는 방법을 제공합니다. 이 기술은 흩어져 있는 코드(예: 로깅, 트랜잭션 관리, 보안 등)를 한 곳에서 관리하도록 도와주는데, 이렇게 흩어져 있는 코드를 우리는 "관심사(cross-cutting concern)"라고 부릅니다.
그럼 AOP를 좀 더 구체적으로 알아봅시다.
AOP의 기본 용어
AOP에서는 몇 가지 중요한 개념을 이해해야 합니다:
Aspect: 프로그램에서 여러 객체나 함수에서 공통으로 적용되는 기능을 말합니다. 로깅, 트랜잭션 관리, 보안 등이 이에 해당합니다.
Join point: 프로그램의 실행 중에 특정 위치를 가리킵니다. 예를 들어, 메소드 호출이나 예외 처리 등이 이에 해당합니다.
Advice: Aspect의 특정 Join point에서 실행되는 코드 조각입니다. Advice는 '전' (Before), '후' (After), '주변' (Around) 등의 타입을 가질 수 있습니다.
Pointcut: 어떤 Join point에서 Advice를 실행할지 결정하는 표현식입니다.
@Aspect
@Component
public class LoggingAspect {
// Pointcut 표현식으로, 'com.example.service' 패키지 내의 모든 메서드에 적용됩니다.
@Pointcut("execution(* com.example.service.*.*(..))")
private void allServiceMethods() {}
// Before Advice: 위의 Pointcut에 정의된 모든 메서드 호출 전에 실행됩니다.
@Before("allServiceMethods()")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Method " + joinPoint.getSignature().getName() + " is about to be called");
}
// After Advice: 메서드 호출 후에 실행됩니다. 성공적으로 끝나거나 예외가 발생하더라도 실행됩니다.
@After("allServiceMethods()")
public void logAfter(JoinPoint joinPoint) {
System.out.println("Method " + joinPoint.getSignature().getName() + " has been called");
}
// Around Advice: 메서드 호출 전후로 실행됩니다.
@Around("allServiceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Method " + joinPoint.getSignature().getName() + " is being called");
Object result = joinPoint.proceed(); // 실제 메서드 실행
System.out.println("Method " + joinPoint.getSignature().getName() + " was called");
return result;
}
}
AOP의 장점
AOP는 코드의 중복을 제거하고 모듈화를 강화하므로 다음과 같은 이점이 있습니다:
유지보수가 쉬워집니다: 코드가 중복되지 않으므로 수정이 필요할 때 한 곳에서만 수정하면 됩니다.
가독성이 향상됩니다: 각 모듈이 하나의 관심사만을 담당하므로 코드의 목적을 이해하기 쉽습니다.
생산성이 향상됩니다: 공통 기능을 한 곳에서 관리하므로 새 기능을 개발하는데 더 집중할 수 있습니다.
AOP 예제 코드 (Spring Framework)
Spring Framework는 자바에서 가장 널리 사용되는 프레임워크 중 하나로, AOP를 지원합니다.
아래는 Spring에서 Aspect를 구현하는 간단한 예제 코드입니다:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LoggingAspect {
@Before("execution(public String getName())")
public void LoggingAdvice(){
System.out.println("Advice run. Get Method called.");
}
}
이 코드는 getName이라는 메소드가 실행되기 전에 로그 메시지를 출력하는 Aspect를 정의합니다.
그리고 AOP에서 빼놓을 수 없는 개념이 바로 '위빙(Weaving)'입니다. 위빙은 횡단 관심사를 애플리케이션의 비즈니스 로직과 결합시키는 과정을 말합니다.
위빙은 크게 세 가지 시점에서 이루어집니다.
컴파일 타임 위빙(Compile-time weaving) : 컴파일 과정에서 어드바이스(Advice, 횡단 관심사를 구현한 코드)가 타깃 코드에 삽입됩니다. AspectJ와 같은 AOP 도구에서 주로 사용되는 방식입니다.
클래스 로딩 타임 위빙(Load-time weaving, LTW) : 클래스가 JVM에 로드되는 시점에 바이트 코드에 어드바이스가 삽입됩니다. 이 방식은 스프링이나 AspectJ에서 선택적으로 사용할 수 있습니다.
런타임 위빙(Runtime weaving) : 런타임 중에 프록시 객체를 생성하여 어드바이스를 적용하는 방식입니다. 스프링 AOP에서 주로 사용되는 방식이며, 런타임에 동적으로 어드바이스를 적용하고 제거할 수 있는 장점이 있습니다.
즉, 위빙이란 AOP에서 횡단 관심사를 애플리케이션의 비즈니스 로직에 '엮어 넣는' 과정을 의미합니다. 이를 통해 중복된 코드를 줄이고, 모듈의 응집력을 높이며, 코드의 가독성을 향상시킬 수 있습니다.
스프링 AOP를 사용하는 간단한 예제를 통해 위빙에 대해 설명드리겠습니다.
Performance라는 인터페이스와 이를 구현한 MusicPerformance라는 클래스입니다. 이들은 우리의 핵심 비즈니스 로직을 나타냅니다.
다음은 Performance라는 인터페이스와 이를 구현한 MusicPerformance라는 클래스입니다. 이들은 우리의 핵심 비즈니스 로직을 나타냅니다.
public interface Performance {
public void perform();
}
public class MusicPerformance implements Performance {
public void perform() {
System.out.println("Performing music...");
}
}
그리고 다음은 Audience라는 Aspect를 나타냅니다. 이 Aspect는 공연이 시작하기 전과 후에 관객들이 행동하는 방식을 나타내는 로직을 담고 있습니다.
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
@Aspect
public class Audience {
@Before("execution(** concert.Performance.perform(..))")
public void silenceCellPhones() {
System.out.println("Silencing cell phones");
}
@After("execution(** concert.Performance.perform(..))")
public void applause() {
System.out.println("CLAP CLAP CLAP!!!");
}
}
위의 코드에서 @Before와 @After 어노테이션은 각각 공연이 시작하기 전과 후에 실행되는 메소드를 나타냅니다. 여기서 Aspect (Audience)와 핵심 로직 (MusicPerformance) 사이에 있는 연결이 바로 위빙입니다. 위빙은 이렇게 Aspect의 Advice를 핵심 비즈니스 로직에 적용하는 것을 말합니다.
이 경우, 위빙은 스프링 프레임워크의 런타임 시점에서 일어납니다. 즉, 애플리케이션 실행 도중에 silenceCellPhones()와 applause() 메소드가 MusicPerformance의 perform() 메소드에 적용되는 것입니다. 이렇게 런타임 위빙을 통해 애플리케이션의 비즈니스 로직을 수정하지 않고도 횡단 관심사를 적용할 수 있습니다.
마무리
Aspect-Oriented Programming은 프로그래밍에서 중요한 패러다임입니다. 코드를 더욱 모듈화하고 가독성을 높여 소프트웨어 개발의 효율성을 높일 수 있습니다. Spring과 같은 프레임워크를 통해 쉽게 AOP를 활용해 볼 수 있습니다.
여기까지 AOP에 대해 알아보았습니다. 다음에는 AOP를 실제 프로젝트에 어떻게 적용할 수 있는지에 대해 알아보겠습니다.
'spring' 카테고리의 다른 글
스프링 보안 강의: Spring Security 이해하기 (0) | 2023.06.05 |
---|---|
DispatcherServlet 이란? (0) | 2023.05.29 |
SpringBoot에서 의존성 주입(Dependency Injection, DI)을 이해하기 (0) | 2023.05.21 |
SpringBoot에서 이해하기 쉬운 IOC(Inversion of Control) 살펴보기 (0) | 2023.05.21 |
spring framework를 사용하는 이유 (0) | 2023.03.19 |