HATEOAS
Hypermedia As the Engine Of Application State
ํ์ฌ ๋ฆฌ์์ค์ ์ฐ๊ด๋(ํธ์ถ ๊ฐ๋ฅํ) ์์ ์ํ ์ ๋ณด๋ฅผ ์ ๊ณต(mapping)
ํด๋ผ์ด์ธํธ๊ฐ ๋ช ์์ ์ผ๋ก ๋งํฌ๋ฅผ ์์ฑํ์ง ์์๋ ์๋ฒ ์ธก์์ ๋ฐ์ ๋งํฌ์ ๋ ํผ๋ฐ์ค๋ฅผ ํตํด ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํ ๋ฐ ์ ์ด๋ฅผ ํํํ ์ ์๋ค.
์ฅ์
- ์์ฒญ URI๊ฐ ๋ณ๊ฒฝ๋๋๋ผ๋ ํด๋ผ์ด์ธํธ์์ ๋์ ์ผ๋ก ์์ฑ๋ URI๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ, ํด๋ผ์ด์ธํธ๊ฐ URI ์์ ์ ๋ฐ๋ฅธ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ์ง ์์๋ ๋๋ ํธ๋ฆฌํจ์ ์ ๊ณตํ๋ค.
- URI ์ ๋ณด๋ฅผ ํตํด ๋ค์ด์ค๋ ์์ฒญ์ ์์ธกํ ์ ์๊ฒ ๋๋ค.
- Resource๊ฐ ํฌํจ๋ URI๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ๋๋ฌธ์, Resource์ ๋ํ ํ์ ์ ์ป์ ์ ์๋ค.
REST API ์ค๊ณ ๋จ๊ณ
0. The Swamp of POX
ํน์ ํ ์น ํ๋กํ ์ฝ(SOAP, XML-RPC)์ ํตํด์ ์ปดํจํฐ๊ฐ ๊ฐ์ง๊ณ ์๋ ์์์ ์๋ฏธ ์์ด ์ ๋ฌ. POST ๋ฉ์๋๋ง ์ฌ์ฉํ๋ฉฐ, ์๋น์ค ๊ฐ์ ๋จ์ผ POST ๋ฉ์๋๋ก XML ๋ฐ์ดํฐ๋ฅผ ๊ตํํ๋ค.
1. Resources
ํจ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋๊ธฐ๋ ๋์ REST URI๋ฅผ ์ด์ฉํ๋ค. POST ๋ฉ์๋ ํ๋๋ฐ์ ์ฌ์ฉํ์ง ์์ง๋ง, POST ๋ฉ์๋๋ก ์๋น์ค๊ฐ ํต์ ์ ํ๋ฉด์ ๋ณต์กํ ๊ธฐ๋ฅ์ ์ฌ๋ฌ ๋ฆฌ์์ค๋ก ๋ถ์ฐ์ํจ๋ค.
2. HTTP Verbs
POST ์ด์ธ์๋ GET, DELETE, PUT, HEAD ๋ฉ์๋๋ฅผ ์ถ๊ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ค.
3. Hypermedia controls
์์ฒญ์ ๋ํ Hypermedia ์๋ต ์์ ํด๋ผ์ด์ธํธ๊ฐ ๋ค์์ ์ทจํด์ผ ํ ์ก์ ์ ๋ํ ์ํ ์ ๋ณด๊ฐ ๋ด๊ฒจ ์๋ค. ๋ฆฌ์์ค์ ์ ๋ณด๋ฅผ ์ถ๊ฐ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ๋ฆฌ์์ค์ ํจ๊ป ์ ๋ฌํ๋ค. ํ์ง๋ง resource๋ฟ๋ง ์๋๋ผ ๋ถ๊ฐ์ ์ธ ์ ๋ณด๊น์ง ๋ํ๋ธ๋ค๋ ์ ์์ ๋ ผ๋์ด ์๋ค.
HATEOAS ์ฌ์ฉ
1. dependency ์ถ๊ฐ
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
2. ๋ฒ์ ๋ณ HATEOAS implementation ํ์ธ
pom.xml ์ ์ผ ์๋จ์ ๋ณด๋ฉด ์คํ๋ง๋ถํธ ๋ฒ์ ํ์ธ ๊ฐ๋ฅ
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
spring 2.1.8 RELEASE
- Resource : ๋ง๋ค๊ณ ์ ํ๋ ์ถ๊ฐ ์์์ Resouce ๊ฐ์ฒด๋ก ๋ฃ์
- ControllerLinkBuilder : ๋งํฌํด์ค
@GetMapping("/users/{id}")
public Resource<User> retrieveUser(@PathVariable int id){
Resource<User> resource = new Resource<>(user);
ControllerLinkBuilder linkTo = linkTo(methodOn(this.getClass())
.retrieveAllUsers());
resource.add(linkTo.withRel("all-users");
return resource;
}
spring 2.2
- EntityModel
- WebMvcLinkBuilder : ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐํ์ํฌ ๋ ์ ์ ๊ฐ ์ฌ์ฉํ ์ ์๋ ์ถ๊ฐ์ ์ธ ์ ๋ณด(๋งํฌ)๋ฅผ hypermedia ํ์์ผ๋ก ๋ฃ์ด๋๋๋ค.
- linkTo, methodOn ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ import ์ static์ ๋ถ์ฌ์ค์ผ ํ๋ค
- linkTo() : ์ปจํธ๋กค๋ฌ ํด๋์ค๋ฅผ ๊ฐ๋ฆฌํค๋ WebMvcLinkBuilder ๊ฐ์ฒด๋ฅผ ๋ฐํ
- methodOn(์ฐ๊ฒฐ์ํฌ ๋ฉ์๋) : this.getClass()๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ ์ค์์ retrieveAllUsers() ๋ฉ์๋๋ฅผ ์ฐ๋
@GetMapping("/users/{id}")
public Resource<User> retrieveUser(@PathVariable int id){
// ๋งค๊ฐ๋ณ์์ ์ ์ ๊ฐ์ฒด๊ฐ ๋ฃ์
EntityModel<User> entityModel = EntityModel.of(user);
WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retrieveAllUsers());
// retrieveAllUsers() ๋ฉ์๋๋ฅผ "all-users"๋ก href ์ฐ๊ฒฐ
// resource ๊ฐ์ฒด์ ๋งํฌ ์ถ๊ฐ
entityModel.add(linkTo.withRel("all-users"));
return model;
}
retrieveAllUsers()์ all-users ์ฐ๋ → /users์ all-users mapping
[์ฐธ๊ณ ]
'๐ฟ Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring Boot/RESTful] REST API Monitoring์ ์ํ Actuator(+spring fox PathPatternParser ์ด์) (0) | 2022.02.18 |
---|---|
[Spring Boot/RESTful] Swagger ์ค์ (+๋ฒ์ ์ค๋ฅ) (0) | 2022.02.18 |
[Spring boot/RESTful] REST API ๋ฒ์ ๊ด๋ฆฌ (0) | 2022.02.18 |
[Spring boot/RESTful] Response Filtering (0) | 2022.02.18 |
[Spring Boot/RESTful] Response ๋ฐ์ดํฐ ํ์ ๋ฐํ(XML format) (0) | 2022.02.18 |
๋๊ธ