인턴

[Spring] @ResponseEntity<T> vs @ResponseBody

jonghyeon6084 2025. 7. 7. 23:35
728x90

spring boot 프로젝트 과제 중 고민이 되던 부분이 바로 @ResponseBody와 ResponseEntity<T> 중 무엇을 사용할지였다.

찾아보던 중 좋은 블로그들이 있어 참고하여 작성해본다.(https://ksh-coding.tistory.com/89)(https://myeongdev.tistory.com/37)

 

1. Spring HTTP 응답 메시지 바디에 메시지를 설정하는 방법

HTTP 응답 메세지 바디에 메세지를 설정하는 방법은 다음과 같이 2가지가 존재한다.

  • 반환 시 ResponseEntity<T> 사용
  • @ResponseBody + 반환 객체 사용

1. ResponseEntity<T> 예제

@PostMapping("/plays")
public ResponseEntity<RaceResultResponse> registerRaceResult(@RequestBody final GameInfoRequest gameInfoRequest) {
    ...
}

2. @ResponseBody + 반환 객체 사용 예제

@PostMapping("/plays")
@ResponseBody
public RaceResultResponse registerRaceResult(@RequestBody final GameInfoRequest gameInfoRequest) {
    ...
}

2. ResponseEntity<T> vs @ResponseBody의 차이

 

두 가지 방법의 차이는 뭘까??

바로 ResponseEntity<T>를 사용하면 DTO 객체 반환 시보다 설정할 수 있는 부분이 더 추가된다는 점이다.

 

자세히 살펴보기 위해 ResponseEntity<T> 클래스를 살펴보자.

 

2-1. ResponseEntity<T> 클래스 (feat. HttpEntity<T>)

* ResponseEntity<T> // HTTPEntity의 확장이며, HttpStatus의 상태코그를 더 할 수 있음
public class ResponseEntity<T> extends HttpEntity<T> { 
		
    private final Object status;

    ... 
}

---
* HttpEntity<T> // header와 body로 이뤄진 HTTP request, response entity
public class HttpEntity<T> {

    private final HttpHeaders headers;

    @Nullable
    private final T body;
}

 

ResponseEntity<T>는 HttpEntity<T>를 상속하기 때문에, HttpStatus와 HttpHeader, HttpBody를 설정하여 HTTP 응답을 보낼 수 있다.

 

이와 달리, @ResponseBody와 객체를 사용해서는 위의 옵션을 설정하기 힘들다.

HTTP 상태 코드는 @ResponseStatus를 통해 설정해줄 수 있지만, 헤더 부분는 설정하기 힘들다.

 

2-2. ResponseEntity<T> vs @ResponseBody의 차이 요약

 

@ResponseBody

  • 장점
    • 어노테이션 추가만으로 간단하게 HTTP 응답을 만들 수 있다.
  • 단점
    • HTTP 헤더, 상태 코드 같은 옵션에 대한 유연성이 떨어진다.
      • HTTP 헤더는 설정하기가 어렵다.
      • 상태 코드는 @ResponseStatus를 추가로 붙여야 설정이 가능하다.

ResponseEntity<T>

  • 장점
    • HTTP 옵션에 대해 유연이다.(HTTP 규약을 지킨다.)
      • HttpEntity를 상속 받고 있기 때문에 여러 HTTP 옵션을 설정할 수 있다.
      • ResponseEntity 빌더를 통해서 여러 HTTP 옵션을 설정할 수 있다.
  • 단점
    • @ResponseBody 보다는 작성할 코드가 많다.

3. 그렇다면, 둘 중에 무엇을 사용할까??

ResponseEntity<T>의 단점은 @ResponseBody보다 작성할 코드가 많다는 것이었다.

 

하지만 ResponseEntity<T> 대신 @ResponseBody를 사용해도 눈에 띌만큼 생산성이 개선되지는 않는다고 느껴진다.

 

또, HTTP 옵션을 사용하지 않아도 되는 곳이라서 @ResponseBody를 사용했을 때도 추후에 HTTP 옵션을 설정해야 하도록 요구사링이 변경된다면 결국 해당 메소드도 변경된다는 단점이 있다.

 

그래서 HTTP 옵션을 지정해서 사용할 수 있는 ResponseEntity<T>를 사용하는 것이 훨씬 좋을 거 같다는 결론이 나왔다.

 

!!!! ResponseEntity를 사용할 때는 생성자 대신 빌더를 사용하자.

 

ResponseEntity 사용 시 생성자를 사용하면 HTTP 상태 코드를 하드 코딩으로 지정할 수 있기 때문에 잘못된 상태 코드를 넣을 수 있다.

물론 HttpStatus에 없는 코드를 넣게 되면 에러가 발생하긴 하지만 컴파일 타임이 아닌 런타임에 발생하기 때문에 좋지 않다.

따라서, ResponseEntity에 있는 빌더를 사용하면 이를 방지하고 가독성도 좋은 코드를 얻을 수 있다.

 

* 생성자 사용
// OK인 200을 2000으로 오타 -> 런타임 에러
return new ResponseEntity<GameResponse>(gameResponse, headers, HttpStatus.valueOf(2000));

* 빌더 사용
return ResponseEntity.ok()
                    .headers(headers)
                    .body(gameResponse);