[REST,RESTAPI]
in JavaScript
REST(Representational State Transfer)๋ HTTP/1.0๊ณผ 1.1์ ์คํ ์์ฑ์ ์ฐธ์ฌํ์๊ณ ์ํ์น HTTP ์๋ฒ ํ๋ก์ ํธ์ ๊ณต๋์ค๋ฆฝ์์ธ ๋ก์ด ํ๋ฉ (Roy Fielding)์ 2000๋ ๋ ผ๋ฌธ์์ ์ฒ์ ์๊ฐ๋์๋ค. ๋ฐํ ๋น์์ ์น์ด HTTP์ ์ค๊ณ ์ ์ฐ์์ฑ์ ์ ๋๋ก ์ฌ์ฉํ์ง ๋ชปํ๊ณ ์๋ ์ํฉ์ ๋ณด๊ณ ์น์ ์ฅ์ ์ ์ต๋ํ ํ์ฉํ ์ ์๋ ์ํคํ ์ณ๋ก์ REST๋ฅผ ์๊ฐํ์๊ณ ์ด๋ HTTP ํ๋กํ ์ฝ์ ์๋์ ๋ง๊ฒ ๋์์ธํ๋๋ก ์ ๋ํ๊ณ ์๋ค. REST์ ๊ธฐ๋ณธ ์์น์ ์ฑ์คํ ์งํจ ์๋น์ค ๋์์ธ์ โRESTfulโ์ด๋ผ๊ณ ํํํ๋ค.
REST ?
HTTP URI + HTTP Method์ด๋ค.
HTTP URI๋ฅผ ํตํด ์ ์ดํ ์์(Resource)์ ๋ช ์ํ๊ณ HTTP Method(GET, POST, PUT, DELETE)๋ฅผ ํตํด
ํด๋น ์์(Resource)๋ฅผ ์ ์ดํ๋ ๋ช ๋ น์ ๋ด๋ฆฌ๋ ๋ฐฉ์์ ์ํคํ ์ณ์ด๋ค.
REST์ ๊ตฌ์ฑ
- ์์(RESOURCE) - URI
- ๋ชจ๋ ์์์ ๊ณ ์ ํ ID๊ฐ ์กด์ฌํ๊ณ , ์ด ์์์ Server์ ์กด์ฌํ๋ค.
- ์์์ ๊ตฌ๋ณํ๋ ID๋ โ/groups/:group_idโ์ ๊ฐ์ HTTP URI ๋ค.
- Client๋ URI๋ฅผ ์ด์ฉํด์ ์์์ ์ง์ ํ๊ณ ํด๋น ์์์ ์ํ(์ ๋ณด)์ ๋ํ ์กฐ์์ Server์ ์์ฒญํ๋ค.
- ํ์(Verb) - HTTP METHOD
- HTTP ํ๋กํ ์ฝ์ Method๋ฅผ ์ฌ์ฉํ๋ค.
- HTTP ํ๋กํ ์ฝ์ GET, POST, PUT, DELETE ์ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
- ํํ(Representations)
- Client๊ฐ ์์์ ์ํ(์ ๋ณด)์ ๋ํ ์กฐ์์ ์์ฒญํ๋ฉด Server๋ ์ด์ ์ ์ ํ ์๋ต(Representation)์ ๋ณด๋ธ๋ค.
- REST์์ ํ๋์ ์์์ JSON, XML, TEXT, RSS ๋ฑ ์ฌ๋ฌ ํํ์ Representation์ผ๋ก ๋ํ๋ด์ด ์ง ์ ์๋ค.
- JSON ํน์ XML๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค.
REST์ ํน์ง
1) Uniform (์ ๋ํผ ์ธํฐํ์ด์ค)
Uniform Interface๋ URI๋ก ์ง์ ํ ๋ฆฌ์์ค์ ๋ํ ์กฐ์์ ํต์ผ๋๊ณ ํ์ ์ ์ธ ์ธํฐํ์ด์ค๋ก ์ํํ๋ ์ํคํ ์ฒ ์คํ์ผ์ ๋งํฉ๋๋ค.
2) Stateless (๋ฌด์ํ์ฑ)
REST๋ ๋ฌด์ํ์ฑ ์ฑ๊ฒฉ์ ๊ฐ์ต๋๋ค. ๋ค์ ๋งํด ์์ ์ ์ํ ์ํ์ ๋ณด๋ฅผ ๋ฐ๋ก ์ ์ฅํ๊ณ ๊ด๋ฆฌํ์ง ์์ต๋๋ค. ์ธ์ ์ ๋ณด๋ ์ฟ ํค์ ๋ณด๋ฅผ ๋ณ๋๋ก ์ ์ฅํ๊ณ ๊ด๋ฆฌํ์ง ์๊ธฐ ๋๋ฌธ์ API ์๋ฒ๋ ๋ค์ด์ค๋ ์์ฒญ๋ง์ ๋จ์ํ ์ฒ๋ฆฌํ๋ฉด ๋ฉ๋๋ค. ๋๋ฌธ์ ์๋น์ค์ ์์ ๋๊ฐ ๋์์ง๊ณ ์๋ฒ์์ ๋ถํ์ํ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ์ง ์์์ผ๋ก์จ ๊ตฌํ์ด ๋จ์ํด์ง๋๋ค.
3) Cacheable (์บ์ ๊ฐ๋ฅ)
REST์ ๊ฐ์ฅ ํฐ ํน์ง ์ค ํ๋๋ HTTP๋ผ๋ ๊ธฐ์กด ์นํ์ค์ ๊ทธ๋๋ก ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ์น์์ ์ฌ์ฉํ๋ ๊ธฐ์กด ์ธํ๋ผ๋ฅผ ๊ทธ๋๋ก ํ์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค. ๋ฐ๋ผ์ HTTP๊ฐ ๊ฐ์ง ์บ์ฑ ๊ธฐ๋ฅ์ด ์ ์ฉ ๊ฐ๋ฅํฉ๋๋ค. HTTP ํ๋กํ ์ฝ ํ์ค์์ ์ฌ์ฉํ๋ Last-Modifiedํ๊ทธ๋ E-Tag๋ฅผ ์ด์ฉํ๋ฉด ์บ์ฑ ๊ตฌํ์ด ๊ฐ๋ฅํฉ๋๋ค.
4) Self-descriptiveness (์์ฒด ํํ ๊ตฌ์กฐ)
REST์ ๋ ๋ค๋ฅธ ํฐ ํน์ง ์ค ํ๋๋ REST API ๋ฉ์์ง๋ง ๋ณด๊ณ ๋ ์ด๋ฅผ ์ฝ๊ฒ ์ดํด ํ ์ ์๋ ์์ฒด ํํ ๊ตฌ์กฐ๋ก ๋์ด ์๋ค๋ ๊ฒ์ ๋๋ค.
5) Client - Server ๊ตฌ์กฐ
REST ์๋ฒ๋ API ์ ๊ณต, ํด๋ผ์ด์ธํธ๋ ์ฌ์ฉ์ ์ธ์ฆ์ด๋ ์ปจํ ์คํธ(์ธ์ , ๋ก๊ทธ์ธ ์ ๋ณด)๋ฑ์ ์ง์ ๊ด๋ฆฌํ๋ ๊ตฌ์กฐ๋ก ๊ฐ๊ฐ์ ์ญํ ์ด ํ์คํ ๊ตฌ๋ถ๋๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ์ ์๋ฒ์์ ๊ฐ๋ฐํด์ผ ํ ๋ด์ฉ์ด ๋ช ํํด์ง๊ณ ์๋ก๊ฐ ์์กด์ฑ์ด ์ค์ด๋ค๊ฒ ๋ฉ๋๋ค.
6) ๊ณ์ธตํ ๊ตฌ์กฐ
REST ์๋ฒ๋ ๋ค์ค ๊ณ์ธต์ผ๋ก ๊ตฌ์ฑ๋ ์ ์์ผ๋ฉฐ ๋ณด์, ๋ก๋ ๋ฐธ๋ฐ์ฑ, ์ํธํ ๊ณ์ธต์ ์ถ๊ฐํด ๊ตฌ์กฐ์์ ์ ์ฐ์ฑ์ ๋ ์ ์๊ณ PROXY, ๊ฒ์ดํธ์จ์ด ๊ฐ์ ๋คํธ์ํฌ ๊ธฐ๋ฐ์ ์ค๊ฐ๋งค์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํฉ๋๋ค.
REST API ?
- API(Application Programming Interface)๋
- ๋ฐ์ดํฐ์ ๊ธฐ๋ฅ์ ์งํฉ์ ์ ๊ณตํ์ฌ ์ปดํจํฐ ํ๋ก๊ทธ๋จ๊ฐ ์ํธ์์ฉ์ ์ด์งํ๋ฉฐ, ์๋ก ์ ๋ณด๋ฅผ ๊ตํ๊ฐ๋ฅ ํ๋๋ก ํ๋ ๊ฒ์ด๋ค.
- REST API์ ์ ์
- REST ๊ธฐ๋ฐ์ผ๋ก ์๋น์ค API๋ฅผ ๊ตฌํํ ๊ฒ
- ์ต๊ทผ OpenAPI(๋๊ตฌ๋ ์ฌ์ฉํ ์ ์๋๋ก ๊ณต๊ฐ๋ API: ๊ตฌ๊ธ ๋งต, ๊ณต๊ณต ๋ฐ์ดํฐ ๋ฑ), ๋ง์ดํฌ๋ก ์๋น์ค(ํ๋์ ํฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ๊ฐ์ ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ์ชผ๊ฐ์ด ๋ณ๊ฒฝ๊ณผ ์กฐํฉ์ด ๊ฐ๋ฅํ๋๋ก ๋ง๋ ์ํคํ ์ฒ) ๋ฑ์ ์ ๊ณตํ๋ ์ ์ฒด ๋๋ถ๋ถ์ REST API๋ฅผ ์ ๊ณตํ๋ค.
- ํน์ง
- ์ฌ๋ด ์์คํ ๋ค๋ REST ๊ธฐ๋ฐ์ผ๋ก ์์คํ ์ ๋ถ์ฐํด ํ์ฅ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ ๋์ฌ ์ ์ง๋ณด์ ๋ฐ ์ด์ฉ์ ํธ๋ฆฌํ๊ฒ ํ ์ ์๋ค.
- REST๋ HTTP ํ์ค์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌํํ๋ฏ๋ก, HTTP๋ฅผ ์ง์ํ๋ ํ๋ก๊ทธ๋จ ์ธ์ด๋ก ํด๋ผ์ด์ธํธ, ์๋ฒ๋ฅผ ๊ตฌํํ ์ ์๋ค.
- ์ฆ, REST API๋ฅผ ์ ์ํ๋ฉด ๋ธํ์ด ํด๋ผ์ด์ธํธ ๋ฟ ์๋๋ผ, ์๋ฐ, C#, ์น ๋ฑ์ ์ด์ฉํด ํด๋ผ์ด์ธํธ๋ฅผ ์ ์ํ ์ ์๋ค.
REST API ๋์์ธ ๊ฐ์ด๋
REST API ์ค๊ณ ์ ๊ฐ์ฅ ์ค์ํ ํญ๋ชฉ์ ๋ค์์ 2๊ฐ์ง๋ก ์์ฝํ ์ ์์ต๋๋ค.
์ฒซ ๋ฒ์งธ, URI๋ ์ ๋ณด์ ์์์ ํํํด์ผ ํ๋ค. ๋ ๋ฒ์งธ, ์์์ ๋ํ ํ์๋ HTTP Method(GET, POST, PUT, DELETE)๋ก ํํํ๋ค.
REST API ์ค์ฌ ๊ท์น
REST์์ ๊ฐ์ฅ ์ค์ํ ๊ธฐ๋ณธ์ ์ธ ๊ท์น์ ๋ ๊ฐ์ง์ด๋ค. URI๋ ์์์ ํํํ๋ ๋ฐ์ ์ง์คํ๊ณ ํ์์ ๋ํ ์ ์๋ HTTP Method๋ฅผ ํตํด ํ๋ ๊ฒ์ด RESTํ API๋ฅผ ์ค๊ณํ๋ ์ค์ฌ ๊ท์น์ด๋ค.
1. URI๋ ์ ๋ณด์ ์์์ ํํํด์ผ ํ๋ค.
๋ฆฌ์์ค๋ช ์ ๋์ฌ๋ณด๋ค๋ ๋ช ์ฌ๋ฅผ ์ฌ์ฉํ๋ค. URI๋ ์์์ ํํํ๋๋ฐ ์ค์ ์ ๋์ด์ผ ํ๋ค. get ๊ฐ์ ํ์์ ๋ํ ํํ์ด ๋ค์ด๊ฐ์๋ ์๋๋ค.
# bad
GET /getTodos/1
GET /todos/show/1
# good
GET /todos/1
2. ์์์ ๋ํ ํ์๋ HTTP Method(GET, POST, PUT, DELETE ๋ฑ)์ผ๋ก ํํํ๋ค.
# bad
GET /todos/delete/1
# good
DELETE /todos/1
HTTP METHOD
์ฃผ๋ก 5๊ฐ์ง์ Method(GET, POST, PUT, PATCH, DELETE)๋ฅผ ์ฌ์ฉํ์ฌ CRUD๋ฅผ ๊ตฌํํ๋ค.
Method | Action | ์ญํ | ํ์ด๋ก๋ |
---|---|---|---|
GET | index/retrieve | ๋ชจ๋ /ํน์ ๋ฆฌ์์ค๋ฅผ ์กฐํ | x |
POST | create | ๋ฆฌ์์ค๋ฅผ ์์ฑ | โ |
PUT | replace | ๋ฆฌ์์ค์ ์ ์ฒด๋ฅผ ๊ต์ฒด | โ |
PATCH | modify | ๋ฆฌ์์ค์ ์ผ๋ถ๋ฅผ ์์ | โ |
DELETE | delete | ๋ชจ๋ /ํน์ ๋ฆฌ์์ค๋ฅผ ์ญ์ | x |
REST API์ ๊ตฌ์ฑ
REST API๋ ์์(Resource), ํ์(Verb), ํํ(Representations)์ 3๊ฐ์ง ์์๋ก ๊ตฌ์ฑ๋๋ค. REST๋ ์์ฒด ํํ ๊ตฌ์กฐ(Self-descriptiveness)๋ก ๊ตฌ์ฑ๋์ด REST API๋ง์ผ๋ก ์์ฒญ์ ์ดํดํ ์ ์๋ค.
๊ตฌ์ฑ ์์ | ๋ด์ฉ | ํํ ๋ฐฉ๋ฒ |
---|---|---|
Resource | ์์ | HTTP URI |
Verb | ์์์ ๋ํ ํ์ | HTTP Method |
Representations | ์์์ ๋ํ ํ์์ ๋ด์ฉ | HTTP Message Pay Load |
REST API์ Example
json-server
$ mkdir rest-api-exam && cd rest-api-exam
$ npm init -y
$ npm install json-server
db.json ํ์ผ์ ์๋์ ๊ฐ์ด ์์ฑํ๋ค.
{
"todos": [
{ "id": 1, "content": "HTML", "completed": false },
{ "id": 2, "content": "CSS", "completed": true },
{ "id": 3, "content": "Javascript", "completed": false }
]
}
json-server๋ฅผ ์คํํ๋ค. ํฌํธ๋ 5000์ ์ฌ์ฉํ๋ค.
$ npm start
GET
todos ๋ฆฌ์์ค์์ ๋ชจ๋ todo๋ฅผ ์กฐํ(index)ํ๋ค.
$ curl -X GET http://localhost:5000/todos
[
{
"id": 1,
"content": "HTML",
"completed": false
},
{
"id": 2,
"content": "CSS",
"completed": true
},
{
"id": 3,
"content": "Javascript",
"completed": false
}
]
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:5000/todos/1');
xhr.send();
xhr.onreadystatechange = function (e) {
if (xhr.readyState !== XMLHttpRequest.DONE) return;
if(xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.log("Error!");
}
};
POST
todos ๋ฆฌ์์ค์ ์๋ก์ด todo๋ฅผ ์์ฑํ๋ค.
$ curl -X POST http://localhost:5000/todos -H "Content-Type: application/json" -d '{"id": 4, "content": "Angular", "completed": true}'
{
"id": 4,
"content": "Angular",
"completed": true
}
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:5000/todos');
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(JSON.stringify({ id: 4, content: 'Angular', completed: true }));
xhr.onreadystatechange = function (e) {
if (xhr.readyState !== XMLHttpRequest.DONE) return;
if(xhr.status === 201) { // 201: Created
console.log(xhr.responseText);
} else {
console.log("Error!");
}
};
PUT
PUT์ ํน์ ๋ฆฌ์์ค์ ์ ์ฒด๋ฅผ ๊ฐฑ์ ํ ๋ ์ฌ์ฉํ๋ค. todos ๋ฆฌ์์ค์์ id๋ฅผ ์ฌ์ฉํ์ฌ todo๋ฅผ ํน์ ํ์ฌ id๋ฅผ ์ ์ธํ ๋ฆฌ์์ค ์ ์ฒด๋ฅผ ๊ฐฑ์ ํ๋ค.
$ curl -X PUT http://localhost:5000/todos/4 -H "Content-Type: application/json" -d '{"id": 4, "content": "React", "completed": false}'
{
"content": "React",
"completed": false,
"id": 4
}
const xhr = new XMLHttpRequest();
xhr.open('PUT', 'http://localhost:5000/todos/4');
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(JSON.stringify({ id: 4, content: 'React', completed: false }));
xhr.onreadystatechange = function (e) {
if (xhr.readyState !== XMLHttpRequest.DONE) return;
if(xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.log("Error!");
}
};
PATCH
PATCH๋ ํน์ ๋ฆฌ์์ค์ ์ผ๋ถ๋ฅผ ๊ฐฑ์ ํ ๋ ์ฌ์ฉํ๋ค. todos ๋ฆฌ์์ค์ id๋ฅผ ์ฌ์ฉํ์ฌ todo๋ฅผ ํน์ ํ์ฌ completed๋ง์ true๋ก ๊ฐฑ์ ํ๋ค.
$ curl -X PATCH http://localhost:5000/todos/4 -H "Content-Type: application/json" -d '{"completed": true}'
{
"id": 4,
"content": "React",
"completed": true
}
const xhr = new XMLHttpRequest();
xhr.open('PATCH', 'http://localhost:5000/todos/4');
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(JSON.stringify({ completed: true }));
xhr.onreadystatechange = function (e) {
if (xhr.readyState !== XMLHttpRequest.DONE) return;
if(xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.log("Error!");
}
};
DELETE
todos ๋ฆฌ์์ค์์ id๋ฅผ ์ฌ์ฉํ์ฌ todo๋ฅผ ํน์ ํ๊ณ ์ญ์ ํ๋ค.
$ curl -X DELETE http://localhost:5000/todos/4
{}
const xhr = new XMLHttpRequest();
xhr.open('DELETE', 'http://localhost:5000/todos/4');
xhr.send();
xhr.onreadystatechange = function (e) {
if (xhr.readyState !== XMLHttpRequest.DONE) return;
if(xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.log("Error!");
}
};
URI ์ค๊ณ์ ์ฃผ์ํ ์
1) ์ฌ๋์ ๊ตฌ๋ถ์(/)๋ ๊ณ์ธต ๊ด๊ณ๋ฅผ ๋ํ๋ด๋๋ ์ฌ์ฉ
http://restapi.example.com/houses/apartments
http://restapi.example.com/animals/mammals/whales
2) URI ๋ง์ง๋ง ๋ฌธ์๋ก ์ฌ๋์(/)๋ฅผ ํฌํจํ์ง ์๋๋ค.
URI์ ํฌํจ๋๋ ๋ชจ๋ ๊ธ์๋ ๋ฆฌ์์ค์ ์ ์ผํ ์๋ณ์๋ก ์ฌ์ฉ๋์ด์ผ ํ๋ฉฐ URI๊ฐ ๋ค๋ฅด๋ค๋ ๊ฒ์ ๋ฆฌ์์ค๊ฐ ๋ค๋ฅด๋ค๋ ๊ฒ์ด๊ณ , ์ญ์ผ๋ก ๋ฆฌ์์ค๊ฐ ๋ค๋ฅด๋ฉด URI๋ ๋ฌ๋ผ์ ธ์ผ ํฉ๋๋ค. REST API๋ ๋ถ๋ช ํ URI๋ฅผ ๋ง๋ค์ด ํต์ ์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ํผ๋์ ์ฃผ์ง ์๋๋ก URI ๊ฒฝ๋ก์ ๋ง์ง๋ง์๋ ์ฌ๋์(/)๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
http://restapi.example.com/houses/apartments/ (X)
http://restapi.example.com/houses/apartments (0)
3) ํ์ดํ(-)์ URI ๊ฐ๋ ์ฑ์ ๋์ด๋๋ฐ ์ฌ์ฉ
URI๋ฅผ ์ฝ๊ฒ ์ฝ๊ณ ํด์ํ๊ธฐ ์ํด, ๋ถ๊ฐํผํ๊ฒ ๊ธด URI๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ค๋ฉด ํ์ดํ์ ์ฌ์ฉํด ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
4)๋ฐ์ค(_)์ URI์ ์ฌ์ฉํ์ง ์๋๋ค.
๊ธ๊ผด์ ๋ฐ๋ผ ๋ค๋ฅด๊ธด ํ์ง๋ง ๋ฐ์ค์ ๋ณด๊ธฐ ์ด๋ ต๊ฑฐ๋ ๋ฐ์ค ๋๋ฌธ์ ๋ฌธ์๊ฐ ๊ฐ๋ ค์ง๊ธฐ๋ ํฉ๋๋ค. ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํผํ๊ธฐ ์ํด ๋ฐ์ค ๋์ ํ์ดํ(-)์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.(๊ฐ๋ ์ฑ)
5) URI๊ฒฝ๋ก์๋ ์๋ฌธ์๊ฐ ์ ํฉํ๋ค.
URI ๊ฒฝ๋ก์ ๋๋ฌธ์ ์ฌ์ฉ์ ํผํ๋๋ก ํด์ผ ํฉ๋๋ค. ๋์๋ฌธ์์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ฆฌ์์ค๋ก ์ธ์ํ๊ฒ ๋๊ธฐ ๋๋ฌธ์ ๋๋ค. RFC 3986(URI ๋ฌธ๋ฒ ํ์)์ URI ์คํค๋ง์ ํธ์คํธ๋ฅผ ์ ์ธํ๊ณ ๋ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ณํ๋๋ก ๊ท์ ํ๊ธฐ ๋๋ฌธ์ด์ง์.
RFC 3986 is the URI (Unified Resource Identifier) Syntax document
6) ํ์ผ ํ์ฅ์๋ URI์ ํฌํจ์ํค์ง ์๋๋ค.
http://restapi.example.com/members/soccer/345/photo.jpg (X)
REST API์์๋ ๋ฉ์์ง ๋ฐ๋ ๋ด์ฉ์ ํฌ๋งท์ ๋ํ๋ด๊ธฐ ์ํ ํ์ผ ํ์ฅ์๋ฅผ URI ์์ ํฌํจ์ํค์ง ์์ต๋๋ค. Accept header๋ฅผ ์ฌ์ฉํ๋๋ก ํฉ์๋ค.
GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg
๋ฆฌ์์ค๊ฐ์ ๊ด๊ณ๋ฅผ ํํํ๋ ๋ฐฉ๋ฒ
REST ๋ฆฌ์์ค ๊ฐ์๋ ์ฐ๊ด ๊ด๊ณ๊ฐ ์์ ์ ์๊ณ , ์ด๋ฐ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ํํ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํฉ๋๋ค.
/๋ฆฌ์์ค๋ช
/๋ฆฌ์์ค ID/๊ด๊ณ๊ฐ ์๋ ๋ค๋ฅธ ๋ฆฌ์์ค๋ช
ex) GET : /users/{userid}/devices (์ผ๋ฐ์ ์ผ๋ก ์์ โhasโ์ ๊ด๊ณ๋ฅผ ํํํ ๋)
๋ง์ฝ์ ๊ด๊ณ๋ช ์ด ๋ณต์กํ๋ค๋ฉด ์ด๋ฅผ ์๋ธ ๋ฆฌ์์ค์ ๋ช ์์ ์ผ๋ก ํํํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ โ์ข์ํ๋โ ๋๋ฐ์ด์ค ๋ชฉ๋ก์ ํํํด์ผ ํ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ํํ๋ก ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
GET : /users/{userid}/likes/devices (๊ด๊ณ๋ช
์ด ์ ๋งคํ๊ฑฐ๋ ๊ตฌ์ฒด์ ํํ์ด ํ์ํ ๋)
HTTP ์๋ต ์ํ ์ฝ๋
์ํ์ฝ๋ | ย |
---|---|
200 | ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ์ ์์ ์ผ๋ก ์ํํจ |
201 | ํด๋ผ์ด์ธํธ๊ฐ ์ด๋ ํ ๋ฆฌ์์ค ์์ฑ์ ์์ฒญ, ํด๋น ๋ฆฌ์์ค๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋จ(POST๋ฅผ ํตํ ๋ฆฌ์์ค ์์ฑ ์์ ์) |
์ํ์ฝ๋ | ย |
---|---|
400 | ํด๋ผ์ด์ธํธ์ ์์ฒญ์ด ๋ถ์ ์ ํ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ ์๋ต ์ฝ๋ |
401 | ํด๋ผ์ด์ธํธ๊ฐ ์ธ์ฆ๋์ง ์์ ์ํ์์ ๋ณดํธ๋ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ์ ๋ ์ฌ์ฉํ๋ ์๋ต ์ฝ๋ |
ย | (๋ก๊ทธ์ธ ํ์ง ์์ ์ ์ ๊ฐ ๋ก๊ทธ์ธ ํ์ ๋, ์์ฒญ ๊ฐ๋ฅํ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ์ ๋) |
403 | ์ ์ ์ธ์ฆ์ํ์ ๊ด๊ณ ์์ด ์๋ตํ๊ณ ์ถ์ง ์์ ๋ฆฌ์์ค๋ฅผ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญํ์ ๋ ์ฌ์ฉํ๋ ์๋ต ์ฝ๋ |
ย | (403 ๋ณด๋ค๋ 400์ด๋ 404๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๊ถ๊ณ . 403 ์์ฒด๊ฐ ๋ฆฌ์์ค๊ฐ ์กด์ฌํ๋ค๋ ๋ป์ด๊ธฐ ๋๋ฌธ์) |
405 | ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญํ ๋ฆฌ์์ค์์๋ ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ Method๋ฅผ ์ด์ฉํ์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ ์๋ต ์ฝ๋ |
์ํ์ฝ๋ | ย |
---|---|
301 | ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญํ ๋ฆฌ์์ค์ ๋ํ URI๊ฐ ๋ณ๊ฒฝ ๋์์ ๋ ์ฌ์ฉํ๋ ์๋ต ์ฝ๋ |
ย | (์๋ต ์ Location header์ ๋ณ๊ฒฝ๋ URI๋ฅผ ์ ์ด ์ค์ผ ํฉ๋๋ค.) |
500 | ์๋ฒ์ ๋ฌธ์ ๊ฐ ์์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ ์๋ต ์ฝ๋ |
RESTFul?
RESTful์ด๋
- RESTful์ ์ผ๋ฐ์ ์ผ๋ก REST๋ผ๋ ์ํคํ
์ฒ๋ฅผ ๊ตฌํํ๋ ์น ์๋น์ค๋ฅผ ๋ํ๋ด๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์ฉ์ด์ด๋ค.
- โREST APIโ๋ฅผ ์ ๊ณตํ๋ ์น ์๋น์ค๋ฅผ โRESTfulโํ๋ค๊ณ ํ ์ ์๋ค.
- RESTful์ REST๋ฅผ REST๋ต๊ฒ ์ฐ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก, ๋๊ตฐ๊ฐ๊ฐ ๊ณต์์ ์ผ๋ก ๋ฐํํ ๊ฒ์ด ์๋๋ค.
- ์ฆ, REST ์๋ฆฌ๋ฅผ ๋ฐ๋ฅด๋ ์์คํ ์ RESTful์ด๋ ์ฉ์ด๋ก ์ง์นญ๋๋ค.
RESTFul์ ๋ชฉ์
- ์ดํดํ๊ธฐ ์ฝ๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์ด REST API๋ฅผ ๋ง๋๋ ๊ฒ
- RESTfulํ API๋ฅผ ๊ตฌํํ๋ ๊ทผ๋ณธ์ ์ธ ๋ชฉ์ ์ด ์ฑ๋ฅ ํฅ์์ ์๋ ๊ฒ์ด ์๋๋ผ ์ผ๊ด์ ์ธ ์ปจ๋ฒค์ ์ ํตํ API์ ์ดํด๋ ๋ฐ ํธํ์ฑ์ ๋์ด๋ ๊ฒ์ด ์ฃผ ๋๊ธฐ์ด๋, ์ฑ๋ฅ์ด ์ค์ํ ์ํฉ์์๋ ๊ตณ์ด RESTfulํ API๋ฅผ ๊ตฌํํ ํ์๋ ์๋ค.
RESTFULํ์ง ๋ชปํ ๊ฒฝ์ฐ
- CRUD๊ธฐ๋ฅ์ ๋ชจ๋ POST๋ก๋ง ์ฒ๋ฆฌํ๋ API
- route์ resource,id์ธ์ ์ ๋ณด๊ฐ ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ ex ) /students/updateName
[์ฐธ๊ณ ]
https://meetup.toast.com/posts/92
https://poiemaweb.com/js-rest-api
https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html