| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 | 31 |
- js
- IntelliJ
- 테스트자동화
- 자바
- Java
- java테스트
- 스프링부트
- junit5
- Array
- 자바스크립트
- ArrayList
- 단위테스트
- javascript
- Eclipse
- HashMap
- math
- junit
- 정규식
- list
- CSS
- SpringBoot
- 인텔리제이
- 배열
- Visual Studio Code
- 자바문법
- input
- vscode
- string
- html
- 문자열
- Today
- Total
어제 오늘 내일
[Spring Boot] AOP 심화 분석 - LogAspect 코드 뜯어보기 & 문법 완벽 정리 본문
지난 포스팅에서 우리는 LogAspect 클래스를 이용해 로그를 자동화했습니다.
하지만 코드가 어떻게 동작하는지 정확히 모르고 쓴다면, 나중에 "Service 계층에도 로그를 찍고 싶은데?" 라거나 "리턴 값을 바꾸고 싶은데?" 같은 상황이 왔을 때 응용하기 어렵습니다.
오늘은 LogAspect 코드를 한 줄씩 해부하고, Pointcut 작성법부터 다양한 어노테이션까지 AOP의 핵심 문법을 마스터해 보겠습니다.
1. 전체 코드 다시 보기
먼저 분석할 대상인 LogAspect.java의 전체 코드입니다.
@Slf4j
@Aspect // (1) AOP 클래스 명시
@Component // (2) Bean 등록
public class LogAspect {
// (3) Pointcut: 적용 범위 설정 (서명)
@Pointcut("execution(* com.example.board.controller..*.*(..))")
public void controller() {}
// (4) Advice: 실행 시점 설정 (@Around)
@Around("controller()")
public Object logging(ProceedingJoinPoint joinPoint) throws Throwable {
// (5) 사전 처리 (Before)
log.info("요청 시작!");
long start = System.currentTimeMillis();
try {
// (6) 타겟 메서드 실행 (Proceed)
Object result = joinPoint.proceed();
// (7) 사후 처리 (After Returning)
long end = System.currentTimeMillis();
log.info("요청 종료! 시간: {}ms", end - start);
return result;
} catch (Throwable e) {
// (8) 예외 처리 (After Throwing)
log.error("에러 발생!");
throw e;
}
}
}2. Pointcut 상세 분석: "어디에 적용할까?"
코드의 (3)번 부분입니다. AOP에서 가장 어렵게 느껴지는 부분이죠.
@Pointcut("execution(* com.example.board.controller..*.*(..))")
public void controller() {} Q1. 라는 텅 빈 메서드는 왜 필요한가요?
이 메서드는 포인트컷 서명(Signature)이라고 부릅니다. 쉽게 말해 "긴 표현식에 별명을 붙이는 것"입니다.
만약 이 메서드가 없다면, 우리는 @Around, @Before 등을 쓸 때마다 저 긴 execution(...) 문자열을 계속 복사/붙여넣기 해야 합니다.
- 별명 사용:
@Around("controller()")➡️ 깔끔! ✨ - 직접 입력:
@Around("execution(* com.example.board....)")➡️ 지저분하고 오타 위험! 😱
Q2. Pointcut 표현식 작성법 (문법 해부)
가장 많이 쓰는 execution 지시자의 문법은 다음과 같습니다.
공식:
execution(접근제어자? 리턴타입 패키지.클래스.메서드(파라미터) 예외?)
우리가 쓴 코드를 대입해 볼까요?
*(맨 앞): 리턴 타입.void,String,List등 무엇이든 상관없다는 뜻.com.example.board.controller: 패키지 경로...: 하위 패키지 포함. (controller폴더 안에api폴더가 있어도 포함됨)*(클래스 자리): 모든 클래스. (MemberController,BoardController등).*(메서드 자리): 모든 메서드. (login,join등)(..): 파라미터. 개수가 0개든 10개든, 타입이 뭐든 상관없음.
💡 응용해보기 (퀴즈)
- Service 패키지의 모든 메서드에 적용하려면?
execution(* com.example.board.service..*.*(..))
- 메서드 이름이 'find'로 시작하는 것만 적용하려면?
execution(* com.example..*.find*(..))
3. Advice 상세 분석: "언제 실행할까?" (어노테이션 종류)
코드의 (4)번 부분입니다. 우리는 @Around를 썼지만, 상황에 따라 더 적절한 어노테이션들이 있습니다.
| 어노테이션 | 실행 시점 | 특징 및 용도 |
| @Before | 메서드 실행 전 | 타겟 메서드를 막을 순 없습니다. (예: 권한 체크, 데이터 유효성 검사 로그) |
| @AfterReturning | 메서드 성공 후 | 메서드가 값을 반환한 직후 실행됩니다. (예: 리턴 데이터 로깅, 결과값 가공) |
| @AfterThrowing | 예외 발생 시 | 에러가 났 때만 실행됩니다. (예: 에러 감지 알림, 트랜잭션 롤백 로그) |
| @After | 무조건 (성공/실패 무관) | 자바의 finally와 같습니다. (예: 리소스 반환, 연결 종료) |
| @Around | 전 + 후 + 예외 (만능) | 메서드 실행을 직접 제어할 수 있는 가장 강력한 어드바이스입니다. 시간 측정이나 트랜잭션 관리는 이것만 가능합니다. |
4. @Around 작성법과 ProceedingJoinPoint
@Around는 가장 강력한 만큼 작성법이 조금 까다롭습니다.
@Around("controller()")
public Object logging(ProceedingJoinPoint joinPoint) throws Throwable { ... }Q1. 가 뭔가요?
AOP가 가로챈 "실제 실행 중인 메서드 정보"가 담긴 객체입니다.
joinPoint.getSignature().getName(): 실행된 메서드 이름 (예:login)joinPoint.getArgs(): 메서드에 들어온 파라미터들 (예:userDto)
주의: ProceedingJoinPoint는 오직 @Around에서만 사용할 수 있습니다. (@Before 등에서는 JoinPoint를 씁니다.)
Q2. 는 왜 중요한가요?
이 코드는 "원래 가려던 길(Controller) 계속 가세요" 라는 명령어입니다.
- 이 줄 위쪽에 쓴 코드는
@Before시점에 실행됩니다. - 이 줄 아래쪽에 쓴 코드는
@After시점에 실행됩니다. - ⚠️ 만약 이 코드를 빼먹으면? 요청이 컨트롤러로 넘어가지 않고 여기서 멈춥니다. (서버 먹통의 원인!)
Q3. 왜 리턴 타입이 인가요?
AOP는 login 메서드(리턴: JwtToken)에도 걸리고, test 메서드(리턴: String)에도 걸립니다.
어떤 타입이 올지 모르기 때문에, 자바의 최상위 타입인 Object로 받아서 그대로 토스(return result)해줘야 합니다.
5. 전체 동작 흐름 (Sequence Diagram)
이 복잡한 과정이 실제로는 어떻게 흘러가는지 그림으로 정리해 봅시다.

🎉 마무리
AOP는 처음엔 낯설지만, "Pointcut으로 위치를 잡고, Advice로 타이밍을 잡는다"는 원리만 알면, 로깅뿐만 아니라 권한 처리, 트랜잭션 등 고급 기능을 자유자재로 구현할 수 있습니다.
'IT > SpringBoot' 카테고리의 다른 글
| [Spring Boot] 실무편 - 예외 처리의 완성, 전역 예외 처리 (@RestControllerAdvice) (0) | 2026.02.28 |
|---|---|
| [Spring Boot] 필수 어노테이션 총정리 (Cheat Sheet) 📝 (0) | 2026.02.28 |
| [Spring Boot] 로그, 노가다 그만! AOP로 요청/응답/시간 자동 기록하기 (0) | 2026.02.27 |
| [Spring Boot] 기초편 - System.out.println은 그만! 로그(Log) 제대로 찍기 (0) | 2026.02.26 |
| [Spring Security] 16편 - "3초 만에 가입" OAuth2 소셜 로그인 연동 (Google) (0) | 2026.02.25 |
