프로젝트/마이그레이션

Spring AOP를 활용한 로깅(Log) 설정

10Biliion 2025. 2. 4. 08:53

 

 

 

 

 

Spring AOP(Aspect-Oriented Programming)를 활용하면 애플리케이션 전반에 걸친 공통적인 로직을 효율적으로 적용할 수 있습니다. 그중 하나가 로깅 기능입니다. Spring AOP 기반 로깅 설정의 원리를 살펴보겠습니다.


전체 코드

@Component
@Aspect
@Slf4j
public class LoggingAspect {
    @Around("execution(* com.example..controller.*Controller.*(..)) " +
            "or execution(* com.example..service.*Service.*(..)) " +
            "or execution(* com.example..repository.*Repository.*(..))")
    public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        String componentType = "";
        String className = joinPoint.getSignature().getDeclaringTypeName();
        
        if (className.contains("Controller")) {
            componentType = "Controller Layer  : ";
        } else if (className.contains("Service")) {
            componentType = "Service Layer     : ";
        } else if (className.contains("Repository")) {
            componentType = "Repository Layer : ";
        }
        
        return joinPoint.proceed();
    }
}

1. @Component, @Aspect, @Slf4j

  • @Component:
    • Spring의 빈(Bean)으로 등록하여 **DI(Dependency Injection)**이 가능하도록 설정합니다.
  • @Aspect:
    • AOP 클래스임을 명시합니다. 이 어노테이션이 붙은 클래스는 공통 기능을 정의하는 역할을 합니다.
  • @Slf4j:
    • Lombok이 제공하는 로깅 어노테이션으로, log.debug(), log.info() 등의 메서드를 사용할 수 있도록 합니다.

2. 포인트컷(Pointcut)과 어드바이스(Advice)

2.1 포인트컷(Pointcut) 표현식

@Around("execution(* com.example..controller.*Controller.*(..)) " +
        "or execution(* com.example..service.*Service.*(..)) " +
        "or execution(* com.example..repository.*Repository.*(..))")

위 코드는 포인트컷 표현식을 정의하는 부분입니다.

  • execution(* com.example..controller.*Controller.*(..))
    • com.example 패키지 아래 controller 패키지에 있는 모든 Controller 클래스의 모든 메서드를 대상으로 설정합니다.
  • execution(* com.example..service.*Service.*(..))
    • com.example 패키지 아래 service 패키지에 있는 모든 Service 클래스의 모든 메서드를 대상으로 설정합니다.
  • execution(* com.example..repository.*Repository.*(..))
    • com.example 패키지 아래 repository 패키지에 있는 모든 Repository 클래스의 모든 메서드를 대상으로 설정합니다.

즉, Controller, Service, Repository 계층의 모든 메서드 실행 시 로깅이 수행됩니다.

2.2 @Around 어드바이스

public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
  • @Around 어노테이션은 메서드 실행 전후에 특정 로직을 삽입할 수 있도록 합니다.
  • ProceedingJoinPoint 객체를 사용하면 대상 메서드의 실행을 제어할 수 있습니다.

3. 로그 출력

3.1 클래스 구분

String componentType = "";
String className = joinPoint.getSignature().getDeclaringTypeName();

if (className.contains("Controller")) {
    componentType = "Controller Layer  : ";
} else if (className.contains("Service")) {
    componentType = "Service Layer     : ";
} else if (className.contains("Repository")) {
    componentType = "Repository Layer : ";
}
  • 실행되는 클래스의 타입이 Controller, Service, Repository 중 어디에 속하는지 구분합니다.

3.2 로그 출력

log.debug(componentType + className + " ." + joinPoint.getSignature().getName() + "()");
  • 최종적으로 클래스명과 실행된 메서드명을 로그로 출력합니다.

3.3 메서드 실행

return joinPoint.proceed();
  • 대상 메서드를 실제로 실행하는 부분입니다.
  • proceed()를 호출하지 않으면 대상 메서드가 실행되지 않습니다.

4. 실행 예시

4.1 Controller 메서드 실행 시 로그 예제

Controller Layer  : com.example.app.controller.UserController.getUserInfo()

4.2 Service 메서드 실행 시 로그 예제

Service Layer     : com.example.app.service.UserService.processUser()

4.3 Repository 메서드 실행 시 로그 예제

Repository Layer : com.example.app.repository.UserRepository.findById()

 

 

 

  • Spring AOP를 활용하여 Controller, Service, Repository 계층의 모든 메서드 실행을 로깅하는 기능을 구현했습니다.
  • @Around 어드바이스를 통해 메서드 실행 전후의 정보를 로깅할 수 있도록 설정했습니다.
  • 비즈니스 로직을 수정하지 않고도 전역적으로 로깅을 적용할 수 있어 유지보수에 용이합니다.