fetch
함수는 특정 URL로 부터 정보를 받아오는데, HTTP 요청을 전송할 URL과 HTTP 요청 메서드, HTTP 요청 헤더, 페이로드 등을 설정한 객체를 전달한다.
fetch
함수는 XMLHttpRequest 객체와 마찬가지로 HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 Web API이다.
fetch
함수는 프로미스를 지원하기 때문에 비동기 처리를 위한 콜백 패턴의 단점에서 자유롭다.
기본 문법
fetch(url, {options})
매개변수
url
: 접근하고자 하는 URLoptions
: 선택 매개변수,method
와header
,body
등을 지정할 수 있음
GET
요청은 정보를 요청(조회)하기 위해 사용되는 메서드로 fetch
함수에 첫 번째 인수로 HTTP 요청을 전송할 URL만 전달하면 GET
요청을 전송한다.
fetch
함수는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환하므로 후속 처리 메서드 then
을 통해 프로미스가 resolve한 Response 객체를 전달받을 수 있다.
Response 객체는 HTTP 응답을 나타내는 다양한 프로퍼티를 제공하는데, 예를 들어 fetch
함수가 반환한 프로미스가 래핑하고 있는 MINE 타입이 application/json인 HTTP 응답 바디를 얻으려면 Response 객체에서 HTTP 응답 바디를 역직렬화하는 Response.prototype.json
메서드를 사용한다.
fetch API의 응답(response) 객체는 json()
을 제공하고 있어 JSON.parse()
대신 사용할 수 있다.
fetch('https://jsonplaceholder.typicode.com/todos/1')
// json 메서드를 사용하여 Response 객체에서 HTTP 응답 바디를 획득하여 역직렬화한다.
.then(response => response.json())
// json은 역직렬화된 HTTP 응답 바디다.
.then(json => console.log(json))
// {userId: 1, id: 1, title: 'delectus aut autem', completed: false}
fetch
+promise
방식(response, data 변수명 상관없음)const getQuestion = () => { fetch('http://localhost:4000/discussions') .then((response) => response.json()) // response 변수명 상관없음 .then((data) => setQuestion(data)); // data 변수명 상관없음 }
fetch
+async/await
방식(response, data 변수명 상관없음)const getQuestion = async () => { const response = await fetch('http://localhost:4000/discussions'); const data = await response.json(); setQuestion(data); }
역직렬화하는 JSON.parse()와 response.json()의 차이
JSON.parse()
에는 응답(response) 바디만을 넣어야 한다. 바디와 헤더가 들어가면 데이터를 읽어오지 못한다.response.json()
에는 응답 헤더가 들어와도 바디만 읽어서 불러온다.
POST
요청은 정보를 전송(추가)하기 위해 사용되는 메서드로 fetch
함수에 첫 번째 인수로 HTTP 요청을 전송할 URL를 전달하고, 두 번째 인수로 method
, header
, body
등을 지정하여 POST
요청을 전송한다.
fetch API를 사용하는 경우 수동으로 JSON.stringify()
를 사용해서 객체를 문자열화 한 다음 body할당해야 한다.
fetch를 사용하면 명시적으로 Content-Type
을 application/json
으로 설정해야 한다.
fetch('https://jsonplaceholder.typicode.com/todos', {
method: 'POST',
headers: {
// JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할
'Content-Type': 'application/json',
},
body: JSON.stringify({
userId: 1,
title: 'JavaScript',
completed: false
}),
})
.then(response => response.json())
.then(json => console.log(json))
// {userId: 1, id: 201, title: 'JavaScript', completed: false}
fetch
+promise
방식(response, data 변수명 상관없음)const handleButtonClick = () => { fetch('http://localhost:4000/discussions', { method: 'POST', // JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할 headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: question.length + 10, createdAt: new Date(), author: author, title: title, url: "#", answer: null, avatarUrl: 'https://source.boringavatars.com/beam', }), }) .then((response) => response.json()) .then((data) => getQuestion(data)); };
fetch
+async/await
방식(response, data 변수명 상관없음)const handleButtonClick = async () => { const response = await fetch('http://localhost:4000/discussions', { method: 'POST', // JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할 headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: question.length + 10, createdAt: new Date(), author: author, title: title, url: "#", answer: null, avatarUrl: 'https://source.boringavatars.com/beam', }), }) const data = await response.json() getQuestion(data) };
PUT
요청은 정보를 완전 대체하기 위해 사용되는 메서드로 fetch
함수에 첫 번째 인수로 HTTP 요청을 전송할 URL를 전달하고, 두 번째 인수로 수정할 특정 필드를 지정하여 PUT
요청을 전송한다.fetch('https://jsonplaceholder.typicode.com/todos/1', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
completed: true
}),
})
.then(response => response.json())
.then(json => console.log(json))
// {id: 1, completed: false}
PATCH
요청은 정보를 부분적으로 수정하기 위해 사용되는 메서드로 fetch
함수에 첫 번째 인수로 HTTP 요청을 전송할 URL를 전달하고, 두 번째 인수로 수정할 특정 필드를 지정하여 PATCH
요청을 전송한다.fetch('https://jsonplaceholder.typicode.com/todos/1', {
method: 'PATCH',
headers: {
// JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할
'Content-Type': 'application/json',
},
body: JSON.stringify({
completed: true
}),
})
.then(response => response.json())
.then(json => console.log(json))
// {userId: 1, id: 1, title: 'delectus aut autem', completed: true}
PUT과 PATCH의 차이점
PUT
은 user data 구조가id
,title
,body
라고 한다면, 회원정보 수정시PUT
은id
를 찾아title
만 업데이트 하더라도 항상 모든 필드값을 가져와서 모든 필드를 항상 새로운 값으로 교체한다.PUT
은 모든 속성을 수정하기 때문에title
데이터만 보내주면 원래 있던id
,body
데이터는 사라진다.
PATCH
는 user data의 구조가id
,title
,body
라고 한다면, 회원정보 수정시PATCH
는id
를 찾아title
만 업데이트할때id
와title
만 받아와서해당 부분을 업데이트 한다.
DELETE
요청은 정보를 삭제하기 위해 사용되는 메서드로 fetch
함수에 첫 번째 인수로 HTTP 요청을 전송할 URL를 전달하고, 두 번째 인수로DELETE
메서드를 지정하여 DELETE
요청을 전송한다.fetch('https://jsonplaceholder.typicode.com/todos/1', {
method: 'DELETE',
})
.then(response => response.json())
.then(json => console.log(json))
fetch
+promise
방식(response 변수명 상관없음)const handleDeleteClick = (id) => { fetch(`http://localhost:4000/discussions/${id}`, { method: 'DELETE' }) .then((response) => getQuestion(response)) }
fetch
+async/await
방식(response 변수명 상관없음)const handleDeleteClick = async (id) => { const response = await fetch(`http://localhost:4000/discussions/${id}`, { method: 'DELETE' }) getQuestion(response) }