부트캠프

AOP(관점 지향 프로그래밍)

taehyon 2025. 6. 12. 10:10

AOP(관점 지향 프로그래밍), 쉽게 배우기

프로그래밍하다 보면 여러 메서드에 반복적으로 들어가는 코드가 많아요.
예를 들어

  • 로그 남기기
  • 실행 시간 측정
  • 권한 체크
    이런 건 진짜 자주 나오죠.

AOP(Aspect Oriented Programming)는
이런 “공통적으로 필요한 기능”만 따로 빼서, 코드 전체에 한 번에 적용할 수 있게 도와주는 기술이에요.


1. 스프링 AOP 기본 예시

1) Aspect 클래스 만들기

import org.aspectj.lang.annotation.*; 
import org.aspectj.lang.JoinPoint; 
import org.springframework.stereotype.Component; 
@Aspect // AOP에서 관점(Aspect)임을 표시 
@Component // 스프링 빈으로 등록 
public class LoggingAspect { 

    // Pointcut: com.example.service 패키지 모든 메서드에 적용 
    @Pointcut("execution(* com.example.service..*(..))") 
    public void serviceMethods() {} // Advice: 메서드 실행 전에 로그를 남긴다 

    @Before("serviceMethods()") 
    public void logBefore(JoinPoint joinPoint) { 
    // 실행될 메서드 이름 출력 
    System.out.println("[AOP] 실행 전: " + joinPoint.getSignature().getName()); } 
    // Advice: 메서드 실행 후에 로그를 남긴다 
    
    @After("serviceMethods()") 
    public void logAfter(JoinPoint joinPoint) { 
    System.out.println("[AOP] 실행 후: " + joinPoint.getSignature().getName()); 
    } 
}

[코드 설명]

  • @Aspect: 이 클래스가 AOP의 “관점”임을 선언
  • @Pointcut: 적용 범위 지정 (여기선 서비스 계층의 모든 메서드)
  • @Before, @After: 메서드 실행 전/후로 Advice(실제로 동작할 코드)를 지정

2) 실행 시간 측정 AOP 예시

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TimeCheckAspect {

    // Around: 메서드 실행 전/후 전체를 감싸고 시간 측정
    @Around("execution(* com.example.controller..*(..))")
    public Object checkTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis(); // 시작 시간 기록

        Object result = joinPoint.proceed(); // 실제 메서드 실행

        long end = System.currentTimeMillis(); // 끝난 시간 기록

        System.out.println("[AOP] " + joinPoint.getSignature().toShortString() +
                           " 실행 시간: " + (end - start) + "ms");
        return result; // 원래 메서드의 결과를 그대로 반환
    }
}

[코드 설명]

  • @Around: 메서드 실행 전/후로 감싸서 동작 (가장 강력한 Advice)
  • joinPoint.proceed(): 실제로 타깃 메서드가 실행됨
  • 실행 시간 측정 및 출력

3) @AfterReturning으로 응답값 로깅

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.JoinPoint;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ResponseLoggingAspect {

    // 컨트롤러 패키지의 모든 메서드 리턴값을 가로채서 로그 남김
    @AfterReturning(pointcut = "execution(* com.example.controller..*(..))", returning = "response")
    public void logResponse(JoinPoint joinPoint, Object response) {
        System.out.println("[AOP] " + joinPoint.getSignature().toShortString() +
                           " 응답값: " + response);
    }
}

[코드 설명]

  • @AfterReturning: 메서드가 정상적으로 리턴한 후 동작
  • returning = "response": 실제 리턴값을 받아서 사용할 수 있음

2. 실전에서 많이 쓰는 AOP 활용 예시

  • 트랜잭션 관리: @Transactional 어노테이션이 내부적으로 AOP로 구현되어 있음
  • 로깅: 예시처럼, 요청/응답, 실행 시간 등 남기기
  • 보안: 권한 체크, 로그인 확인 등

3. 왜 AOP를 써야 할까?

  • 반복되는 코드 제거: 핵심 로직에만 집중할 수 있음
  • 유지보수 쉬움: 변경 시 한 곳만 수정하면 됨
  • 관심사 분리: 비즈니스 코드와 공통 코드가 섞이지 않음

4. 참고자료 / 더 알아보기

'부트캠프' 카테고리의 다른 글

테이블 객체끼리 관계 만들기  (0) 2025.06.24
Spring Boot, H2, 그리고 JDBC  (1) 2025.06.23
JPQL 정리  (3) 2025.06.10
StringBuilder  (1) 2025.05.14
SQL 달리기반 문제  (0) 2025.03.28