ResponseEntity란?

ResponseEntityHttpEntity의 확장 클래스로써 HttpStatus 상태 코드를 추가한 전체 HTTP 응답(상태 코드, 헤더 및 본문)을 표현하는 클래스입니다. 

ResponseEntity를 어디에 사용할 수 있나요?

  • ResponseEntity 클래스는 주로 @Controller 또는 @RestController 애너테이션이 붙은 Controller 클래스의 핸들러 메서드(Handler Method)에서 요청 처리에 대한 응답을 구성하는데 사용됩니다. Used in RestTemplate as well as in @Controller methods.
  • 그리고 RestTemplate으로 외부의 API 통신에 대한 응답을 전달 받아서 처리할 경우, 역시 ResponseEntity를 사용합니다.

ResponseEntity를 어떻게 사용해야 할까요?

가장 일반적인 방식

가장 일반적인 방식은 [코드 1-1]과 같이 new로 ResponseEntity 객체를 생성하는 방식입니다.

1
2
3
4
5
6
7
8
9
10
11
@RestController
@RequestMapping("/v1/coffees")
public class ResponseEntityExample01 {
    @PostMapping
    public ResponseEntity postCoffee(Coffee coffee) {
 
        // coffee 정보 저장
        
        return new ResponseEntity<>(coffee, HttpStatus.CREATED);
    }
}
[코드 1-1]

 

[코드 1-1]은 ResponseEntity 객체를 생성하면서 응답의 body 데이터와 HttpStatus의 상태를 전달하고 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping("/v1/coffees")
public class ResponseEntityExample01 {
    @GetMapping("/{coffee-id}")
    public ResponseEntity getCoffee(@PathVariable("coffee-id"long coffeeId) {
 
        if (coffeeId < 0) {
            return new ResponseEntity<>(
                    "coffeeId should be greater than 0",
                    HttpStatus.BAD_REQUEST);
        }
 
        return new ResponseEntity<>(new Coffee(), HttpStatus.OK);
    }
}
[코드 1-2]

 

코드 1-2는 coffeeId에 따라서 HttpStatus 상태를 동적으로 지정하는 예입니다.

 

코드 1-2는 요청 데이터에 대한 유효성 검사가 API 계층에 포함에 직접 포함이 되어 있는데, 이는 좋은 개발 방식은 아닙니다.

Handler Method는 단순히 클라이언트의 요청을 전달 받고, 처리된 응답을 다시 클라이언트에게 전달하는 역할만 하도록 로직을 단순화 하는 것이 좋으며, 유효성 검사나 비즈니스 처리 등의 로직은 별도의 메서드 또는 클래스로 분리를 하는 것이 좋습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
@RequestMapping("/v1/coffees")
public class ResponseEntityExample01 {
    @GetMapping("/{coffee-id}")
    public ResponseEntity getCoffee(@PathVariable("coffee-id"long coffeeId) {
 
        if (coffeeId < 0) {
            return new ResponseEntity<>(
                    "coffeeId should be greater than 0",
                    HttpStatus.BAD_REQUEST);
        }
 
        HttpHeaders headers = new HttpHeaders();
        headers.add("Custom-Header""bar");
        return new ResponseEntity<>(new Coffee(), headers, HttpStatus.OK);
    }
}
[코드 1-3]

만일 ResponseEntity에 Custom header를 포함하고 싶다면 코드 1-3과 같이 HttpHeaders에 원하는 header를 추가하고 ResponseEntity의 생성자로 headers 객체를 전달하면 됩니다.

 

BodyBuilder를 이용한 메서드 체인 방식

ResponseEntity 클래스의 생성자로 body, header, HttpStatus 등을 추가하는 방식과 달리 BodyBuilder 클래스를 이용하면 각각의 항목들을  메서드 체인 방식으로 전달할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
@RestController
@RequestMapping("/v1/coffees")
public class ResponseEntityExample02 {
    @PostMapping
    public ResponseEntity<Coffee> postCoffee(Coffee coffee) {
 
        // coffee 정보 저장
        long savedCoffeeId = 1L;
        return ResponseEntity.created(URI.create("/members/" + savedCoffeeId)).body(coffee);
    }
}
[코드 1-4]

코드 1-4는 코드 1-1을 ResponseEntity.BodyBuilder를 이용해서 메서드 체인 방식으로 ResponseEntity 객체를 리턴해주고 있습니다.

created() 메서드의 경우 URI를 지정할 수 있는데, 이는 새롭게 생성된 리소스에 대한 접근 URI를 Location 헤더 값으로 포함시킴으로써 클라이언트 쪽에서 이 정보를 이용해 해당 리소스에 접근할 수 있도록 해줍니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping("/v1/coffees")
public class ResponseEntityExample02 {
    @GetMapping("/{coffee-id}")
    public ResponseEntity getCoffee(@PathVariable("coffee-id"long coffeeId) {
 
        if (coffeeId < 0) {
            return ResponseEntity.badRequest().body("coffeeId should be greater than 0");
        }
 
        HttpHeaders headers = new HttpHeaders();
        headers.add("Custom-Header""bar");
        return ResponseEntity.ok().headers(headers).body(new Coffee());
    }
}
[코드 1-5]

코드 1-5는 코드 1-3을 BodyBuilder를 이용해서 메서드 체인 방식으로 변경한 코드입니다.

 

ResponseEntity 관련 자료

+ Recent posts

출처: http://large.tistory.com/23 [Large]