개요
네트워크에서 HTTP 통신을 이용하여 리소스를 가져오는(fetch
) 역할을 한다. Fetch API 이전에는 XMLHttpRequest 와 Ajax 가 있었다. 다만, XMLHttpRequest
는 스펙 자체가 사용하기 조금 불편하다는 단점이 있었고, Ajax
는 JQuery 의존성이 걸려있다는 단점이 있었다.
이러한 문제들을 해결한 유연하고 강력한 API 가 fetch
API 이다.
특징
요청으로 Request 인터페이스를 이용하고 반환 값으로 Response 오브젝트를 이용하는데, 응답은 비동기이기에 이를 resolve()
하여 Promise<Response>
형태로 반환한다.
fetch()
의 결과로 반환되는 Promise
객체는 오직 네트워크 에러가 발생했을 때만 reject
를 하고 HTTP 상태 코드만 있다면 404
와 같은 HTTP 응답 코드에 대해서는 resolve
하여 fulfilled
상태가 된다.
이로 인해, HTTP 에서 200 OK
가 아닌 다른 응답코드를 주더라도 then()
에서 응답 코드에 따른 처리가 가능하다. Response.ok 와 같이 200 OK
인지 아닌지 나타내는 프로퍼티도 존재하고 Response.status 와 같이 상태코드 자체를 나타내는 프로퍼티도 있어서 편한대로 쓰면 된다.
호출 시 호출하는 웹페이지의 connect-src
(Content Security Policy) 지시자에 따라 제어되어 잘 동작하지 않는다면 서버의 보안 설정을 한번 더 확인해보자.
fetch()
메서드의 파라미터는 Request 객체의 생성자와 같다.
Ajax 와의 차이
ajax
는200 OK
외에404 Not Found
같은 응답코드가 왔을 때 이를 에러처리 하는데,fetch API
는 네트워크 문제가 있지 않는 이상 모든 HTTP 코드를resolve
한다.fetch()
메서드는 구형 브라우저에서 사용했을 때, credentials 와 함께 사용되지 않는이상, cross-origin 요청에서 쿠키를 보내지 않는다. 또한 응답으로 돌아온 쿠키도 세팅하지 않는다.- Ajax 는
jqXHR
라는 자체적으로 생성한XMLHTTPRequest
의 상위 집합을 사용하는 반면fetch
는Promise<Response>
오브젝트를 리턴한다.
사용하기
fetch('http://example.com/movies.json')
.then(response => response.json())
.then(data => console.log(data));
Promise<Response>
- 콜백에서
Response.json()
을 반환
- 콜백에서
Promise<Json>
받기- 받은 Json을 이용해 비즈니스 로직 처리
실제 JSON 을 가지기까지 Promise
를 2번이나 까줘야(?) 한다. .then()
의 첫번째 콜백에 상태코드에 따른 처리를 해주면 되고, 두번째 .then()
에서는 넘겨받은 (아마) JSON 을 가지고 비즈니스에 관여하는 로직을 만들면 된다.
지원하는 요청 옵션 살펴보기
fetch
API 는 2번째 파라미터로 init
오브젝트를 받는다. 이 오브젝트를 이용하여 HTTP 요청에 이용되는 다양한 옵션을 커스터마이징할 수 있다.
// Example POST method implementation:
async function postData(url = '', data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData('https://example.com/answer', { answer: 42 })
.then(data => {
console.log(data); // JSON data parsed by `data.json()` call
});
인증 정보 함께 보내기
fetch('https://example.com', {
credentials: 'include'
});
위와 같이 fetch
API 의 두번째 오브젝트에 credentials: 'include'
를 담아 보내면, same-origin
혹은 cross-origin
으로 보낼 때 모두 credentials
를 함께 보내게 된다.
JSON 보내기
const data = { username: 'example' };
fetch('https://example.com/profile', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
Content-Type 을 잘 맞춰주고, 자바스크립트의 JSON 오브젝트 타입을 그대로 사용할 수는 없으니 당연히 JSON.stringify()
를 해주어야 한다.
파일 업로드하기
const formData = new FormData();
const fileField = document.querySelector('input[type="file"]');
formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);
fetch('https://example.com/profile/avatar', {
method: 'PUT',
body: formData
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});
FormData 오브젝트를 이용하면 상대적으로 쉽게 가능하다.
여러 파일 업로드하기
const formData = new FormData();
const photos = document.querySelector('input[type="file"][multiple]');
formData.append('title', 'My Vegas Vacation');
for (let i = 0; i < photos.files.length; i++) {
formData.append(`photos_${i}`, photos.files[i]);
}
fetch('https://example.com/posts', {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});
FormData
를 이용하는 것은 비슷한데, <Input />
태그에서 파일을 여러 개 선택할 수 있도록 해주면 된다.
문법
fetch(resource)
fetch(resource, init)
레퍼런스
'자바스크립트 > 개념' 카테고리의 다른 글
자바스크립트 클로저 (Closure) 란 무엇인가? (0) | 2022.07.13 |
---|---|
자바스크립트 var , let , const 의 스코프 차이에 대해 알아보자. (0) | 2022.07.13 |
자바스크립트의 Proxy 란? (0) | 2022.06.30 |
자바스크립트 Promise 알아보기 (0) | 2022.06.25 |
자바스크립트 XMLHttpRequest 알아보기 (0) | 2022.06.25 |