관리 메뉴

ballqs 님의 블로그

[Spring] AOP 본문

코딩 공부/Spring

[Spring] AOP

ballqs 2024. 8. 29. 14:18

스프링은 여러 특징이 있고 그중 하나가 AOP 라고 생각한다.


AOP란?

AOP(Aspect-Oriented Programming)는 '관전 지향 프로그래밍' 이라는 의미이고 메소드에 대해서 공통적으로 적용해줘야 하는 기능이 있다면 메소드마다 따로 코딩하면 중복코딩이 많아지기 때문에 AOP를 통해서 공통적으로 적용할수 있다.

 

대표적으로 사용되는 상황은 아래와 같다.

  • 로깅(Logging) : 애플리케이션의 전역적인 로깅을 구현할 때 AOP를 사용! 특정 메서드나 클래스에 대한 로그를 남기는 작업을 코드에 직접 삽입하는 대신, AOP를 통해 자동으로 로그를 기록할 수 있다. 이는 코드의 중복을 줄이고 유지보수를 쉽게 만든다.
  • 트랜잭션 관리(Transaction Management) : 트랜잭션 관리는 비즈니스 로직에서 중요한 역할을 하지만, 비즈니스 로직 코드 자체에 트랜잭션 관련 코드를 섞는 것은 바람직하지 않아서 AOP를 통해 트랜잭션 관리 로직을 비즈니스 로직에서 분리하는데 사용한다.
  • 보안(Security) : 특정 메서드에 접근 권한을 검사하거나, 인증 및 권한 부여 작업을 수행할 때 AOP를 사용한다.
  • 예외 처리(Exception Handling) : 애플리케이션 전반에 걸쳐 일관된 예외 처리 로직을 적용하고자 할 때 AOP를 사용한다.

의존성 설정

implementation 'org.springframework.boot:spring-boot-starter-aop'

사용 방법

AOP를 적용한 코드

@Configuration
@Aspect
public class LoggingAspect {
    // 멤버 변수 및 메서드
}

 

적용할 코드에 @Aspect를 선언해두면 준비는 완료 된다.


AOP Annotataion

Annotataion 설명
@Before("${pattern}") 지정한 패턴의 메소드가 실행하기 전 interceptor와 같이 동작
@After("${pattern}") 지정한 패턴의 메소드가 실행 후 동작
@Around("${pattern}") 지정한 패턴의 메소드가 실행 전, 후 동작

 

Pattern이란?

아래의 예제와 같이 패키지를 지정하는 곳

@Before("execution(* org.myapp.learnspringaop..*(..))")

@After("execution(* org.myapp.learnspringaop..*(..))")

@Around("execution(* org.myapp.learnspringaop..*(..))")

 

실제 예제

@Configuration
@Aspect
public class LoggingAspect {

    private Logger logger = LoggerFactory.getLogger(getClass());
    
    @Before("execution(* org.myapp.learnspringaop..*(..))")
    public void execute(JoinPoint joinPoint) {
        System.out.println(joinPoint.getSignature().getName());
    }
}

 

@Configuration
@Aspect
public class LoggingAspect2 {

    private Logger logger = LoggerFactory.getLogger(getClass());
    
    @Around("execution(* org.myapp.learnspringaop..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        System.out.println("START: " + joinPoint.toString());
        try{
            return joinPoint.proceed();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
        }
    }
}


마무리

좀더 자세한 AOP 사용 방법은 나중에 더 알게 되었을때 작성해야겠다.

현재로써는 간단하게 적용하는 방법을 알았고 이부분을 블로그로 남겨두어야지 싶어서 작성했다.