참고) Modern Javascript Deep Dive
864p) 45장 Promise
fetch : XMLHttpRequest 객체와 비슷하게 HTTP 요청 전송 기능 제공하는 Client Side Web API(CSR)
const promise = fetch(url [, options])
fetch ('url').then(response => console.log(response));
=> Promise 객체 리턴
fetch('url')
.then(response => response.json())
.then(json => console.log(json));
Response의 HTTP body를 json화
에러처리
url이 잘못되어 404 Not found가 발생해도 catch()가 실행되지 않는다. (=Response 객체 resolve)
fetch('wrongURL')
.then(response => {
if (!response.ok) throw new Error(response.statusText);
return response.json();
})
.then(todo => console.log(todo))
.catch(err => console.error(err));
axios : 모든 HTTP 에러 reject하는 Promise 리턴 -> 후에 공부하기
<AI가 비유해준 fetch 시나리오>
fetch('/api/hamburger') 코드를 실행하면, 서버에 "햄버거 하나 주세요"라고 주문을 넣습니다.
서버는 즉시 햄버거를 주지 않습니다. 대신 "주문이 정상적으로 접수되었습니다"라는 의미의 '진동벨'(Promise)을 먼저 돌려줍니다.
잠시 후 진동벨이 울립니다. 이제 카운터로 가면 음식을 받을 수 있는 상태가 된 것입니다.
이 '진동벨이 울린 상태'가 fetch의 첫 번째 then에 해당하며, 우리는 Response라는 객체를 받습니다. 이 객체에는 주문 성공 여부(response.status) 같은 정보가 있지만, 아직 햄버거(실제 데이터)는 손에 없습니다.
카운터에서 받은 햄버거의 포장을 뜯어서 먹을 준비를 해야 합니다.
response.json() 메서드를 호출하는 것이 이 과정에 해당합니다. 서버가 보낸 JSON 형식의 데이터를 자바스크립트 객체로 변환(파싱)하는 과정인데, 이 과정도 약간의 시간이 걸리는 또 다른 약속(Promise)입니다.
포장을 다 뜯고 드디어 햄버거를 손에 쥐었습니다.
두 번째 then에서 드디어 우리가 원했던 실제 데이터(자바스크립트 객체)를 사용할 수 있게 됩니다.
async function getPosts() {
try {
// fetch는 기본적으로 GET 요청을 보냅니다.
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
// 서버 응답을 JSON 객체로 변환합니다.
const data = await response.json();
console.log('GET 요청 성공:', data);
} catch (error) {
console.error('GET 요청 실패:', error);
}
}
getPosts();
async function createPost() {
// 서버에 보낼 새로운 게시물 데이터
const newPost = {
title: '새로운 게시물',
body: '내용입니다.',
userId: 1
};
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
// 1. 요청 메서드를 'POST'로 지정
method: 'POST',
// 2. 요청 헤더에 보내는 데이터의 형식을 명시 (JSON)
headers: {
'Content-Type': 'application/json'
},
// 3. 자바스크립트 객체를 JSON 문자열로 변환하여 body에 담아 전송
body: JSON.stringify(newPost)
});
const data = await response.json();
console.log('POST 요청 성공:', data);
} catch (error) {
console.error('POST 요청 실패:', error);
}
}
createPost();
: 기존 데이터의 일부만 수정 (전체 교체 시 PUT)
async function updatePostTitle() {
// 수정할 데이터 (제목만 보냄)
const updatedData = {
title: '수정된 제목'
};
try {
// URL에 수정할 데이터의 id(예: 1)를 포함시켜야 합니다.
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(updatedData)
});
const data = await response.json();
console.log('PATCH 요청 성공:', data);
} catch (error) {
console.error('PATCH 요청 실패:', error);
}
}
updatePostTitle();
async function deletePost() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'DELETE'
});
// DELETE 요청은 성공 시 보통 빈 응답을 반환하므로, 상태 코드로 성공 여부를 확인합니다.
if (response.ok) { // response.ok는 상태 코드가 200-299 범위에 있는지 확인
console.log('DELETE 요청 성공: 게시물이 삭제되었습니다.');
} else {
console.log('DELETE 요청 실패:', response.status);
}
} catch (error) {
console.error('DELETE 요청 실패:', error);
}
}
deletePost();