본 캠프_49일차

졸용·2025년 4월 25일

TIL

목록 보기
50/144

AOP란?

AOP (Aspect-Oriented Programming)관점 지향 프로그래밍이라고 한다


🔧 핵심 개념 요약

AOP는 "공통 관심사(공통 기능)"를 핵심 로직에서 분리해서 재사용성, 가독성, 유지보수성을 높이는 기법이다


🎯 왜 필요한가?

서비스나 컨트롤러 코드를 짜다 보면 아래와 같은 "모든 메서드에서 반복되는 코드"가 많아진다:

  • 로그 출력

  • 실행 시간 측정

  • 트랜잭션 관리

  • 인증/인가 체크

  • 예외 처리

  • 캐시 처리

이걸 매번 메서드마다 반복하면 코드가 더러워지고, 변경도 어렵다


📦 AOP 구성 요소 (Spring 기준)

구성요소역할
Aspect공통 기능이 무엇인지 정의한 클래스
Join Point메서드 실행 지점 같은 "코드의 특정 포인트"
Advice그 시점에 "무슨 일을 할지" (before, after 등)
Pointcut어떤 Join Point에 적용할지 조건 정의
Weaving실제로 대상 코드에 끼워 넣는 작업

🧪 예시: 실행 시간 측정

@Aspect
@Component
public class TimerAspect {

    @Around("execution(* com.myapp..*(..))")  // Pointcut
    public Object measureTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed(); // 핵심 로직 실행
        long end = System.currentTimeMillis();
        System.out.println("실행 시간: " + (end - start) + "ms");
        return result;
    }
}

🧼 사용하면 좋은 상황

  • @Transactional 같은 트랜잭션 처리

  • @LogExecutionTime 같은 실행 시간 로그

  • 사용자 인증, 권한 체크 (@AuthCheck)

  • 예외 감싸기

  • API 요청/응답 로깅


💬 정리

AOP는 "코드 중복 없이, 필요한 기능만 쏙쏙 껴넣을 수 있는 마법 같은 도구"
핵심 로직은 핵심에만 집중하고, 나머지 잡일은 AOP가 해주는 구조라고 보면 된다


이제 메서드 실행 전후로 로그 찍어주는 AOP 를 만들어보면,
Spring에서 AOP 쓰려면 먼저 몇 가지 준비가 필요하다.


✅ 1. 의존성 추가 (Spring Boot라면 보통 이미 있다)

build.gradle (만약 없다면 추가)

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

✅ 2. 로그 찍는 AOP 클래스 만들기

package com.outsourcing.outsourcingproject.common.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // ⭐ 포인트컷: com.outsourcing.outsourcingproject 패키지 하위의 모든 메서드
    @Pointcut("execution(* com.outsourcing.outsourcingproject..*(..))")
    public void applicationPackagePointcut() {}

    // 🔹 메서드 실행 전
    @Before("applicationPackagePointcut()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("➡️ [Before] " + joinPoint.getSignature());
    }

    // 🔹 메서드 실행 후
    @AfterReturning(pointcut = "applicationPackagePointcut()", returning = "result")
    public void logAfter(JoinPoint joinPoint, Object result) {
        System.out.println("✅ [After] " + joinPoint.getSignature());
        System.out.println("📦 [Return] " + result);
    }

    // 🔺 예외 발생 시
    @AfterThrowing(pointcut = "applicationPackagePointcut()", throwing = "error")
    public void logException(JoinPoint joinPoint, Throwable error) {
        System.out.println("❌ [Exception] " + joinPoint.getSignature());
        System.out.println("🚨 [Error] " + error.getMessage());
    }
}

✅ 3. 실행 예시

예를 들어 OrderService의 메서드 하나 실행하면 콘솔에 이렇게 찍힌다:

➡️ [Before] OrderService.createOrder(..)
✅ [After] OrderService.createOrder(..)
📦 [Return] OrderResponseDto{...}

🔥 커스터마이징도 가능

  • 특정 어노테이션 붙은 메서드만 AOP 적용

  • 메서드 실행 시간 측정

  • HttpServletRequest 꺼내서 클라이언트 IP 찍기 등등…

profile
꾸준한 공부만이 답이다

0개의 댓글