eelseungmin

@ResponseBody와 ResponseEntity, 어떤 걸 사용할까?

by eelseungmin

들어가며

최근 아쉽게도 더 이상 진행하지 못하고 종료하게 되었던 프로젝트 코드를 살펴보다가, 문득 @ResponseeBody와 ResponseEntity 둘 중 어떤 것을 사용할지에 대한 의문이 들었다.

 

차이점

개념의 차이

ResponseEntity is like @ResponseBody but with status and headers.

스프링 공식 문서에서는 ResponseEntity를 @ResponseBody와 대체로 비슷하지만 header나 status를 묶어서 설정할 수 있도록 했다고 설명하고 있다.

 

@GetMapping("/api/category")
public ResponseEntity<ApiSuccessResponse<CategoryResponse>> getCategory() {

  return ResponseEntity.ok()
          .body(new ApiSuccessResponse<>(placeService.getCategory()));
}

ReponseEntity는 위처럼 빌더 방식으로 응답을 작성할 수도 있고, 생성자를 활용하는 방식으로도 작성이 가능하다. 다만 빌더가 지원되는 이상 굳이 생성자 방식으로 작성하기보다는 빌더 방식으로 작성해서 가독성도 얻고, 오타를 컴파일 타임에 잡아낼 수 있도록 하는 것이 더 좋다고 생각한다.

 

@ReponseBody는 아래와 같은 코드가 될 것이다.

@GetMapping("/api/category")
public ApiSuccessResponse<CategoryResponse> getCategory() {

  return new ApiSuccessResponse<>(placeService.getCategory());
}

얼핏 봐서는 @ResponseBody 어노테이션이 보이지 않지만 컨트롤러 클래스 상단에 @RestController를 작성하게 되면 다음 사진처럼 내부에 @ResponseBody가 자동으로 포함되게 된다.

내부에 @ResponseBody가 포함된 모습.

 

그리고 조사를 하다 보니 @ResponseBody의 단점으로서 상태 코드와 헤더를 유연하게 변경하지 못한다는 점을 단점으로 꼽는 경우도 있었는데, 이는 @ReponseStatus 어노테이션을 덧붙이고 HttpServletResponse에 헤더를 설정해서 응답함으로써 해결이 가능하기 때문에 틀린 내용이다. 물론 이 방식 때문에 ResponseEnity보다 가독성이 떨어지고 깔끔하지 못하다는 점은 동의한다.

 

성능의 차이

https://www.youtube.com/watch?v=fCgU_VFv33M&list=WL&index=6

10분 테코톡 영상 중 관련 주제가 있어서 들어봤는데 결론적으로 두 사용 방식은 HTTP 응답을 생성하는 방식이 동일하기 때문에 성능 면에서 차이가 없을 것이라는 내용이 있었다.

 

내포하는 의미의 차이

단순 성능이나 개념을 떠나서 각각의 사용 방식이 내포하는 의미가 다를 수 있다. 이게 무슨 뜻일까? 다음 내용을 살펴보자.

 

https://github.com/cheese10yun/spring-guide/issues/33

위 링크에서 cheese10yun님의 답변을 살펴보면 다음과 같은 내용이 있다.

ResponseEntity 객체로 감싼다는 것은 해당 컨트롤러에서 여러 가지 케이스에 대해서 대체하여 그에 따른 HTTP Status Code를 포함하여 Response Body를 내려주겠다는 의미인데요.
그렇다는 건 개별 컨트롤러 단에서 예외에 대한 핸들링을 진행하겠다는 의미입니다. 그것을 하는 것이 바람직하지 않다고 생각하여 GlobalExceptionHandler를 만든 것인데요. API 서버에서 발생하는 모든 예외를 해당 객체에서 처리하여 통일성 있는 예외 Response를 내려주고 각 개별적인 컨트롤러에 예외에 대한 핸들링에 대한 책임을 부여하지 않아 컨트롤러 계층을 작게 가져가기 위함입니다.
다시 정리하면 일반 컨트롤러에서 ResponseEntity으로 응답하겠다는 것은 예외에 대한 처리까지 해당 컨트롤러에서 진행하겠다는 의미입니다. 쉽게 말해서 개별적인 컨트롤러는 MemberResponse, CouponResponse에 대한 성공 2xx에 대한 응답을 내려주게 객체의 책임을 작게 부여한 것입니다.

 

결론

상황에 따라 다른 방식을 가져가야 한다는 점과 최근 프로젝트에서 컨트롤러 단의 메서드까지 ResponseEntity로 감쌀 필요가 없었다는 점도 알게 되었다. 이러한 코드는 GlobalExceptionHandler의 존재를 모르는 사람이 본다면 컨트롤러 단에서 예외에 대한 핸들링을 하는 것처럼 비춰질 수도 있을 것이다.

 

아무튼 결론은 조직의 규칙을 따르되 본인이 규칙을 정해야 한다면 위와 같은 사항들을 고려해보도록 하자.

 

출처

https://docs.spring.io/spring-framework/reference/6.0/web/webmvc/mvc-controller/ann-methods/responsebody.html

https://docs.spring.io/spring-framework/reference/6.0/web/webmvc/mvc-controller/ann-methods/responseentity.html#page-title

https://yeonyeon.tistory.com/257

https://www.youtube.com/watch?v=fCgU_VFv33M&list=WL&index=6

블로그의 정보

eel.log

eelseungmin

활동하기