We will find a way, we always have.

-interstellar

Spring

[Spring] @ResponseBody vs ResponseEntity

Redddy 2024. 4. 21. 15:40

서론

스프링을 사용할 때 컨트롤러에서 직렬화할 데이터를 반환할 때 @ResponseBody를 사용할 지 ResponseEntity를 사용할 지 토론이 이어졌다.

무엇을 사용하는게 좋을 지 살펴보자.

본론

@ResponseBody 

@ResponseBody는 스프링 버전 3.0에 등장한 녀석이다. 이 녀석을 사용한다면 반환값을 HttpMessageConverter를 통해 응답 바디로 직렬화할 수 있다.

 

 

 

 

위 코드는 스프링 @ResponseBody의 코드이고 아래는 @ResponseBody 사용 예시이다.

 

@ResponseBody 사용방법

 

/reservations 로 GET 요청이 올 때 동작하는 메서드인데 @ResponseBody 사용방법이라고 해놓고 @ResponseBody 애노테이션은 보이지도 않는다.

 

무슨일인걸까??!!!

 

정답은 @RestController에 있다.

 

 

@RestController 애노테이션은 @Controller와 @ResponseBody를 합쳐놓은 애노테이션이다. 때문에 클래스 레벨에 @RestController를 붙여준다면 @ResponseBody를 생략해도 된다!

 

덕분에 @RestController를 사용한다면 아주 깔쌈하게 데이터를 직렬화할 수 있다. 참고로 @RestController는 스프링 버전 4.0에 등장하였다.

 

ResponseEntity

ResponseEntity는 @ResponseBody 보다는 조금 늦은 버전 3.0.2에 등장하였다. 

 

 

 

ResponseEntity는 Http 상태 코드를 가지고 있고, Http 헤더와 바디를 가지고 있는 HttpEntity(스프링 버전 3.0.2에 등장)를 상속하는 구조로 되어 있다.

 

ResponseEntity 사용방법


Http 상태 코드를 변경하고 싶다거나 헤더를 수정하고 싶다면 ResponseEntity를 사용하면 된다. 

 

정리해보자면 객체를 json으로 직렬화한다는 점에서는 동일하지만 ResponseEntity를 사용한다면 HTTP 헤더, 상태 코드를 수정할 수 있다는 장점이 있다. 반면 @ResponseBody와 @RestController를 사용한다면 보다 간결하게 직렬화할 수 있다.

물론 @ResponseBody를 사용한다고 해서 HTTP 상태코드를 변경하지 못하는 것은 아니다. 기본 값이 200이고, @ResponseStatus 애노테이션을 사용하여 HTTP 상태코드를 변경할 수 있다. 

 

Like this

 

하지만 동적으로 상태코드를 변경할 수 없다는 단점이 있다. 예를 들어 예약을 삭제하는 메서드가 있다. 이 메서드의 파라미터로 id가 넘어오는데 존재하는 id라면 204를 반환하고, 존재하지 않는 id라면 404를 반환해야 하는 상황이 있다고 가정하자. @ResponseStatus는 이렇게 상황에 따라 상태 코드 변경이 불가하고 한 메서드에 하나의 상태 코드만 반환할 수 있다.

 

들었던 의문점이 있다. HTTP 상태 코드를 수정하거나 헤더를 수정할 일이 없다면 불필요하게 ResponseEntity로 객체를 매핑할 필요 없이 그냥 @ReseponseBody를 사용하는 게 효율적이라고 생각했다. 하지만 간결하게 @ResponseBody를 사용해도 될 상황인데도 대부분이 ResponseEntity를 사용하고 있었다. 여기서 말하는 대부분은 우테코 팀프로젝트 코드들이다.

 

HTTP 상태 코드를 수정할 일도 없고, 헤더를 수정하는 경우가 아니여도 99.9% ResponseEntity를 사용하고 있었다. 딱 하나 ResponseBody를 사용한 코드를 찾았는데 ping pong 테스트 용이였다. ㅎ

 

 

 

결론

Simple is best라면 @ResponseBody를 사용하고, 변화에 유연하게 대처하고 싶다면 ResponseEntity를 사용하면 될 거 같다. 아니면 팀 컨벤션에 맞추자.

 

 

번외1

ResponseEntity를 사용하여 HTTP 상태 코드를 변경하고 또 @ResponseStatus를 사용하여 상태 코드를 변경한다면 누구의 상태 코드를 반환할까 궁금해서 실험해보았는데 결과는 ResponseEntity의 상태 코드를 따랐다.

 

 

번외2

ResponseEntity를 사용하지 않고 헤더의 값을 설정하는 방법이 없을까 엄청 찾다가 과거에서 답을 얻었다.

방법은 서블릿을 사용하는 것이다. HttpServletResponse를 파라미터로 받은다음 헤더를 설정해주면 된다!