1. ResponseBodyAdvice 소개
1.1 개념
ResponseBodyAdvice는 Spring MVC에서@ResponseBody또는ResponseEntity를 사용하는 컨트롤러 메서드의 실행 후, HttpMessageConverter로 응답 본문이 작성되기 전에 응답을 커스터마이징할 수 있게 해주는 인터페이스입니다.- 컨트롤러가 반환한 데이터가 실제 HTTP 응답으로 변환되기 직전에 가로채서 수정할 수 있는 기능을 제공합니다.
1.2 주요 특징
- Spring 4.1부터 도입된 인터페이스입니다.
- HTTP 응답 본문을 전역적으로 가로채고 수정할 수 있습니다.
@ControllerAdvice와 함께 사용하면 자동으로 감지되어 등록됩니다.- 또한
@ControllerAdvice어노테이션과 함께 사용되어 여러 컨트롤러에 걸쳐 응답 본문에 전역적인 변경사항을 적용할 때 활용됩니다.
- 또한
RequestMappingHandlerAdapter와ExceptionHandlerExceptionResolver에 직접 등록할 수도 있습니다.
2. ResponseBodyAdvice 인터페이스 구조
2.1 인터페이스 정의
public interface ResponseBodyAdvice<T> {
boolean supports(MethodParameter returnType,
Class<? extends HttpMessageConverter<?>> converterType);
@Nullable
T beforeBodyWrite(@Nullable T body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response);
}
2.2 메서드 상세 설명
2.2.1 supports 메서드
boolean supports(MethodParameter returnType,
Class<? extends HttpMessageConverter<?>> converterType)
- 역할: 이 컴포넌트가 주어진 컨트롤러 메서드의 반환 타입과 선택된 HttpMessageConverter 타입을 지원하는지 확인
- 매개변수:
returnType: 컨트롤러 메서드의 반환 타입converterType: 선택된 컨버터 타입
- 반환값:
beforeBodyWrite메서드가 호출되어야 하면true, 아니면false
2.2.2 beforeBodyWrite 메서드
@Nullable
T beforeBodyWrite(@Nullable T body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response)
- 역할: HttpMessageConverter가 선택된 후, write 메서드가 호출되기 직전에 실행
- 매개변수:
body: 작성될 응답 본문returnType: 컨트롤러 메서드의 반환 타입selectedContentType: 콘텐츠 협상을 통해 선택된 콘텐츠 타입selectedConverterType: 응답에 쓰기 위해 선택된 컨버터 타입request: 현재 요청response: 현재 응답
- 반환값: 전달받은 본문 또는 수정된(새로운) 인스턴스
3. 동작 원리와 실행 순서
3.1 Spring MVC 요청 처리 흐름에서의 위치
- 클라이언트 요청 → Spring 애플리케이션으로 HTTP 요청이 들어옵니다.
- DispatcherServlet → 모든 요청을 받아 처리를 시작합니다.
- HandlerMapping → 요청 URL에 맞는 컨트롤러 메서드를 찾습니다.
- HandlerAdapter → 찾은 컨트롤러 메서드를 실행할 어댑터를 선택합니다.
- Controller 메서드 실행 → 실제 비즈니스 로직이 처리되고 결과가 반환됩니다.
- 반환값 처리 → 컨트롤러가 반환한 값을 HTTP 응답으로 변환하는 과정이 시작됩니다.
- ResponseBodyAdvice.supports() 호출 → 등록된 모든 ResponseBodyAdvice에 대해 지원 여부를 확인합니다.
- supports() 결과 판단:
true인 경우: ResponseBodyAdvice.beforeBodyWrite() 호출 → 응답 본문을 수정할 기회를 제공합니다.false인 경우: 바로 다음 단계로 진행합니다.
- HttpMessageConverter 선택 → 응답 데이터를 HTTP 형식으로 변환할 컨버터를 선택합니다.
- HTTP 응답 본문 작성 → 최종 응답 본문이 작성됩니다.
- 클라이언트에게 응답 → 완성된 HTTP 응답이 클라이언트로 전송됩니다.
3.2 실행 순서
- 컨트롤러 메서드 실행 완료
- ResponseBodyAdvice.supports() 호출: 등록된 모든 ResponseBodyAdvice에 대해 지원 여부 확인
- ResponseBodyAdvice.beforeBodyWrite() 호출: 지원하는 advice에 대해 응답 본문 수정 기회 제공
- HttpMessageConverter 선택 및 실행: 최종 응답 본문을 HTTP 응답으로 변환
4. 기본 구현 예제
4.1 간단한 ResponseBodyAdvice 구현
@ControllerAdvice
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType,
Class<? extends HttpMessageConverter<?>> converterType) {
// 모든 응답에 대해 적용
return true;
}
@Override
public Object beforeBodyWrite(Object body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response) {
// 모든 응답을 표준 형식으로 래핑
if (body instanceof ApiResponse) {
return body; // 이미 래핑된 경우
}
return ApiResponse.success(body);
}
}