Open zuminzi opened 1 year ago
정의 및 특징:
HttpEntity
클래스를 제공한다.HttpEntity
클래스는 HTTP 요청 또는 응답에 해당하는 헤더와 바디를 포함하는 클래스다.따라서 이 클래스는 다음과 같은 생성자와 필드를 갖는다.
public class HttpEntity<T> {
// 바디나 헤더가 없는 비어있는 객체
public static final HttpEntity<?> EMPTY = new HttpEntity<>();
private final HttpHeaders headers;
@Nullable
private final T body;
protected HttpEntity() {
this(null, null);
}
public HttpEntity(T body) {
this(body, null);
}
public HttpEntity(MultiValueMap<String, String> headers) {
this(null, headers);
}
public HttpEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers) {
this.body = body;
this.headers = HttpHeaders.readOnlyHttpHeaders(headers != null ? headers : new HttpHeaders());
}
}
HttpEntity
클래스를 상속받아 구현한 클래스가 RequestEntity
, ResponseEntity
클래스이다.HttpRequest
에 대한 응답 데이터를 포함하는 클래스이다.사용 사례:
RestTemplate
:
예시 1
ResponseEntity<String> entity = template.getForEntity("https://example.com", String.class);
String body = entity.getBody();
MediaType contentType = entity.getHeaders().getContentType();
HttpStatus statusCode = entity.getStatusCode();
RestTemplate
클래스에서 getForEntity()
와 exchange()
메서드의 응답 객체로도 사용하고 있다.
getForEntity()
: 주어진 URL 주소로 GET 요청을 보내고, ResponseEntity를 반환한다.exchange()
: getForEntity()
보다 더 유연하게 HTTP 요청을 조작할 수 잇는 메서드로, 요청 메서드(GET, POST 등)와 함께 URL을 지정하여 HTTP 요청을 보내고, ResponseEntity를 반환한다.예시 2 - 프로젝트 코드
@Service
@RequiredArgsConstructor
public class KakaoMapSearchApi {
public String[] searchByRoadAddressName(String roadAddressName, Double curLnt, Double curLat) {
// 1. API 호출을 위한 요청 설정
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "KakaoAK " + API_KEY);
HttpEntity<String> entity = new HttpEntity<>(headers);
String apiURL = "https://dapi.kakao.com/v2/local/search/keyword.JSON?"
+ "query=" + roadAddressName + DEFAULT_QUERY_WORD
+ "&x=" + curLnt
+ "&y=" + curLat;
// 2. API 호출하여 응답 받기
JsonNode result = restTemplate.exchange(apiURL, HttpMethod.GET, entity, JsonNode.class)
.getBody()
.get("documents");
..
}
HttpEntity
는 HttpHeaders
를 통해 HTTP 요청의 헤더를 설정하고, 이를 RestTemplate
의 exchange()
메서드를 호출할 때 사용하여 API 호출에 필요한 정보들을 담고 있다.Spring MVC의 @Controller
메서드:
예시 1
// 생성자 사용
@RequestMapping("/handle")
public ResponseEntity<String> handle() {
URI location = ...;
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setLocation(location);
responseHeaders.set("MyResponseHeader", "MyValue");
return new ResponseEntity<String>("MyBody", responseHeaders, HttpStatus.CREATED);
}
// 빌더 패턴 사용 (가독성 측면에서 권장)
@RequestMapping("/handle")
public ResponseEntity<String> handle() {
URI location = ...;
return ResponseEntity.created(location)
.header("MyResponseHeader", "MyValue")
.body("MyBody");
}
ResponseEntity
객체 자체를 반환 값으로 두는 것이다.예시 2 - 프로젝트 코드
@RequestMapping("/favorites")
@RestController
@RequiredArgsConstructor
@Slf4j
public class FavoriteController {
private final FavoriteService favoriteService;
private final ShopService shopService;
@PreAuthorize("isAuthenticated()")
@GetMapping(value = "")
public ResponseEntity<List<FavoriteResponse>> showFavoritesList(@AuthenticationPrincipal MemberContext memberContext,
@RequestParam @NotNull Double userLat,
@RequestParam @NotNull Double userLng
) {
List<FavoriteResponse> favoriteResponses = favoriteService.getFavoritesList(memberContext.getId(), userLat, userLng);
return ResponseEntity.ok(favoriteResponses);
}
@ResponseStatus
를 추가로 붙여야 설정이 가능하다.사용 사례:
REST API를 제공하는 @RestController
@Slf4j
@RestController
public class ResponseBodyController {
@ResponseStatus(HttpStatus.OK)
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return helloData;
}
}
@RestController
를 사용하면 자동으로 모든 핸들러 메서드에 @ResponseBody
가 적용된다.ResponseEntity
와 @ResponseBody
의 비교ResponseEntity
(HttpEntity
)와 @ResponseBody
모두 핸들러 메서드(혹은 controller)가 데이터를 반환할 때 필요 시 HttpMessageConverter
에 의해 직렬화(객체 → 반환 타입)되는 것은 동일하다.@ResponseBody
는 어노테이션 추가만으로 간략한 HTTP 응답 바디 작성 기능을 지원하는 반면, ResponseEntity
는 보다 다양한 HTTP 옵션을 설정할 수 있기 때문에 더 유연하다.ResponseEntity
를 사용하는 것이 유용하다.
ResponseEntity + @Controller
와 ResponseEntity + @RestController
의 비교ResponseEntity
는 전체 응답을 나타내므로 ResponseEntity
사용 시 @ResponseBody
를 명시할 필요는 없다.@ResponseBody
를 포함한 @RestController
대신 @Controller
를 사용해도 JSON, XML 등의 객체 반환이 정상적으로 이루어진다.@RestController
는 @ResponseBody
와 @Controller
를 결합한 스테레오타입 주석이지만, 그 이상으로 컨트롤러에 더 많은 의미를 부여하고 프레임워크의 향후 릴리스에서 추가 의미를 전달할 수도 있다고 한다.@Controller
를, 순수한 REST API를 제공하는 웹 애플리케이션에서는 @RestController
를 사용하고, 필요에 따라 ResponseEntity
를 결합하는 것이 적합하다고 생각한다.
문제
HTTP API나 REST API를 제공할 때, HTML 대신 JSON, XML, TEXT와 같은 형식의 데이터를 HTTP 메시지 body에 담아 보낸다. Spring에서는 이러한 응답을
ResponseEntity
와@ResponseBody
로 편리하게 작성할 수 있음을 배웠다.그렇다면
ResponseEntity
와@ResponseBody
의 차이점은 무엇인지 정리해보자.관련 섹션