📌 참고 사이트
REST API와 Fetch api (velog.io)
REST API와 Fetch api
해당 포스팅에서는 Rest api와 Fetch api에 대해 다루었습니다.
velog.io
HTTP - 위키백과, 우리 모두의 백과사전 (wikipedia.org)
HTTP - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. HTTP(HyperText Transfer Protocol, 문화어: 초본문전송규약, 하이퍼본문전송규약)는 W3 상에서 정보를 주고받을 수 있는 프로토콜이다. 주로 HTML 문서를 주고받는 데에
ko.wikipedia.org
fetch
ko.javascript.info
📋 Fetch API의 개념
Fetch API는 HTTP request 전송 기능을 제공하는 클라이언트 사이트 Web API이다.
브라우저에 내장되어 있는 함수로, 서버와의 통신을 통해 CRUD(Create, Read, Update, Delete)를 구현할 수 있게 하고, Promise를 지원하는 내장 함수이다.
📋 HTTP
클라이언트와 서버 사이에서 이루어지는 요청(request), 응답(response) 프로토콜(통신 규약)이다.
클라이언트에서 서버로 전송되는 것은 request이고, 서버에서 클라이언트로 전달되는 것은 response이다.
ex) 클라이언트인 웹 브라우저가 HTTP를 통해 서버로부터 웹페이지(HTML)나 그림 정보를 요청하면 서버는 그 요청에 응답하여 필요한 정보를 해당 사용자에게 전달한다. 클라이언트에게 전달된 정보는 모니터와 같은 출력 장치를 통해 사용자에게 나타난다.
📋 REST API
📍 REST API란?
➡️ HTTP의 통일성을 위해 만들어진 아키텍쳐이다.
➡️ HTTP 프로토콜을 의도에 맞게 디자인하도록 유도하는 권고사항이다.
➡️ REST API만으로도 HTTP 요청의 내용을 이해할 수 있다.
📍 REST API의 3가지 요소
구성 요소 | 내용 | 표현 방법 |
자원 (Resource) | 자원 | URI (Uniform Resource Identifier, 통합 자원 식별자, URL의 상위 개념) |
행위 | 자원에 대한 행위 | HTTP 요청 메서드 (GET, POST, PUT, DELETE 등...) |
표현 | 자원에 대한 행위의 구체적 내용 | payload (전송의 근본적인 목적이 되는 데이터의 일부분(순수한 데이터)으로 그 데이터와 함께 전송되는 헤더와 메타데이터와 같은 부분은 제외) |
📍 REST API의 설계 원칙
➡️ URI는 리소스를 표현하기 위해 명사를 사용해야 한다. (동사 금지!)
// bad
GET /getTodos/1
// good
GET /todos/1
➡️ 리소스에 대한 행위는 HTTP 요청 메소드로 표현한다. (URI에 표현 X)
💡 HTTP 요청 메소드 : 클라이언트가 서버에게 요청(request) 종류와 목적(자원에 대한 행위)를 알리는 방법이다.
HTTP 요청 메소드 | 종류 | 목적 | 페이로드 |
GET | index/retrieve | 모든/특정 리소스 취득 | X |
POST | create | 리소스 생성 | O |
PUT | replace | 리소스의 전체 교체 | O |
PATCH | modify | 리소스의 일부 수정 | O |
DELETE | delete | 모든/특정 리소스 삭제 | X |
📋 fetch 사용하기
📍 기본적인 사용법
const promise = fetch(url, [, options]);
1️⃣ 파라미터
- 첫번째 인자 : HTTP 요청을 전달할 url (GET 요청을 보낼 때는 뒤에 options를 작성하지 않고 url만 작성해 주면 됨.)
- 두번재 인자 : 옵션 객체 (HTTP 요청 메소드, HTTP 요청 헤더, payload 등)
2️⃣ Response 객체
HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환한다.
then 메서드를 사용하여 fetch가 반환한 Promise 객체를 받고, Response 객체의 내용에 대하여 확인해 볼 수 있다.
(then 메서드는 프로미스가 처리(resolve 실행)되고 해당 응답 객체가 준비되면 호출됨.)
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => console.log(response));
// 결과
Promise {<pending>} // fecth 함수에 의해 반환된 프로미스
// fetch가 반환한 프로미스에서 resolve되어 있는 응답 객체 내용
Response {type: 'cors', url: 'https://jsonplaceholder.typicode.com/todos/1',
redirected: false, status: 200, ok: true, …}
response 객체는 다음과 같은 것들을 읽어올 수 있다.
➡️ HTTP 응답 성공 여부
Response.ok 속성으로 나타내어진다.
값으로는 true나 false가 들어간다. (상태 코드가 200~299일 경우 true, 다른 경우에는 false)
➡️ HTTP 응답 상태
클라이언트가 서버를 향해 요청을 보내면 서버에서 그 결과가 어떻게 되었는지 알려준다.
상태 코드 | 클래스 | 설명 |
1XX | Informational | 요청을 받아들여 처리 중 |
2XX | Success | 요청을 정상적으로 처리했음 |
3XX | Redirection | 요청을 완료하기 위해서 추가 동작 필요 |
4XX | Client Error | 서버는 요청 이해 불가능 |
5XX | Server Error | 서버는 요청 처리 실패 |
➡️ HTTP 응답 헤더(header), HTTP 응답 전문(body)
HTTP 헤더는 클라이언트와 서버가 요청 또는 응답으로 부가적인 정보를 전송할 수 있도록 해준다.
HTTP 응답 전문에는 실제 전송을 하는 데이터가 들어 있다.
➡️ Response.redirected 메소드
3XX의 응답과 연결되어 요청을 정상적으로 처리 종료하기 위해 브라우저 측에서 특별한 처리를 수행해야 함을 나타낸다.
ex) 특정 회원 등급 게시판에 접속하려 할 때 경고 페이지로 이동
➡️ Response.prototype 메소드
Response 객체에서 HTTP 응답 body (response.body)를 취득하여 역직렬화 한다.
역직렬화 ex) JSON을 역직렬화하려면 JSON.parse를 사용한다. 서버에서는 클라이언트에 JSON 데이터를 문자열로 전송하는데, JSON.parse를 사용하여 JSON 포맷의 문자열을 객체로 변환할 수 있다.
📍 GET 방식
GET 방식에서는 보낼 데이터가 없기 때문에 headers와 body 옵션을 적어주지 않는다.
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => response.json())
.then((data) => console.log(data));
// {userId: 1, id: 1, title: 'delectus aut autem', completed: false}
❓ JSON.parse(문자열)와 response.json()의 차이
➡️ JSON.parse(문자열) : JSON 형식의 문자열을 JS 객체로 변환하는 메서드로, 문자열을 직접 파싱하고 결과를 반환한다. 따라서 문자열을 파싱할 때 발생하는 오류에 대한 예외적 처리가 필요하다.
➡️ fetch에서의 response.json() : 웹 브라우저의 Fetch API 또는 Node.js HTTP 모듈과 함께 사용되는 메서드이다. 네트워크 요청으로부터 받은 JSON 형식의 응답을 처리하기 위해 사용된다. response.json()은 HTTP 응답을 비동기적으로 처리하고 JSON 형식의 데이터를 추출해 JS 객체로 반환한다.
네트워크 요청이 실패하는 경우에 대한 예외 처리도 포함되어야 한다.
📍 POST 방식
GET 방식 때와는 다르게 HTTP 요청 메소드를 나타내는 method와 Content-Type이 명시된 HTTP 헤더를 나타내는 headers와 payload(전송되는 데이터 자체, request의 body 안에 넣는 데이터 객체)가 담긴 body 이렇게 3개의 프로퍼티를 가진 객체를 url과 함께 인자로 넣어 주어야 한다.
fetch('https://jsonplaceholder.typicode.com/posts', {
// method 옵션 POST 지정
method: 'POST',
// JSON 포맷
headers: {
// json 형식으로 데이터를 보내라고 알려주는 Content-Type
'Content-Type': 'application/json',
},
// body에는 payload 넣기
body: JSON.stringify({
title: 'Test',
body: 'I am testing!',
userId: 1,
}),
})
.then((response) => response.json())
.then((data) => console.log(data));
// {title: 'Test', body: 'I am testing!', userId: 1, id: 101}
💡 상태 코드(status code)가 201이 뜨는 것은 POST 작업이 성공적으로 이루어졌다는 의미이고, 생성된 자원은 response 메시지의 본문 (body)에 등록된다.
* 요청 header 중 일반 헤더 살펴보기
* 요청 body (payload) 살펴보기
📍 PUT 방식
put 방식에서도 method, headers, body를 프로퍼티로 가지는 객체를 인자로 넣어 주어야 하는데 method를 'PUT'으로 작성하는 것 빼고 POST 방식과 사용 방식이 같다. body에는 수정하고 싶은 내용을 작성하면 된다.
❓ POST와 PUT의 차이점
➡️ POST : 리소스의 생성을 담당하고, 요청 시마다 새로운 리소스가 생성된다. (멱등하다.)
➡️ PUT : 리소스의 생성과 수정을 담당하고, 요청 시마다 같은 리소스를 반환한다. (멱등하지 않다.)
RESTful한 세계에서의 POST와 PUT의 차이, 거기에 PATCH까지 (velog.io)
RESTful한 세계에서의 POST와 PUT의 차이, 거기에 PATCH까지
HttpResponseHTTP/1.1 200 OK{ “id”: 1, “name”: “뽀로로”, “grade”: 1}HttpResponseHTTP/1.1 200 OK{ “id”: 1 “name”: “뽀로로”, “grade”: 2}HTTP/1.1 200 OK{ “id”
velog.io
📍 DELETE 방식
DELETE 방식에서는 보낼 데이터가 없기 때문에 headers와 body 옵션을 적지 않는다.
method 옵션만 DELETE로 설정하면 된다.
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'DELETE',
})
.then((response) => response.json())
.then((data) => console.log(data));
// {}
✏️ fetch를 사용해 Github에서 사용자 정보 가져오기
GitHub 사용자 이름이 담긴 배열을 인자로 받는 비동기 함수 getUsers(names)를 만든 후, Github에서 fetch한 사용자 정보들이 담긴 배열을 반환하는 함수를 만들어 보자.
사용자명에 해당하는 사용자 정보를 가져오려면 Github API https://api.github.com/users/사용자명 에 요청을 보내면 된다. 다음 조건들을 지켜 과제를 완수해 보자.
1️⃣ 사용자당 fetch 요청은 한 번만 수행해야 한다.
2️⃣ 데이터가 최대한 일찍 도착할 수 있도록 각 요청은 다른 요청의 결과를 기다려서는 안 된다.
3️⃣ 요청에 실패하거나 존재하지 않는 사용자에 대한 요청을 보냈다면 null을 return하고 배열 요소에 담아야 한다.
🅰️
// 비동기 getUsers 함수, 매개변수로는 names 배열이 들어감.
async function getUsers(names) {
let jobs = []; // 사용자 정보들이 담길 배열
// 사용자 이름 하나씩 순회하기
for (let name of names) {
let job = fetch(`https://api.github.com/users/${name}`)
.then(successResponse => {
// 응답 상태 코드가 200이 아니면 null 반환
if (successResponse.status !== 200) {
return null;
}
// 응답 상태 코드가 200인 경우에만 .json()을 호출해 객체를 읽는다.
else {
return successResponse.json();
}
// fetch에 실패하면 null 반환
}).catch(failResponse => {
return null;
})
}
// Promise.all(jobs)는 Promise.all()은 jobs 배열 원소인 모든 입력 Promise가 이행되거나 거부될 때까지 기다린 다음,
// 각 Promise의 결과(resolve되거나 reject된 값)를 배열로 반환하는 역할을 한다.
let results = await Promise.all(jobs);
return results;
}
// result 값
// 0: {login: 'C17AN', id: 26535030, node_id: 'MDQ6VXNlcjI2NTM1MDMw', avatar_url: 'https://avatars.githubusercontent.com/u/26535030?v=4', gravatar_id: '', …}
// 1: {login: 'Violet-Bora-Lee', id: 6451384, node_id: 'MDQ6VXNlcjY0NTEzODQ=', avatar_url: 'https://avatars.githubusercontent.com/u/6451384?v=4', gravatar_id: '', …}
// 2: null
'Javascript study' 카테고리의 다른 글
[JS] 이벤트 루프 (0) | 2023.09.05 |
---|---|
[JS] async와 await (0) | 2023.09.04 |
[JS] Promise (0) | 2023.08.28 |
[JS] IndexedDB (2) | 2023.08.27 |
[JS] Closure (0) | 2023.08.27 |
댓글