AOP에서 제일 중요한 질문은 하나다.
“공통 로직을 언제 실행할 것인가?”
수업에서도 ‘어드바이스 (횡단 관심)’는 동작 시점이 핵심이라고 계속 강조했다.
같은 로그라도 언제 찍느냐에 따라 의미가 완전히 달라진다.
예를 들어, 게시판 서비스에 아래 같은 메서드가 있다고 하자.
- insertBoard() / updateBoard() / deleteBoard()
- getBoard() / getBoardList()
이 핵심 메서드들이 실행될 때, 공통 기능 (로그 / 트랜잭션 / 예외 로그 등)을 실행 전에 할지, 정상 종료 후에 할지, 예외일 때만 할지, 또는 전 / 후를 감싸서 할지 선택하는 게 “Advice 타입 (동작 시점)”이다.
(1) Before (실행 전)
정의
- 핵심 메서드가 실행되기 바로 직전에 동작한다.
언제 쓰나
- “시작 로그”를 찍기 가장 좋다 (요청이 들어왔다는 증거를 남김)
- 권한 체크 / 세션 체크처럼 실행 전에 막아야 하는 정책
- 가벼운 파라미터 검증 (형식 체크 등)
수업에서 나온 체감 포인트
수업 중 실습에서도 “서비스 들어오자마자 찍히는 로그”가 바로 before라고 짚었다.
코드에는 로그 호출이 없는데도 DAO / 서비스보다 먼저 로그가 찍히면 before가 걸린 것이다.
실습 코드와 연결 (예시)
LogAdvice는 printLog()로 로그를 찍는 공통 로직이다.
이걸 before로 묶으면 insertBoard()든 getBoardList()든 실행 전에 항상 찍히게 만들 수 있다.
(2) After (실행 후, “끝” 개념)
정의
- 핵심 메서드가 끝난 뒤 실행된다.
- 중요한 뉘앙스: 성공 / 예외 여부와 무관하게 “끝났다는 사실”에 붙는 타입이다.
언제 쓰나
- 종료 로그 (“끝났다” 기록)
- finally 성격의 공통 처리 (단, DB close 같은 건 보통 try-with-resources가 더 안전한 기본기)
감각 정리
- After는 “성공했는지 실패했는지”보다 “일단 이 함수가 끝났다”라는 사실에 관심이 있다.
(3) After Returning (정상 반환 후)
정의
- 핵심 메서드가 정상적으로 값을 반환한 직후에 실행된다.
After와 뭐가 다르나? (많이 헷갈리는 포인트)
- After: 성공 / 실패 상관 없이 “끝”
- After Returning: 정상 종료 + 반환이 끝난 뒤에만 실행
“성공 케이스에서만 정책을 적용하고 싶다”면 After Returning이 더 정확하다.
언제 쓰나 (예시)
- 반환값 기반 로깅 (예: 조회 결과 건수, 반환 DTO 요약)
- 성공했을 때만 남겨야 하는 감사 로그 (audit log)
- 성공 결과를 캐시에 저장하는 정책 (실패 / 예외는 저장하면 안 됨)
(4) After Throwing (예외 발생 시)
정의
- 핵심 메서드에서 예외가 발생했을 때만 실행된다.
수업 실습과 정확히 연결되는 부분
수업에서도 “예외가 없으면 아무 일도 안 하고 예외가 터지면 예외 전용 로그가 나온다” 흐름으로 보여줬다.
실습 코드에도 예외 전용 Advice가 있다:
public class AfterThrowingAdvice {
public void printLog() {
System.out.println("예외발생시 출력되는 로그");
}
}
그리고 서비스에서 일부러 예외를 터뜨려 확인한다:
public boolean insertBoard(BoardDTO dto) {
if(dto.getBid() == 0) { // == 항상
throw new NullPointerException("런타임 에러");
}
return boardDAO.insertBoard(dto);
}
insertBoard() 실행 중 예외가 터지면 → AfterThrowingAdvice.printLog()가 예외 상황에서만 실행되는 구조를 만들 수 있다.
실무에서 After Throwing을 어떻게 쓰나
- 예외 전용 로그 (스택트레이스 / 요청 파라미터/사용자 정보 등)
- 모니터링 지표 (장애 카운트) 적재
- 알림 (슬랙 / 메일) 트리거
단, 수업에서 “예외 처리를 Advice로 다 해결하는 건 추천하지 않는다”는 뉘앙스도 있었다.
핵심 예외 처리는 보통 로직 / 전역 예외 처리기에서 하고 AOP는 “관측 / 정책”에 쓰는 게 더 안전하다.
(5) Around (전 / 후를 감싸는 “가장 강력한 타입”)
정의
- 핵심 메서드를 전 / 후로 감싸서 제어한다.
- 단순히 “앞에 찍고 끝”이 아니라 핵심 메서드 실행 자체를 중간에서 컨트롤할 수 있다.
수업에서 강조한 Around의 ‘폼 (형태)’
수업에서는 around 메서드가 보통 아래 기본 폼을 가진다고 설명했다:
- 인자: ProceedingJoinPoint (PJP)
- 반환: Object
- 예외: throws (예측 불가하니 크게 잡음)
public class AroundAdvice {
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("비즈니스 메서드 수행 전");
Object returnObj = pjp.proceed();
System.out.println("비즈니스 메서드 수행 후");
return returnObj;
}
}
ProceedingJoinPoint (pjp)가 핵심인 이유
- pjp는 “지금 실행될 핵심 메서드”를 들고 있다.
- pjp.proceed()가 핵심 메서드 실제 실행 지점이다.
이 줄을 호출하면 통과 (proceed)되고 호출하지 않으면 핵심 메서드 자체가 실행되지 않을 수도 있다.
그래서 around는 인터셉터 (가로채기) 같은 성격으로 설명된다.
왜 반환 타입이 Object인가
around는 포인트컷을 넓게 잡는 경우가 많다.
그럼 어떤 메서드는 BoardDTO를 반환하고 어떤 메서드는 List<BoardDTO>를 반환하고 또 어떤 건 boolean을 반환한다.
around는 이 모든 반환 타입을 하나로 받을 수 있어야 하므로 Object로 받아서 그대로 리턴하는 게 기본 패턴이 된다.
Around는 언제 쓰면 실무자가 좋아하나
- 실행 시간 측정 (성능 측정): 시작 시간 찍고 proceed 후 종료 시간 찍기
- 캐싱: 실행 전 캐시 조회 → 있으면 proceed 생략 가능
- 마스킹: 반환값을 공통 규칙으로 가공
- 트랜잭션처럼 전 / 후가 한 세트인 정책 (단, 실무는 스프링 트랜잭션 AOP가 표준)
(6) “실습 흐름”으로 연결해서 한 번에 이해하기
BoardClient가 applicationContext.xml을 올리고 BoardService 빈을 꺼내 호출한다.
호출 흐름은 이런 구조다:
- 메뉴 1(전체출력) → getBoardList()
- 메뉴 3(글 작성) → insertBoard()
여기에 설정이 붙으면 (다음 파트에서 XML로 연결):
- before가 걸린 메서드는 실행 전에 로그가 먼저 찍히고
- get*에 around가 걸리면 조회 로직이 전 / 후로 감싸지고
- insertBoard()에서 예외가 터지면 after-throwing이 그때만 실행된다.
이게 수업에서 말한 “코드에 직접 호출이 없는데도 설정으로 공통 로직이 자동 결합되는 구조”의 핵심이다.
요약
- Before: 실행 전 (시작 로그 / 권한 체크)
- After: 실행 후(성공 / 예외 무관) (마무리 로그)
- After Returning: 정상 반환 후 (반환값 기반 정책)
- After Throwing: 예외 발생 시 (예외 전용 로깅 / 모니터링)
- Around: 전 / 후 감싸서 제어 (proceed가 핵심, 가장 강력)
수업에서도 이 5개를 “동작 시점 세트”로 정리했다.
'수업 복습' 카테고리의 다른 글
| Spring XML 기반 AOP 실습 정리 (0) | 2026.01.23 |
|---|---|
| XML 기반 AOP 설정 실습 흐름 (0) | 2026.01.23 |
| Spring AOP 개념 / 용어 정리 (0) | 2026.01.23 |
| Spring MVC / JSP Q&A 정리 (0) | 2026.01.22 |
| Spring Boot + JSP 로그인부터 게시판 조회 (0) | 2026.01.20 |