ResponseEntity 를 사용한 REST API 응답 데이터 생성기(Feat.builder 패턴)

HeoSeungYeon·2022년 1월 30일
2

Record the project

목록 보기
3/3
post-thumbnail

🗯️ 문제 : RESTful API 의 응답 데이터를 어떻게 잘 담을까?


RESTful API을 준수하기 위해선 다음 항목들을 알고 실천해야 합니다.

  • Uniform (유니폼 인터페이스)
  • Stateless (무상태성)
  • Cacheable (캐시 가능)
  • Self-descriptiveness (자체 표현 구조)
  • Client - Server 구조
  • 계층형 구조

위 항목 중 이번 시간에 다뤄볼 내용은 Self-descriptiveness (자체 표현 구조) 인데요,

클라이언트 - 서버 사이에서 오고가는 요청 메세지를 보고 해당 메세지가

  • 어떤 행위를 하고
  • 어떤 리소스를 요구하고(반환하고)
  • 해당 요청에 대한 응답이 어떤 결과를 가졌는지

를 바로 알 수 있어야 위 항목을 준수한다고 볼 수 있습니다.

1️⃣ 어떤 행위를 하고?

먼저 첫번째 사항에 대해선 HTTP Method를 적절히 사용해야 합니다. 예를 들어 4가지 Method를 통해 CRUD에 해당하는 행위를 표현할 수 있는데요.

  • Post : 리소스 생성
  • Get : 리소스 조회
  • Put : 리소스 수정
  • Delete : 리소스 삭제

클라이언트와 서버 간의 위 행위에 대한 정의가 API 에 잘 담겨있을수록 더욱 Self-descrptiveness 에 다가갈 수 있습니다.

2️⃣ 어떤 리소스를 요구하고(반환하고)

두번째 사항을 준수하기 위해선 위에서 정의한 HTTP Method에 맞는 Best Practice를 찾아볼 필요가 있습니다. HTTP Method(행위)에 따라

  • URI 는 어떤 형식으로 이루어져야 하는지
    • path variable 로 어떤 데이터를 주고 받을까
    • query parameter 로 어떤 데이터를 주고 받을까
  • HTTP Body에 데이터를 담을 것인지, 어떻게 담을 것인지

에 대한 내용을 알아보고 이를 준수했을 때, 좀 더 통일된 HTTP API를 작성할 수 있습니다.

3️⃣ 해당 요청에 대한 응답이 어떤 결과를 가졌는지

세번째 사항은 HTTP 상태 코드에 관한 내용입니다. 요청에 대한 결과가 어떻게 됐는지 클라이언트가 아는 것도 매우 중요합니다. 이를 표현해줄 수 있는 방법은 HTTP Status Code를 HTTP STATUS CODE 문서 를 보고 맞는 결과의 종류에 맞게 설정할 수 있습니다.

백엔드 서버를 개발하는 프로젝트를 진행하면서, RESTful API 답게 응답 데이터(json(DTO), 상태코드)를 편리하게 생성하여 전송할 수 있는 방법이 궁금해졌습니다. ( >> 밑에서 공개 )

🔥 해결 방법 : ResponseEntity로 쉽게 응답해보자!


어떻게 하면 상태코드도 담고 DTO도 담고 간결하게 클라이언트로 응답 데이터를 보낼 수 있을까요?

spring에선 위 기능을 ResponseEntity.class를 통해 제공합니다.

public class ResponseEntity<T> extends HttpEntity<T> {

	private final Object status;

	...
}

먼저 ResponseEntity는 HttpEntity를 상속하는 클래스입니다. 따로 1️⃣ status라는 필드를 가지며 우리는 상태코드 값을 설정할 수 있습니다. 그럼 상속된 클래스인 HttpEntity는 어떤 필드를 가질까요?

public class HttpEntity<T> {

	/**
	  * The empty {@codeHttpEntity}, with no body or headers.
	  */
	public static final HttpEntity<?> EMPTY = new HttpEntity<>();
	
	
	private final HttpHeaders headers;
	
	@Nullable
	private final T body;

...
}

HttpEntity는 2️⃣header와  3️⃣body를 필드로 갖고 있습니다.

따라서 우리는 ResponseEntity status, header, body 를 전달하고 생성하여 응답 데이터를 클라이언트로 보낼 수 있습니다.

ResponseEntity 적용 해보기


public ResponseEntity<XXXDto> controllerMethod(@RequestBody body){

	...

	return new ResponseEntity(xxxDto, header, HttpStatus.ok);
}

최초에 ResponseEntity를 적용했을 때 new 생성자를 통해 클라이언트로 return 해주었습니다.

그러고 코드리뷰를 하면서, ResponseEntity를 new 생성자 대신 Buider 패턴을 통해 생성하면 더 유용하게 사용할 수 있다는 점을 알게 되었습니다. 먼저 아래와 같은 Builder 패턴 자체의 장점들을 고스란히 가져갈 수 있습니다.

  • 유연하게 값을 설정할 수 있음.
  • 가독성 측면에서 좋다.

제일 좋았던 점은 2번째 항목인(가독성 측면)도 얼추 포함되는 내용인데 ResponseEntity의 생성자가 갖는 매개변수 순서를 굳이 외울 필요가 없다는 점입니다.

따라서 위 코드와 같이 작성된 부분을 builder 패턴을 사용하는 방식으로 리팩토링을 진행하였습니다.

public ResponseEntity<XXXDto> controllerMethod(@RequestBody body){

	...

	return ResponseEntity.ok(marketService.getMarketById(marketId));
}

+추가)

ResponseEntity 내부 코드를 보게 되면


public static BodyBuilder ok() {
	return status(HttpStatus.OK);
}

public static<T> ResponseEntity<T> ok(@Nullable T body) {
	return ok().body(body);

자주 사용되는 Http 상태 코드를 이름으로 갖는 메서드가 선언되어 있습니다.

그래서 자주 사용되는 Http 상태 코드를 사용할 때에는, 위 메서드를 통해 Http 상태 코드를 정해줄 수 있고, builder 패턴을 통해 body나 header 값도 정할 수 있습니다.

📖 참고문서


[Spring Boot] ResponseEntity란 무엇인가?

ResponseEntity - Spring Boot에서 Response를 만들자

[Spring] ResponseEntity는 왜 쓰는 것이며 어떻게 쓰는걸까?

ResponseEntity란?

[Spring MVC] @ResponseBody와 ResponseEntity

profile
안녕하세요~! 백엔드 개발자 허승연 입니다 :)

0개의 댓글