Handler Method : ResponseEntity

2024. 10. 9. 16:58Spring Framework/Web on Servlet Stack


ResponseEntity는 HTTP 응답 본문, 상태 코드, 그리고 응답 헤더를 함께 처리할 수 있는 스프링의 강력한 기능입니다. @ResponseBody는 주로 응답 본문만 직렬화하여 반환하는 반면, ResponseEntity는 상태 코드와 헤더를 포함한 더 많은 정보를 제어할 수 있습니다.

기본 개념

  • ResponseEntityHTTP 응답의 상태 코드헤더를 포함하여 응답을 더 세부적으로 제어할 수 있습니다. 예를 들어, 응답의 HTTP 상태 코드, ETag(헤더), 응답 본문 등을 함께 설정할 수 있습니다.
  • 본문: 응답의 내용, 보통 JSON, XML, 문자열 등의 데이터를 포함할 수 있습니다.
  • 헤더: 응답에 포함될 다양한 HTTP 헤더를 설정할 수 있습니다. 예를 들어, ETag, Cache-Control 등을 설정할 수 있습니다.
  • 상태 코드: 200 OK, 404 Not Found, 500 Internal Server Error와 같은 HTTP 상태 코드를 지정할 수 있습니다.

ResponseEntity 사용 예시

1. 문자열 응답과 상태 코드, 헤더 설정

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExampleController {

    @GetMapping("/something")
    public ResponseEntity<String> handle() {
        String body = "This is the response body";
        String etag = "12345";  // 예를 들어 ETag 값

        // 200 OK 상태와 함께 응답 본문과 ETag 헤더 반환
        return ResponseEntity.ok()
                             .eTag(etag)
                             .body(body);
    }
}

코드 설명:

  • ResponseEntity.ok(): 200 OK 상태 코드를 설정합니다.
  • eTag(etag): 응답 헤더에 ETag 값을 추가합니다.
  • body(body): 응답 본문으로 문자열을 설정합니다. 이 경우 "This is the response body"가 클라이언트에 전송됩니다.

2. JSON 객체 응답 예시

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AccountController {

    @GetMapping("/accounts/{id}")
    public ResponseEntity<Account> getAccount(@PathVariable String id) {
        Account account = new Account(id, "John Doe", 1000);

        // 200 OK 상태와 함께 Account 객체를 JSON으로 반환
        return ResponseEntity.ok(account);
    }
}

코드 설명:

  • ResponseEntity.ok(account): Account 객체를 JSON으로 변환하여 반환합니다. HttpMessageConverter가 이를 JSON으로 직렬화하여 클라이언트로 전달합니다.

파일 콘텐츠 응답

파일을 응답으로 전송할 때는 Resource 객체를 ResponseEntity와 함께 사용하여 InputStream을 클라이언트에 전달할 수 있습니다.

파일 다운로드 예시

import org.springframework.core.io.Resource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FileController {

    @GetMapping("/download")
    public ResponseEntity<Resource> downloadFile() {
        // 클래스 경로에 있는 파일을 리소스로 반환
        Resource file = new ClassPathResource("files/example.txt");

        // 파일 다운로드 응답 설정
        return ResponseEntity.ok()
                             .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=example.txt")
                             .contentType(MediaType.TEXT_PLAIN)
                             .body(file);
    }
}

코드 설명:

  • Resource: 파일을 Resource 객체로 반환하여 응답 본문에 스트리밍합니다.
  • CONTENT_DISPOSITION: 이 헤더를 통해 클라이언트가 파일을 다운로드하도록 설정합니다. 파일 이름을 example.txt로 지정했습니다.
  • contentType(): 응답의 콘텐츠 타입을 text/plain으로 설정합니다.

비동기 응답 (Reactive 스택에서 ResponseEntity 사용)

Spring WebFlux와 같은 비동기 스택에서는 Mono 또는 Flux와 함께 ResponseEntity를 사용하여 비동기 응답을 처리할 수 있습니다.

WebFlux에서 Mono<ResponseEntity> 사용 예시

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
public class ReactiveAccountController {

    @GetMapping("/accounts/{id}")
    public Mono<ResponseEntity<Account>> getAccount(@PathVariable String id) {
        Account account = new Account(id, "John Doe", 1000);

        // 비동기적으로 ResponseEntity와 Account 객체 반환
        return Mono.just(ResponseEntity.ok(account));
    }
}

코드 설명:

  • Mono<ResponseEntity>: 비동기적으로 Account 객체와 상태 코드를 포함한 ResponseEntity를 반환합니다.
  • Mono.just(): 비동기 응답을 반환하며, 클라이언트는 응답을 기다렸다가 Account 객체와 함께 응답을 받게 됩니다.

비동기 응답에서 상태 코드와 본문을 동시에 처리

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
public class ReactiveAccountController {

    @GetMapping("/accounts/{id}")
    public Mono<ResponseEntity<Account>> getAccount(@PathVariable String id) {
        return findAccountById(id)
                .map(account -> ResponseEntity.ok(account))  // 200 OK와 함께 Account 반환
                .defaultIfEmpty(ResponseEntity.notFound().build());  // 없을 경우 404 반환
    }

    private Mono<Account> findAccountById(String id) {
        // 가상의 비동기 데이터베이스 조회
        Account account = new Account(id, "John Doe", 1000);
        return Mono.just(account);
    }
}

코드 설명:

  • map(account -> ResponseEntity.ok(account)): 비동기적으로 데이터를 조회하여 200 OK 응답과 함께 Account 객체를 반환합니다.
  • defaultIfEmpty(): 데이터가 없을 경우 404 Not Found 응답을 반환합니다.

요약

  • ResponseEntityHTTP 상태 코드, 응답 본문, 헤더를 모두 제어할 수 있는 객체입니다. 이를 통해 클라이언트에게 더 세부적인 응답을 보낼 수 있습니다.
  • ResponseEntity.ok(): 주로 200 OK 상태 코드를 반환하며, 본문과 헤더를 함께 설정할 수 있습니다.
  • 파일 응답: Resource 객체를 사용하여 파일을 클라이언트로 스트리밍할 수 있으며, CONTENT_DISPOSITION 헤더를 설정해 파일 다운로드를 유도할 수 있습니다.
  • Reactive 스택에서는 MonoResponseEntity를 결합하여 비동기적으로 응답을 처리할 수 있습니다.

이 방식은 클라이언트에게 상태 코드와 헤더를 포함한 응답을 보낼 수 있는 매우 유연한 방법으로, RESTful API 설계에서 주로 사용됩니다.


참고 : [https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/responseentity.html]

'Spring Framework > Web on Servlet Stack' 카테고리의 다른 글

Model  (0) 2024.10.09
Handler Method : Jackson JSON  (0) 2024.10.09
Handler Method : @ResponseBody  (0) 2024.10.09
Handler Method : HttpEntity  (0) 2024.10.09
Handler Mapping : @RequestBody  (0) 2024.10.09