본문 바로가기
  • Let's study
BackEnd/Spring

[Spring] AOP로 REST API 응답 후처리하기

by 코딩고수이고파 2026. 8. 13.

AOP 코드를 작성할 때 가장 복잡해 보이는 부분이 어떤 메서드에 AOP를 적용할 것인지 지정하는 부분실제 메서드를 실행한 뒤 응답을 처리하는 부분이다. 해당 부분만 간단하게 정리해보겠다.

1. 어떤 메서드에 AOP를 적용할 것인가

(
    within
    (
        org.springframework.web.bind.annotation.RestController *
    )
    &&
    (
        annotation(org.springframework.web.bind.annotation.GetMapping)
        ||
        annotation(org.springframework.web.bind.annotation.PostMapping)
        ||
        annotation(org.springframework.web.bind.annotation.PutMapping)
        ||
        annotation(org.springframework.web.bind.annotation.DeleteMapping)
    )
)
||
annotation(org.springframework.web.bind.annotation.ResponseBody)

이 코드는 REST API로 사용되는 메서드에 AOP를 적용하겠다는 의미이다.

within

within(org.springframework.web.bind.annotation.RestController *)

RestController가 붙어 있는 클래스 내부의 메서드를 대상으로 한다는 의미이다.

annotation

annotation(org.springframework.web.bind.annotation.GetMapping)

해당 어노테이션이 붙은 메서드를 대상으로 한다는 의미이다.

따라서 다음과 같은 메서드가 대상이 된다.

@GetMapping
@PostMapping
@PutMapping
@DeleteMapping

@ResponseBody
따라서 전체적으로 보면 다음과 같은 의미이다.

RestController 내부에 있으면서 GetMapping, PostMapping, PutMapping, DeleteMapping 중 하나가 붙은 메서드

또는

ResponseBody가 붙은 메서드

를 AOP의 대상으로 지정한다.

2. 실제 메서드 실행하기

Object rst = joinPoint.proceed();
 

joinPoint.proceed()는 원래 실행되어야 할 실제 메서드를 실행하는 것이다.

예를 들어 Controller에 다음 메서드가 있다면,

@GetMapping
public RsData<PostDto> list() {
    // 실제 작업
}
 

AOP에서

Object rst = joinPoint.proceed();
 

를 호출하는 순간 list() 메서드가 실행된다.

그리고 메서드가 반환한 값을 rst에 저장한다.

3. 반환값이 RsData인지 확인하기

 
if (rst instanceof RsData rsData) {
    int statusCode = 201;
    response.setStatus(statusCode);
}

먼저

rst instanceof RsData

를 통해 실제 메서드의 반환값이 RsData인지 확인한다.

RsData라면 반환된 객체를 rsData 변수로 사용할 수 있다.

response.setStatus(statusCode);

를 통해 HTTP 응답 상태 코드를 직접 변경한다.

예를 들어

int statusCode = 201;
response.setStatus(statusCode);

라면 최종 HTTP 응답 코드를 201로 설정하는 것이다.

하지만 이렇게 하면 모든 응답이 201이 되므로, RsData에 getStatusCode() 만들어서 활용하는 것이 좋다.

@JsonIgnore
public int getStatusCode() {
    return Integer.parseInt(resultCode.split("-")[0]);
}

RsData에서는 resultCode의 앞부분을 HTTP 상태 코드로 사용한다.

int statusCode = rsData.getStatusCode();
response.setStatus(statusCode);
 

이 코드를 외울 필요는 없으며, within은 대상 클래스 범위, annotation은 특정 어노테이션이 붙은 메서드, proceed()는 실제 메서드 실행 정도를 이해해두면 충분하다.

댓글