์๋: ์ง์์๊ฐ RESTful API์ ๊ฐ๋ ๊ณผ ์ด๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๊ณ ์๋์ง ํ๊ฐ
ํ
๋์ ๋ต์
RESTful API๋ REST, ์ฆ Representational State Transfer ์ํคํ ์ฒ ์คํ์ผ์ ๋ฐ๋ฅด๋ API๋ฅผ ๋งํฉ๋๋ค.
REST์ ํต์ฌ ์์น์ ์์์ URI๋ก ํํํ๊ณ , HTTP ๋ฉ์๋๋ฅผ ์ฌ์ฉํด ์์์ ์กฐ์ํ๋ ๊ฒ์ ๋๋ค.RESTful API์ ํน์ง์ ๋ฌด์ํ์ฑ, ์ผ๊ด๋ ์ธํฐํ์ด์ค, ํด๋ผ์ด์ธํธ-์๋ฒ ๋ถ๋ฆฌ ๋ฑ์ด ์์ต๋๋ค.
์ด๋ฐ ๊ตฌ์กฐ ๋๋ถ์ ํ๋ก ํธ์๋์์๋ ๋ฐฑ์๋์ ๋ ๋ฆฝ์ ์ผ๋ก ๊ฐ๋ฐ์ด ๊ฐ๋ฅํ๊ณ , ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ด ๋์์ง๋๋ค.
์ฃผ์ด์ง ๋ต์ (๋ชจ๋ฒ ๋ต์)
REST๋ Representational State Transfer์ ์ฝ์๋ก, ์์์ URI๋ก ํํํ๊ณ HTTP ๋ฉ์๋๋ฅผ ํตํด ์กฐ์ํ๋ ์ํคํ ์ฒ ์คํ์ผ์ ๋๋ค.
RESTful API๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ์ ํต์ ์ ์ํ ์ธํฐํ์ด์ค๋ก, ์ผ๊ด์ฑ๊ณผ ์์ธก ๊ฐ๋ฅ์ฑ์ ์ ๊ณตํฉ๋๋ค.GET์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ๋, POST๋ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ ๋, PUT์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ ๋, DELETE๋ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
RESTful API๋ ์๋ 6๊ฐ์ง ์ ์ฝ ์กฐ๊ฑด์ ์ค์ํด์ผ ํ๋ค.
Cache-Control, ETag ๋ฑ์ ์ค์ ํ์ฌ ํด๋ผ์ด์ธํธ๊ฐ ์บ์ฑํ ์ ์๋๋ก ํ๋ค.โญ HATEOAS๋?
HATEOAS๋ RESTful API์ ์์น ์ค ํ๋๋ก, ํด๋ผ์ด์ธํธ๊ฐ API์ ์๋ต์ ํตํด ๋ค์์ ์ํํ ์ ์๋ ์ก์ (๋งํฌ)์ ๋์ ์ผ๋ก ์ ์ ์๋๋ก ํ๋ ๊ฐ๋ ์ด๋ค.
์ฆ, API ์๋ต์ด ๋จ์ํ ๋ฐ์ดํฐ๋ง์ด ์๋๋ผ, ๊ด๋ จ๋ ์ก์ ์ ํฌํจํ๋ ํ์ดํผ๋ฏธ๋์ด(hypermedia)๋ฅผ ์ ๊ณตํด์ผ ํ๋ค๋ ์์น์ด๋ค.
โญ HATEOAS ๊ฐ๋ ์ ๋ฆฌ
- HATEOAS์ ํต์ฌ ์์ด๋์ด
๐ ํด๋ผ์ด์ธํธ๋ API์ ์๋ํฌ์ธํธ(URL)๋ฅผ ์ฌ์ ์ ๋ชฐ๋ผ๋ ๋๋ค.
๐ ์๋ฒ๊ฐ ์๋ต์ ๊ด๋ จ๋ ๋งํฌ๋ฅผ ํฌํจํ์ฌ ํด๋ผ์ด์ธํธ๊ฐ ์๋์ผ๋ก ํ์์ด ๊ฐ๋ฅํ๋ค.
๐ RESTful API์์ ํ์ดํผ๋งํฌ๋ฅผ ์ด์ฉํ์ฌ ๋ฆฌ์์ค ๊ฐ์ ๊ด๊ณ๋ฅผ ํํํ๋ค.- ์์ ์์ด ์ฝ๊ฒ ์ค๋ช ํ๋ฉด?
๐ ์น์ฌ์ดํธ์์ ํ๋์ ๋งํฌ๋ฅผ ํด๋ฆญํ๋ฉด ๋ค์ ๋์(ํ์ด์ง ์ด๋, ๋ ๋ณด๊ธฐ ๋ฑ)์ด ๊ฐ๋ฅํ๋ฏ์ด,
๐ API ์๋ต์์๋ ํ์ฌ ๋ฆฌ์์ค์ ๋ํ ์ ๋ณด + ๋ค์ ์์ฒญ์ ์ํ ๋งํฌ๋ฅผ ํฌํจํ๋ ๋ฐฉ์
โญ HATEOAS ์ ์ฉ ์์
- HATEOAS ์์ด ์ผ๋ฐ์ ์ธ REST API ์๋ต
๋ฌธ์ ์ { "id": 1, "name": "์ด์์ ", "email": "lee@example.com" }
๐ ํด๋ผ์ด์ธํธ๊ฐ "์ด์์ "์ ์ ๋ณด๋ฅผ ์์ ํ๋ ค๋ฉด ์ฌ์ ์ ์๋ํฌ์ธํธ(/users/1/edit๋ฑ)๋ฅผ ์๊ณ ์์ด์ผ ํ๋ค.
๐ API๊ฐ ํ์ฅ๋ ๊ฒฝ์ฐ ํด๋ผ์ด์ธํธ ์ฝ๋๋ ๋ณ๊ฒฝํด์ผ ํ๋ค.- HATEOAS๋ฅผ ์ ์ฉํ REST API ์๋ต
๊ฐ์ ๋ ์ { "id": 1, "name": "์ด์์ ", "email": "lee@example.com", "_links": { "self": { "href": "/users/1" }, "edit": { "href": "/users/1/edit" }, "delete": { "href": "/users/1/delete" }, "orders": { "href": "/users/1/orders" } } }
๐ API ์๋ต์ ์ฌ์ฉ์๊ฐ ์ํํ ์ ์๋ ์ก์ ์ ํฌํจํ๋ค.
๐ ํด๋ผ์ด์ธํธ๋ ์๋ต๋ง ๋ณด๊ณ ๋ ๋ค์ ๋์(์์ , ์ญ์ , ์ฃผ๋ฌธ ๋ณด๊ธฐ ๋ฑ)์ ์ ์ ์๋ค.
๐ API ๊ตฌ์กฐ๊ฐ ๋ฐ๋์ด๋ ํด๋ผ์ด์ธํธ๊ฐ ํ๋์ฝ๋ฉํ URL์ ๋ฐ๊พธ์ง ์์๋ ๋๋ค.
โญ HATEOAS์ ์ฅ์
- ํด๋ผ์ด์ธํธ์ ์ ์ฐ์ฑ ์ฆ๊ฐ
API ๊ตฌ์กฐ ๋ณ๊ฒฝ์ด ์ผ์ด๋๋, ํด๋ผ์ด์ธํธ๋ ์๋ฒ์ ์๋ต์ ์ฐธ๊ณ ํ์ฌ ๋์ ์ผ๋ก API๋ฅผ ํ์ํ๋ค.- ๋ฌธ์ํ ํ์์ฑ์ด ์ค์ด๋ฆ
API ์๋ต ๋ด์ ๊ฐ๋ฅํ ์ก์ (๋งํฌ)์ ํฌํจํ๋ฏ๋ก, ๋ช ์์ ์ธ API ๋ฌธ์ ์์ด๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.- REST์ ์์จ ํ์์ฑ(self-discoverability) ๋ณด์ฅ
ํด๋ผ์ด์ธํธ๋ ์ฌ์ ์ง์ ์์ด๋ API๋ฅผ ํ์ํ ์ ์๋ค.
โญ HATEOAS์ ๋จ์
- ์๋ต ํฌ๊ธฐ๊ฐ ์ปค์ง
๋งํฌ ์ ๋ณด๋ฅผ ํฌํจํ๋ค ๋ณด๋, ์ผ๋ฐ์ ์ธ JSON ์๋ต๋ณด๋ค ๋ฐ์ดํฐ๊ฐ ์ฆ๊ฐํ๋ค.- ๊ตฌํ์ด ๋ณต์ก
์๋ฒ์์ ๊ฐ ๋ฆฌ์์ค์ ๋ํด ์ ์ ํ ๋งํฌ๋ฅผ ๋์ ์ผ๋ก ์์ฑํด์ผ ํ๋ค.- REST API๋ฅผ ํธ์ถํ ๋ ์ค๋ฒํค๋ ๋ฐ์
ํ์ํ ๋งํฌ๋ฅผ ์ฐพ๊ธฐ ์ํด ์ฌ๋ฌ ๊ฐ์ API ํธ์ถ์ด ํ์ํ ์ ์๋ค.
RESTful API๋ ๋ฆฌ์์ค(Resource)๋ฅผ ์ค์ฌ์ผ๋ก ์ค๊ณ๋๋ฉฐ, HTTP ํ์ค์ ํ์ฉํ๋ค.
https://api.example.com/users/123/users/123 : ID๊ฐ 123์ธ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์๋ฏธHTTP ๋ฉ์๋
RESTful API๋ HTTP ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ CRUD(Create, Read, Update, Delete) ์์
์ ์ํํ๋ค.
| HTTP ๋ฉ์๋ | ๋ชฉ์ | ์ค๋ช |
|---|---|---|
| GET | ์กฐํ(Read) | ๋ฐ์ดํฐ๋ฅผ ์กฐํ |
| POST | ์์ฑ(Create) | ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์์ฑ |
| PUT | ์ ์ฒด ์์ (Update) | ํน์ ๋ฆฌ์์ค๋ฅผ ์ ์ฒด ์ ๋ฐ์ดํธ |
| PATCH | ๋ถ๋ถ ์์ (Update) | ํน์ ๋ฆฌ์์ค๋ฅผ ๋ถ๋ถ ์ ๋ฐ์ดํธ |
| DELETE | ์ญ์ (Delete) | ํน์ ๋ฆฌ์์ค๋ฅผ ์ญ์ |
/users/123 ์์์ ๋ํด ์ํํ ์ ์๋ ์์
GET /users/123 : ID๊ฐ 123์ธ ์ฌ์ฉ์ ์ ๋ณด ์กฐํPOST /users : ์๋ก์ด ์ฌ์ฉ์ ์์ฑPUT /users/123 : ID๊ฐ 123์ธ ์ฌ์ฉ์ ์ ๋ณด ์ ์ฒด ์์ PATCH /users/123 : ID๊ฐ 123์ธ ์ฌ์ฉ์ ์ ๋ณด ์ผ๋ถ ์์ DELETE /users/123 : ID๊ฐ 123์ธ ์ฌ์ฉ์ ์ญ์ โ /getUser
โ
/users/{ID}โ /user
โ
/usersโ
/users/{id}/orders โก๏ธ ํน์ ์ฌ์ฉ์์ ์ฃผ๋ฌธ ๋ชฉ๋ก ์กฐํHTTP ์ํ ์ฝ๋(Status Code) ํ์ฉ
RESTful API๋ ์ ์ ํ HTTP ์ํ ์ฝ๋๋ฅผ ๋ฐํํด์ผ ํ๋ค.
| ์ํ ์ฝ๋ | ์๋ฏธ | ์ค๋ช |
|---|---|---|
| 200 OK | ์ฑ๊ณต | ์์ฒญ์ด ์ฑ๊ณต์ ์ผ๋ก ์ฒ๋ฆฌ๋จ |
| 201 Created | ์์ฑ ์๋ฃ | ์๋ก์ด ๋ฆฌ์์ค๊ฐ ์์ฑ๋จ |
| 204 No Content | ์ฑ๊ณต (์๋ต ๋ณธ๋ฌธ ์์) | ์์ฒญ ์ฑ๊ณต, ํ์ง๋ง ๋ฐํํ ๋ฐ์ดํฐ ์์ |
| 400 Bad Request | ์๋ชป๋ ์์ฒญ | ํด๋ผ์ด์ธํธ ์์ฒญ์ด ์๋ชป๋จ |
| 401 Unauthorized | ์ธ์ฆ ์คํจ | ์ธ์ฆ๋์ง ์์ ์ฌ์ฉ์ |
| 403 Forbidden | ์ ๊ทผ ๊ฑฐ๋ถ | ๊ถํ์ด ์์ |
| 404 Not Found | ๋ฆฌ์์ค ์์ | ์์ฒญํ ์์์ด ์กด์ฌํ์ง ์์ |
| 409 Conflict | ์ถฉ๋ ๋ฐ์ | ์ค๋ณต๋ ๋ฐ์ดํฐ ๋๋ ์ถฉ๋ ๋ฐ์ |
| 500 Internet Server Error | ์๋ฒ ์ค๋ฅ | ์๋ฒ ๋ด๋ถ ์ค๋ฅ |
GET /users/99999 (์กด์ฌํ์ง ์๋ ์ฌ์ฉ์) โ 404 Not FoundPOST /users (ํ์ ํ๋ ๋๋ฝ) โ 400 Bad RequestDELETE /users/123 (์ญ์ ์ฑ๊ณต) โ 204 No Content{
"id": 123,
"name": "ํ๊ธธ๋",
"email": "hong@example.com"
}Content-Type: application/jsonGET /users?role=adminGET /users?sort=name,descGET /users?page=2&size=20RESTful API๋ ๊ฐ๊ฒฐํ๊ณ ํ์ฅ์ฑ์ด ๋ฐ์ด๋๋ฉฐ, HTTP ํ์ค์ ํ์ฉํ์ฌ ํจ๊ณผ์ ์ธ ํด๋ผ์ด์ธํธ-์๋ฒ ํต์ ์ ์ ๊ณตํ๋ค.
์ฌ๋ฐ๋ฅธ RESTful API ์ค๊ณ๋ฅผ ์ํด์๋ URI ๋ช
๋ช
๊ท์น, HTTP ๋ฉ์๋ ํ์ฉ, ์ํ ์ฝ๋ ๋ฐํ, JSON ์๋ต ํ์ ๋ฑ์ ์์น์ ์ ๋ฐ๋ฅด๋ ๊ฒ์ด ์ค์ํ๋ค.