HTTP
를 기반으로 클라이언트가 서버의 리소스에 접근하는 방식을 규정한 아키텍처다.HTTP
의 장점을 최대한 활용할 수 있는 아키텍처로서 REST(REpresentational State Transfer)가 나오게 되었고, HTTP 프로토콜을 의도에 맞게 디자인하도록 유도하고 있다. REST의 기본 원칙을 잘 지킨 서비스 디자인을 RESTful
이라고 표현한다.구성 요소 | 내용 | 표현 방법 |
---|---|---|
Resource | 자원 | HTTP URI |
Verb | 자원에 대한 행위 | HTTP 요청 메서드 |
Representations | 자원에 대한 행위의 내용 | Pay Load |
1. URI는 리소스를 표현해야 한다.
# bad
GET /getTodos/1
GET /todos/show/1
# good
GET /todos/1
2. 리소스에 대한 행위는 HTTP 요청 메서드로 표현한다.
# bad
GET /todos/delete/1
# good
DELETE /todos/1
http://restapi.example.com/houses/apartments
# bad
http://restapi.example.com/houses/apartments/
# good
http://restapi.example.com/houses/apartments
# bad
http://khj93.com/test_blog
# good
http://khj93.com/test-blog
# bad
http://restapi.example.com/members/soccer/345/photo.jpg
# good
GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg
✅ 리소스 간에 연관 관계가 있는 경우
// /리소스명/리소스 ID/관계가 있는 다른 리소스명
GET : /users/{userid}/devices (일반적으로 소유 ‘has’의 관계를 표현할 때)
// 관계명이 복잡하다면 서브 리소스에 명시적으로 표현
GET : /users/{userid}/likes/devices
http:// restapi.example.com/sports/soccer/players/13
GET
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:5000/todos');
xhr.send();
xhr.onload = () => {
if(xhr.status === 200) {
document.querySelector('pre').textContent(xhr.response);
} else {
console.log("Error!", xhr.status, xhr.statusText);
}
};
/*
[
{
"id": 1,
"content": "HTML",
"completed": false
},
{
"id": 2,
"content": "CSS",
"completed": true
},
{
"id": 3,
"content": "Javascript",
"completed": false
}
]
*/
const xhr = new XMLHttpRequest();
// 1번 todo를 조회
xhr.open('GET', 'http://localhost:5000/todos/1');
xhr.send();
xhr.onload = () => {
if(xhr.status === 200) {
document.querySelector('pre').textContent(xhr.response);
} else {
console.log("Error!", xhr.status, xhr.statusText);
}
};
/*
{
"id": 1,
"content": "HTML",
"completed": false
}
*/
POST
setRequestHeader
메서드를 사용하여 요청 몸체에 담아 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다.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.onload = () => {
// 200 : OK, 201 : created
if(xhr.status === 200 || xhr.status === 201) {
document.querySelector('pre').textContent(xhr.response);
} else {
console.log("Error!", xhr.status, xhr.statusText);
}
};
/*
{
"id": 4,
"content": "Angular",
"completed": true
}
*/
PUT
setRequestHeader
메서드를 사용하여 요청 몸체에 담아 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다.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.onload = () => {
if(xhr.status === 200) {
document.querySelector('pre').textContent(xhr.response);
} else {
console.log("Error!", xhr.status, xhr.statusText);
}
};
/*
{
"id": 4
"content": "React",
"completed": false,
}
*/
PATCH
setRequestHeader
메서드를 사용하여 요청 몸체에 담아 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다.const xhr = new XMLHttpRequest();
// id로 todo를 특정.
xhr.open('PATCH', 'http://localhost:5000/todos/4');
xhr.setRequestHeader('Content-type', 'application/json');
// completed 값만 수정.
xhr.send(JSON.stringify({ completed: true }));
xhr.onload = () => {
if(xhr.status === 200) {
document.querySelector('pre').textContent(xhr.response);
} else {
console.log("Error!", xhr.status, xhr.statusText);
}
};
/*
{
"id": 4,
"content": "React",
"completed": true
}
*/
DELETE
const xhr = new XMLHttpRequest();
xhr.open('DELETE', 'http://localhost:5000/todos/4');
xhr.send();
xhr.onload = () => {
if(xhr.status === 200) {
document.querySelector('pre').textContent(xhr.response);
} else {
console.log("Error!", xhr.status, xhr.statusText);
}
};
/*
{}
/*
<모던 자바스크립트 deepdive와, 추가 탐구한 내용을 정리한 포스트입니다.>