Notice
Recent Posts
Recent Comments
Link
«   2025/09   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

코딩 이래요래

AOP를 통한 서비스 계층 로그 분리 본문

Refactoring

AOP를 통한 서비스 계층 로그 분리

강범호 2025. 5. 2. 11:19

AOP를 적용해 로깅 코드 분리 리팩토링

이전에 정리한 블로그 내용 중 AOP 개념을 정리한 적이 있는데, 그 당시에는 간단하게만 정리하고 넘어갔지만, 프로젝트 리팩토링을 통해 개념을 다시 정리 해보려고 한다

 

Spring Framework 핵심 개념

1. IoC (Inversion of Control) - 제어의 역전 즉, 객체의 생성, 초기화 등 개발자가 직접 제어하는 것이 아닌, 컨테이너가 대신 관리하는 개념 1-1. IoC 구조 ☑️ 기존의 의존성 주입// controllerpublic class User

kh-coding.tistory.com

 

 

AOP(Aspect Oriented Programming)란 ?

  • OOP 프로그래밍을 하다보면 어쩔 수 없이 반복적으로 등장하는 코드들이 생기기 마련
    • 로깅
    • 트랜잭션 처리
    • 보안 검사
  • 이러한 중복되는 코드들을 하나의 모듈로 분리하여 관리하는 설계 방법이다

AOP 용어 정리

용어 설명  예시 (Spring AOP)
Pointcut 어드바이스가 적용될 지점을 정의하는 표현식. 메서드 실행 시점 등을 지정. @Pointcut("execution(* com.example.service..*(..))")
Advice 실제로 수행되는 부가기능 로직. 아래 Before, After 등으로 세부 분류됨. @Before("pointcut()")
JoinPoint 실제 AOP가 적용되는 구체적인 실행 지점. 메서드 실행, 생성자 호출 등. JoinPoint joinPoint 파라미터로 메서드 정보 접근
Before Advice 메서드 실행 전에 실행되는 부가기능. @Before("pointcut()")
After Advice 메서드 실행이 끝난 직후 실행 (정상/예외 관계없이 무조건 실행). @After("pointcut()")
AfterReturning 메서드가 정상적으로 끝난 후 실행. 리턴값을 가로챌 수 있음. @AfterReturning(pointcut = "pointcut()", returning = "result")
AfterThrowing 메서드 실행 중 예외가 발생했을 때만 실행. @AfterThrowing(pointcut = "pointcut()", throwing = "ex")
Around Advice 메서드 실행 전후 전체를 감쌈. 실행 여부도 제어 가능하며 가장 강력함. @Around("pointcut()")
Aspect 포인트컷 + 어드바이스를 묶은 단위 모듈. @Aspect 클래스
Weaving 실제 코드에 AOP 기능이 적용되는 시점. (컴파일 타임, 로드 타임, 런타임 등) 스프링 AOP는 런타임 위빙(프록시 기반)
Target Object AOP가 적용되는 실제 비즈니스 객체(빈). ChannelServiceImpl 같은 클래스

 

AOP 적용하기 (프로젝트 리팩토링)

🖼️ AOP 다이어그램

 

🎯 기존 코드

Service 코드

  • createChannel 메소드에는 channel을 생성하는 비즈니스 로직, 전달받은 인자를 확인하는 로깅 코드가 같이 있음
  • OOP 관점으로 보았을 때 createChannel 메소드의 상관 없는 로깅 코드가 존재함

Application (현 프로젝트에서 Controller 역할)

  • Controller에도 불필요한 메소드의 실행 결과를 확인하는 로깅 메소드들이 존재함

✅ AOP를 적용해 로깅 코드 분리

logging 클래스 정의

 

  • @Pointcut("execution(* com.sprint.mission.discodeit.service..*(..))") 포인트컷 지정
    • com.sprint.mission.discodeit.service 패키지 이하 모든 메소드 실행 시점에 적용
  • @Before("serviceMethods()") serviceMethods의 포인트컷이 실행되기 전
    • joinpoint를 통해 메소드 이름, 전달 받은 인자를 로깅
  • @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    • 메소드가 실행되고난 후 메소드의 이름, 결과 값을 로깅
  • @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
    • 메소드 실행 중 예외가 발생하였을 경우에만 예외 로깅

Service 코드 수정

  • 전달받은 인자를 확인하는 로깅 코드 제거

Controller 코드

// 기존 코드
log("채널 생성", () -> channelService.createChannel(channelCreateDto));

// 수정한 코드
Channel channel = channelService.createChannel(channelCreateDto);
  • AOP가 자동으로 실행 로그를 남기므로 기존 수동 로그 제거

✨ 결과

  • ✅ 서비스 계층의 모든 메서드는 자동으로 실행 로그가 남음
  • ✅ 서비스/컨트롤러의 중복 코드 제거 → 비즈니스 로직만 집중
  • ✅ 유지보수성, 코드 가독성 향상
  • 추후 Repository, Controller도 AOP 적용 예정