
REST API는 REST(Representational state transfer) 기반으로 만들어진 API입니다.
REST는 HTTP의 장접을 최대한 활용할 수 있는 아키텍처이고, 자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미합니다.
REST의 원칙을 지킨 서비스 디자인을 RESTful이라고 표현합니다.
RESTful API는 REST를 기반으로 데이터를 ‘웹 URL’을 통해 API를 일관성 있게 사용가능하게 하는 인터페이스입니다. 이를 통해 개발자들이 일관성있게 API를 만들고 이용하는 것을 도와줍니다.
REST API를 실행시키는 시스템은 효율적으로 확장이 가능합니다.
서버와 클라이언트의 상호작용을 최적화하기 때문입니다. (잘 관리되는 캐싱으로 클라이언트-서버 통신 단축 등)
이러한 특징들이 퍼포먼스를 향상시킬 수 있습니다.
RESTful 웹 서비스는 클라이언트와 서버의 분리를 가능하게 한다
다양한 서버 구성 요소를 단순화하고 분리하여 각 부분이 독립적으로 발전할 수 있도록 합니다
API 설계에 영향을 주지 않고 다양한 프로그래밍 언어로 클라이언트 및 서버 애플리케이션을 모두 작성할 수 있습니다.
일관된 인터페이스를 사용하기 위해선 몇가지 규약들이 필요합니다.
그리고 리소스는 single URL을 통해 식별 가능하도록 유일해야 합니다.
일관된 인터페이스는 데이터 스토리지로부터 유저를 분리시킵니다.
클라이언트의 도메인은 UI와 request 수집에 관한 것이고,서버의 도메인은 데이터 액세스, 워크로드 관리, 보안에 관한 것입니다.
클라이언트와 서버를 분리하면 각각을 서로 독립적으로 개발하고 개선할 수 있습니다.
클라이언트에서 서버로 보내는 요청에는 서버가 이를 이해하고 적절히 처리할 수 있도록 필요한 모든 정보가 포함되어야 합니다. 서버는 클라이언트 상태에 대한 어떠한 정보도 가지고 있을 수 없습니다.
요청에 대한 응답 내의 데이터는 캐시 가능 또는 캐시 불가능으로 레이블이 지정되어야 합니다.
REST는 계층적 구조를 허용함으로써, 각 컴포넌트들은 상호작용할 때 바로 위 계층 너머를 볼 수 없습니다.
REST API는 스크립트 형태로 코드를 다운로드하고 실행합니다.
서버는 XML 또는 JSON 형태로 데이터를 보내는데, 이는 서버가 필요할 때 실행 가능한 코드를 클라이언트로 보낼 수 있게 합니다.
동사보다는 명사를, 대문자보다는 소문자를 사용합시다.
따라서 이름에 get 같이 행위에 대한 표현이 들어가면 안됩니다.
# ❌ bad
GET /getTodos/1 
GET /todos/show/1
# ✅ good
GET /todos/1
DELETE /todos/2HTTP 요청 메서드는 클라이언트가 서버에게 요청의 종류와 목적을 알리는 방법입니다.
주로 get, post, put patch, delete를 사용해서 CRUD(Create, Replace, Update, Delete) 를 구현합니다.
Read & Retrieve 할 때 사용합니다.
만약에 GET요청이 성공적으로 이루어진다면 XML이나 JSON과 함께 200 (Ok) 응답 코드를 리턴합니다.
error가 발생하면 주로 404 (Not found) 또는 400 (Bad request) 발생합니다.
데이터를 조회하는 것이기 때문에 요청시에 Body 값과 Content-Type 값이 비워져있습니다.
GET은 캐싱이 가능하여 같은 데이터를 한번 더 조회할 경우에 저장한 값을 사용하여 조회 속도가 빨라집니다.
const xhr = new XMLHttpRequest();
// ✅ GET: get todos
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
// HTTP 요청
xhr.send();
xhr.onload = () => {
    if (xhr.status === 200) {
        document.querySelector('div').textContent = xhr.response;
    } else {
        console.log('Error', xhr.status, xhr.statusText);
    }
}
새로운 리소스를 create할 때 사용됩니다.
성공적으로 완료하면 201 (Created) 응답을 반환합니다.
URL을 통해서 데이터를 받지 않고, Body 값을 통해서 받습니다.
이때, 데이터를 생성하는 것이기 때문에 요청시에 Body 값과 Content-Type 값을 작성해야합니다.
body : {date : "example"}
Content-Type : "application/json"⚠️ POST 요청은 idempotent 하지 않습니다.
같은 POST 요청을 반복해서 했을 때 항상 같은 결과물이 나오는 것을 보장하지 않는다!
const xhr = new XMLHttpRequest();
// ✅ POST: create new todo 
xhr.open('POST', 'https://jsonplaceholder.typicode.com/todos/1/posts');
// payload의 MIME type 지정
xhr.setRequestHeader('content-type', 'application/json');
// HTTP request 
// send payload to server
xhr.send(JSON.stringify({ title: "New Title!", completed: false}));
xhr.onload = () => {
    if (xhr.status === 200 || xhr.status === 201) {
        document.querySelector('div').textContent = xhr.response;
    } else {
        console.log('Error', xhr.status, xhr.statusText);
    }
}
id를 제외한 특정 리소스 전체를 업데이트하기 위해 사용합니다.
데이터를 수정하는 것이기 때문에 요청시에 Body 값과 Content-Type을 함께 보내야 합니다.
⚠️ PUT 요청은 idempotent 합니다.
요청할 때마다 데이터를 생성하는 POST와는 다르게, 동일한 PUT 요청을 여러 번 호출하면 항상 동일한 결과가 생성됩니다.
const xhr = new XMLHttpRequest();
// ✅ id: 1 리소스로 요소를 특정합니다
xhr.open('PUT', 'https://jsonplaceholder.typicode.com/posts/1');
xhr.setRequestHeader('content-type', 'application/json');
xhr.send(JSON.stringify({ userId: 3, title: "New Title!", completed: false}));
xhr.onload = () => {
    if (xhr.status === 200) {
        document.querySelector('div').innerHTML = xhr.response;
    } else {
        console.log('Error', xhr.status, xhr.statusText);
    }
}
// HTTP request
xhr.send(JSON.stringify({ userId: 3, id: 3, title: "New Title!", body: "hello world!"}));server로 보낼 object의 key-value 부분만 바꿔서 request 해 보았다.

