일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- findFirst
- auto configuration
- jpa
- 포맷터
- Spring Boot
- LogInterceptor
- Thread Safety
- Stream
- AccessLevel
- @AutoConfiguration
- Save Action
- JsonType
- findAny
- fotmatter
- ClientHttpRequestInterceptor
- restTemple
- AOP 매개변수
- ResponseBodyAdvice
- JsonStringType
- java
- AOP
- gradle
- 쓰레드 안전
- AOP target
- vaultTemplate
- AOP this
- 개방/폐쇄 원칙
- Starter
- RestTemplate
- spring
- Today
- Total
맨땅에 헤딩하는 개바른자
Controller Response 공통 처리 하기 본문
프로젝트 구성 할 때 Response를 공통화하기위해 공통객체를 생성하고 Controller에서 공통객체로 리턴하는 구간을 간략하게 처리할 수 있는 방법입니다.
보통 Controller에서 공통처리 시 아래와 같이 선언이 됩니다.
최종 객체로 ResponseEntity를 선언하고 그 안에 공통 객체를 VgnApiResponse 사용하는 구성으로 코딩이 되어 있습니다.
@GetMapping("/me")
public ResponseEntity<VgnApiResponse<MemberDto>> getMyMemberInfo() {
return ResponseEntity.ok(
VgnApiResponse.<MemberDto>builder()
.logKey(LogKey.get())
.data(memberService.getMyInfo())
.build()
);
}
리턴형태
{
"logKey": "5efb26f7-57a7-4767-919b-e5682ca9dfb0",
"data": {
"id": 1,
"email": "test@hanatour.com",
"name": "테스트",
"nickname": "테스터",
"profileUrl": ""
}
아래코드를 보면 간결하고 명확한 리턴 값의 가독성을 높인 소스코드입니다.
@GetMapping("/me")
public MemberDto getMyMemberInfo() {
return memberService.getMyInfo();
}
ResponseEntity, VgnApiResponse 객체가 사라진걸 보실 수 있습니다.
리턴형태도 이전과 동일한 것을 확인 할 수 있습니다.
{
"logKey": "f6a2095b-f5f5-4218-8dcc-75e863c0fdab",
"data": {
"id": 1,
"email": "test@hanatour.com",
"name": "테스트",
"nickname": "테스터",
"profileUrl": ""
}
}
그러면 위와 같이 간결하게하기 위해서 처리하는 과정을 알아보겠습니다.
우선 기존 사용했던 공통응답 객체는 아래와 같이 수정하였습니다.
static으로 of로 리턴 항목을 추가하는 메소드를 제거하고 생성자로 data를 주입받는 것으로 수정하였습니다.
[공통 Response 객체 생성]
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public final class VgnApiResponse<T> {
private String logKey;
private T data;
public VgnApiResponse(T data) {
this.logKey = LogKey.get();
this.data = data;
}
}
그리고 모든 Controller에서 응답될 때 걸쳐가는 구간에서 핸들링이 가능한 관련항목을 설정하여 자동으로 공통응답이 셋팅되도록 하였습니다.
[Response 핸들링 관련 설정]
@RestControllerAdvice
public class VgnResponseBodyAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(final MethodParameter returnType, final Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
return new ApiResponse(body);
}
}
여기서 사용되는 기능 중 살펴볼 것을 2가지 입니다.
1. @RestControllerAdvice
@ControllerAdvice와 @ResponseBody를 합쳐놓은 어노테이션이다. @ControllerAdvice와 동일한 역할을 수행하고, 추가적으로 @ResponseBody를 통해 객체를 리턴할 수도 있다. 따라서 단순히 예외만 처리하고 싶다면 @ControllerAdvice를 적용하면 되고, 응답으로 객체를 리턴해야 한다면 @RestControllerAdvice를 적용하면 된다. 위 두 어노테이션 모두 적용 범위를 클래스나 패키지 단위로 제한할 수도 있으며, 아래와 같이 사용하면 된다
@RestControllerAdvice(basePackageClasses = Some.class) @RestControllerAdvice(basePackages = "com.package.path")
2. ResponseBodyAdvice 인터페이스
인터페이스를 들어가면 영문으로.. 아래 처럼 번역하면 글이 나온다.
@ResponseBody 또는 ResponseEntity 컨트롤러 메서드를 실행한 후 HttpMessageConverter로 본문을 작성하기 전에 응답을 사용자 지정할 수 있습니다. 구현은 RequestMappingHandlerAdapter 및 ExceptionHandlerExceptionResolver로 직접 등록되거나 @ControllerAdvice로 주석이 추가될 가능성이 더 높으며 이 경우 둘 다에 의해 자동 감지됩니다.
Http응답 구간에서 메시지를 가공할 수 있는 구간이 존재하고 일부 객체를 직접 구현해 커스텀이 가능한 형태로 되어있다. 해당 객체를 상속하여 원하는 것을 핸들링하면되는데 메시지를 가공하거나, 에러가 발생하였을 때 가공할 수가 있는 것 같다
[간략정리]
- ResponseBodyAdvice 는 @ResponseBody가 설정된 controller가 return 할 때 실행된다.
- Exception advice 이후에 실행된다. (설정 순서 조정 가능)
- @Override 하는 beforeBodyWrite에서 최종적인 후처리를 진행한다.
# supports 메소드
이 구성 요소가 지정된 컨트롤러 메서드 반환 유형과 선택한 HttpMessageConverter 유형을 지원하는지 여부.
# beforeBodyWrite 메소드
HttpMessageConverter가 선택된 후 쓰기 메서드가 호출되기 직전에 호출됩니다.
'JAVA' 카테고리의 다른 글
static 메소드 내 지역변수는 thread safe 한가? (0) | 2022.07.22 |
---|---|
리스코프 치환 원칙 (LSP) Liskov substitytion principle (0) | 2022.05.26 |
개방/폐쇄 원칙 (OCP open/closed principle) (0) | 2022.05.24 |
JAVA 다형성을 이해해보자 (기본편) (0) | 2022.04.15 |
Spring MVC Lifecycle 구조 (0) | 2022.04.15 |