개발기록
[SpringBoot] ResponseEntity<> ? 본문
Restful API를 만드는 이유는?
메시지 기반, XML, JSON과 같은 Client에서 바로 객체로 치환 가능한 형태의 데이터 통신을 하는 AJAX를 하기 위해서라고 말할 수 있다. 하지만 Restful APIs를 만드는 가장 큰 이유는 Client Side가 PC에 국한되지 않고 모바일, PC, 어플리케이션 등 플랫폼에 제약을 두지 않는 것을 목표로 하기 때문이다.
즉, 클라이언트 플랫폼이 다양화되기 시작하면서 그에 맞춰 일일이 Server 측면에서 작업하기가 점점 비효율적으로 되면서
메시지 기반, XML, JSON과 같은 Client에서 바로 객체로 치환 가능한 형태의 데이터 통신을 지향하게 되면서 Server와 Client의 역할을 분리하게 되었다.
이런 변화를 겪으면서 필요해진 것은 HTTP의 표준 규약을 지켜서 API를 만드는 것.
이 Restful APIs를 개발하다보면 HTTP의 Response 규약을 지키지 않고 API의 리턴값을 JSON 객체로 바로 응답하는 경우를 많이 확인할 수 있는데 그것은 옳지 않다.
Client Side가 정형화되어있지 않은 환경에서 개발속도를 저하하는 가장 큰 이유는 표준을 지키지 않아서다. 그 표준을 지키지 않게 되었을 때 발생하는 가장 큰 이슈는 HTTPStatus 코드를 제대로 응답하지 않게되는 것이고 이런 경우 클라이언트에서는 별도의 방어코드를 짜 넣는 수고가 발생하고 이런 작업들이 많아질수록 프로젝트의 속도를 저하시키는 요소가 된다.
내 개인 프로젝트 코드의 RestController 리턴값의 타입은 모두 Object 값이였다.
하지만, 실제 서비스에서 제공하는 API는 반환하는 리소스에 Value만 있지 않다는 것을 모두 알고 있을 것이다.
당장 생각나는 것으로는 상태코드, 응답 메시지 등이 포함될 수 있겠다. 그럴때 사용되는 것이 ResponseEntity.Class 이다.
ResponseEntity는 HttpEntity를 상속받음으로써 HttpHeader와 body를 가질 수 있다.

오늘은 위와 같은 장황한 이유 때문에 Spring에서 제공하는 ResponseEntity 객체를 이용해 규약에 맞는 HTTP Response를 만들어보고자 한다.
package com.danwoo.springbootdemo.controller;
import com.danwoo.springbootdemo.model.ApiResponseMessage;
import com.danwoo.springbootdemo.model.StatusEnum;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
@RestController
public class TestController {
@RequestMapping(value ="/test",method = RequestMethod.GET)
public ResponseEntity<ApiResponseMessage> hello(){
ApiResponseMessage message = new ApiResponseMessage();
HttpHeaders headers = new HttpHeaders();
Map<String, String> map = new HashMap<>();
map.put("value1","test data");
headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
message.setStatus(StatusEnum.OK);
message.setMessage("성공 코드");
message.setData(map);
return new ResponseEntity<ApiResponseMessage>(message,HttpStatus.OK);
}
}
Api호출이 가능한 구조의 http://localhost:8080/test의 호출구조를 가진 api를 설계하였다.
@RestController는 별도의 뷰를 제공하지 않는 형태로 서비스를 실행하기 때문에, 때로는 결과 데이터가 예외적인 상황에서 문제가 발생할 수 있다. 웹의 경우는 HTTP 상태(status) 코드가 이러한 정보를 나타내는데 사용한다.
주로 많이 사용되는 상태 코드는 아래와 같다.

스프링에서 제공하는 ResponseEntitiy<T>는 개발자가 직접 결과 데이터 + HTTP의 상태 코드를 제어할 수 있다.
package com.danwoo.springbootdemo.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.http.HttpHeaders;
@Getter
@Setter
@ToString
public class ApiResponseMessage {
// HttpStatus
private StatusEnum status;
private Object data;
// Http Default Message
private String message;
// Error Message to USER
private String errorMessage;
// Error Code
private String errorCode;
public ApiResponseMessage() {
}
public ApiResponseMessage(StatusEnum status, Object data, String message, String errorMessage, String errorCode) {
this.status = status;
this.data = data;
this.message = message;
this.errorMessage = errorMessage;
this.errorCode = errorCode;
}
}
package com.danwoo.springbootdemo.model;
public enum StatusEnum {
OK(200, "OK"),
BAD_REQUEST(400, "BAD_REQUEST"),
NOT_FOUND(404, "NOT_FOUND"),
INTERNAL_SERER_ERROR(500, "INTERNAL_SERVER_ERROR");
int statusCode;
String code;
StatusEnum(int statusCode, String code) {
this.statusCode = statusCode;
this.code = code;
}
}
StatusEnum 클래스에 여러가지 다뤄야할 Http 상태코드를 관리하면서 enum을 관리하면 개발자하면서 응답데이터를
더 자세하게 관리할 수 있을 것이다.
'Spring' 카테고리의 다른 글
| [Springboot] Controller, RestController는 뭐가 다른가요? 응답이 어떻게 다른가요? (0) | 2021.06.01 |
|---|---|
| [Springboot] Bean Container란 뭔가요? (0) | 2021.06.01 |
| [SpringBoot] Spring Security (0) | 2021.05.25 |
| [SpringBoot] Auth2.0 (0) | 2021.05.25 |
| [SpringBoot] DI, IOC (0) | 2021.05.20 |