REST API
Rest API는 Representational State Transfer (REST) 아키텍처 스타일을 따르는 웹 서비스를 개발하기 위한 기능과 도구를 제공합니다. `REST`는 클라이언트-서버 간의 통신을 위한 아키텍처 스타일로, 자원을 고유한 식별자(URI)로 표현하고 HTTP 프로토콜을 사용하여 자원에 대한 CRUD (Create, Read, Update, Delete) 작업을 수행합니다.
REST API에 대해 공부하거나 예제를 보면 `JSON(JavaScript Object Notation)`을 같이 사용하는 것을 봤을 것입니다. JSON은 데이터를 표현하기 위한 텍스트 기반 형식으로 가볍고, 파싱하기도 쉽고, 사람도 읽기 쉬워서 많이 사용되는 데이터 교환 형식입니다.
- @RestController
해당 컨트롤러가 REST API 엔드포인트를 처리하는 컨트롤러임을 나타냅니다.
이를 통해 컨트롤러의 메서드에서 반환되는 객체가 자동으로 JSON 형식으로 변환되어 클라이언트에 응답됩니다. - @RequestMapping
HTTP 메서드를 매핑하는 어노테이션입니다.
예를 들어, @RequestMapping(value = "/users", method = RequestMethod.GET)와 같이 사용하여 "/users" 엔드포인트에 GET 요청을 처리하는 메서드를 정의할 수 있습니다. - @PathVariable: URL 경로에 포함된 변수를 매핑하는 어노테이션입니다. 예를 들어, @RequestMapping(value = "/users/{id}", method = RequestMethod.GET)와 같이 사용하여 "/users/1"과 같은 요청을 처리하는 메서드에서 id 변수에 해당하는 값을 가져올 수 있습니다.
- @RequestBody: 요청의 본문에 포함된 데이터를 객체로 변환하는 어노테이션입니다. 주로 POST 또는 PUT 요청의 데이터를 객체로 받아서 처리할 때 사용됩니다.
- ResponseEntity: HTTP 응답을 표현하는 클래스로, 상태 코드, 헤더, 본문 데이터 등을 설정하여 클라이언트에게 응답을 보낼 수 있습니다.
REST API 사용법
JSON 설정
dependencies {
// Jackson 라이브러리
implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.4'
}
@EnableWebMVC 추가
@Configuration
@EnableWebMvc
public class WebConfig {
// ...
}
@RestController: @Controller + @ResponseBody
@RestController
@RequestMapping("/users")
public class UserController {
private List<User> users = new ArrayList<>();
@GetMapping("/{id}")
public User getUserById(@PathVariable("id") int id) {
User user = findUserById(id);
if (user != null) {
return user;
} else {
throw new NotFoundException("사용자를 찾을 수 없습니다.");
}
}
@GetMapping(value = "/users", produces = MediaType.APPLICATION_XML_VALUE)
public List<User> getUsers() {
// ...
}
@PostMapping("/insert")
public User insertUser(@RequestBody User user) {
// ...
return user;
}
}
- @RestController
- @RestController = @Controller + `@ResponseBody`
- @RestController를 사용하면 단순 문자열을 반환합니다. 즉, view를 반환하는 것이 아니라 문자열을 반환하고 객체를 반환하는 경우 JSON 형태(문자열)로 반환합니다. 그 이유는 바로 `@ResponseBody` 에 있습니다.
- @ResponseBody
- 메서드의 반환값을 문자열, JSON 형식으로 변환하는 방식입니다. 이때 메서드 수준에 적용할 수도 있지만 클래스 수준에 적용하여 핸들러 메섣스에 일일이 추가하는 번거로움을 줄일 수 있습니다. @RestController를 부여한 경우 자동적으로 @ResponseBody를 클래스 수준에 적용한 것과 마찬가지입니다.
- 어노테이션을 적용하면 기본적으로 모든 핸들러 메서드는 JSON 형식으로 응답하므로, 다른 형식의 응답을 반환하려면 `produces` 속성을 사용해야 합니다.
- @RequestBody
- 브라우저에서 전달된 JSON 데이터를 객체로 변환합니다. @RequestBody는 내부적으로 HttpMessageConverter 타입의 객체들을 이용해 다양한 포맷의 입력 데이터를 변환할 수 있습니다. 주로 JSON 데이터를 원하는 타입의 객체로 변환하는 용도로 사용합니다.
- 브라우저에서 전달된 JSON 데이터를 객체로 변환합니다. @RequestBody는 내부적으로 HttpMessageConverter 타입의 객체들을 이용해 다양한 포맷의 입력 데이터를 변환할 수 있습니다. 주로 JSON 데이터를 원하는 타입의 객체로 변환하는 용도로 사용합니다.
- @PathVariable
- URL 경로에 포함된 변수를 매핑하는 어노테이션입니다.
REST API 프레임워크 구조
프런트 컨트롤러 구조랑 아래 구조를 보면 노란 박스 부분이 다름을 확인할 수 있습니다.
기존 응답 본문을 생성하기 위한 View를 사용하지 않기 때문이며, '요청 본문 해석'과 '응답 본문 해석' 처리를 위해 `HttpMessageConverter` 컴포넌트가 추가되었습니다.
- `DispatcherServlet` 클래스는 클라이언트에서 요청을 받습니다.
- `DispatcherServlet`는 `HandlerMapping` 인터페이스의 `getHandler` 메소드를 호출하고 요청을 처리할 `핸들러(REST API용 컨트롤러)` 객체를 가져옵니다.
- `DispatcherServlet` 클래스는 `HandlerAdapter` 인터페이스의 `handler` 메소드를 호출해서 `핸들러` 객체의 메소드 호출을 의뢰합니다.
- `HandlerAdapter` 인터페이스의 구현 클래스는 `HttpMessageConverter` 메소드를 호출하고 요청 본문 데이터를 리소스 클래스 `객체`로 변환합니다.
- `HandlerAdapter` 인터페이스의 구현 클래스는 `핸들러` 객체에 구현돼 있는 메소드를 호출해서 요청을 처리합니다.
- `HandlerAdapter` 인터페이스의 구현 클래스는 `HttpMessageConverter` 메소드를 호출하고 `핸들러` 객체에서 반환된 리소스 클래스 객체를 응답 본문에 기록합니다.
- `DispatcherServlet` 클래스는 클라이언트에 응답을 반환합니다.
HttpMessageConverter란?
스프링 MVC는 스프링 웹에서 제공하는 HttpMessageConverter를 사용해 요청 본문을 자바 객체로 변환하고 자바 객체를 응답 본문으로 변환합니다.
주고받을 데이터가 일반적인 리소스 형식(JSON, XML 등)이면 스프링이 제공하는 HttpMessageConverter 구현 클래스만으로 충분합니다.
💡의존 라이브러리 필요없는 HttpMessageConverter 구현 클래스
ByteArrayHttpMessageConverter | '본문(임의의 미디어 타입) ↔ 바이트 배열' 변환용 클래스 |
StringHttpMessageConverter | '본문(텍스트 형식 미디어 타입) ↔ String' 변환용 클래스 |
ResourceHttpMessageConverter | '본문(임의의 미디어 타입) ↔ org.springframework.core.io.Resource 구현 클래스' 변환용 클래스 |
AllEncompassingFormHttpMessageConverter | '본문(폼 형식 또는 멀티파트 형식의 미디어 타입) ↔ org.springframework.util.MultiValueMap' 변환용 클래스 |
💡의존 라이브러리 필요한 HttpMessageConverter 구현 클래스
MappingJacksonHttpMessageConverter | '본문(JSON 형식의 미디어 타입) ↔ 임의의 자바빈즈' 변환용 클래스 FasterXML Jackson Databind를 이용 |
GsonHttpMessageConverter | '본문(JSON 형식의 미디어 타입) ↔ 임의의 자바빈즈' 변환용 클래스 Goolge Gson을 이용 |
MappingJackson2XmlHttpMessageConverter | '본문(XML 형식의 미디어 타입) ↔ 임의의 자바빈즈' 변환용 클래스 FasterXML Jackson Databind를 이용 |
Jaxb2RootElementHttpMessageConverter | '본문(XML 형식의 미디어 타입) ↔ 임의의 자바빈즈' 변환용 클래스 자바 표준의 JAXB2를 이용 |
리소스 클래스란?
리소스 클래스란 그냥 리소스를 표현하는 자바 클래스입니다.
Entity와 같은 도메인 객체를 리소스 클래스로 쓰는 경우도 있지만, 도메인 객체와는 별개로 다른 클래스를 만들어서 쓰는 경우도 있습니다. 후자로 설명하겠습니다.
※도메인 객체가 아닌 별개로 클래스 사용하는 이유
도메인 객체 클래스로 그대로 사용할 수도 있지만, 다른 클래스를 만드는 이유는 클라이언트와의 입출력에서 다루는 리소스 정보와 업무 처리에서 다루는 도메인 객체의 정보가 반드시 일치하는 것은 아니기 때문입니다.
리소스 클래스와 도메인 객체 클래스를 미리 분리해 두면 REST API에서 다루는 리소스 정보가 변경되거나 업무 처리에서 다루는 도메인 객체 정보가 변경되더라도 그로 인한 영향 범위를 최소화 할 수 있습니다.
JSON 형식 리소스 예제
{
"login": "resource",
"id": "960828"
"name": "dutmdcjf",
"blog": "http://yeo-computerclass.tistory.com"
}
리소스 클래스 구현 예제
public class UserReousrce implements Serializable{
private statc final long serialVersionUID = -32154684235465L;
private String login;
private Integer id;
private String name;
private String blog;
//생략
}
'Spring Framework' 카테고리의 다른 글
Spring 파일 업로드 (0) | 2022.09.07 |
---|---|
Spring @SessionAttributes, @SessionStatus: Model과 연동을 통한 상태 유지 (0) | 2022.09.07 |
Spring Model 객체: 컨트롤러에서 뷰로 데이터 전달 (0) | 2022.09.06 |
Spring @RequestMapping과 이에 대한 속성 (0) | 2022.09.05 |
Spring 스프링 MVC란? (feat. 프런트 컨트롤러 구조) (0) | 2022.09.05 |