이렇게 모든 값 전체가 교체되지만 id는 바뀌지 않는 것을 볼 수 있습니다.
왜냐하면 처음에 id로 todo를 특정하여 리소스 전체를 교체했기 때문입니다.
전체를 업데이트하는 PUT과는 다르게, 특정 리소스의 일부를 수정할 때 사용합니다.
예를 들어 todo의 completed 부분만 true -> false 바꿀 때 유용합니다.
데이터를 수정하는 것이기 때문에 요청시에 Body 값과 Content-Type을 함께 보내야 합니다.
⚠️ POST 요청은 idempotent 하지 않습니다.
const xhr = new XMLHttpRequest();
// ✅ id: 1 리소스로 요소를 특정합니다
xhr.open('PUT', 'https://jsonplaceholder.typicode.com/posts/1');
xhr.setRequestHeader('content-type', 'application/json');
xhr.send(JSON.stringify({ completed: false }));
xhr.onload = () => {
    if (xhr.status === 200) {
        document.querySelector('div').innerHTML = xhr.response;
    } else {
        console.log('Error', xhr.status, xhr.statusText);
    }
}
리소스에서 id를 사용하여 특정 요소를 삭제합니다.
데이터를 삭제하는 것이기 때문에 요청시에 Body 값과 Content-Type 값이 비워져있습니다.
URL을 통해서 어떠한 데이터를 삭제할지 parameter를 받습니다.
데이터 삭제에 성공한다면 Body 값 없이 성공 응답만 보내게 됩니다.
const xhr = new XMLHttpRequest();
// ✅ id: 1인 todo를 삭제합니다.
xhr.open('DELETE', 'https://jsonplaceholder.typicode.com/posts/1');
xhr.send();
xhr.onload = () => {
    if (xhr.status === 200) {
        document.querySelector('div').innerHTML = xhr.response;
    } else {
        console.log('Error', xhr.status, xhr.statusText);
    }
}