fetch() 소개

fetch()를 사용하면 XMLHttpRequest (XHR)와 유사한 네트워크 요청을 할 수 있습니다. 주요 차이점은 Fetch API가 Promises를 사용한다는 점입니다. Promises에는 XMLHttpRequest API의 복잡한 콜백을 피하는 데 도움이 되는 더 간단한 API가 있습니다.

브라우저 지원

  • Chrome: 42.
  • Edge: 14.
  • Firefox: 39.
  • Safari: 10.1

소스

이전에 Promises를 사용한 적이 없다면 JavaScript Promises 소개를 확인하세요.

다음은 XMLHttpRequest로 구현된 다음 fetch로 구현된 예입니다. URL을 요청하고 응답을 가져와 JSON으로 파싱하려고 합니다.

XMLHttpRequest에는 성공 및 오류 사례를 처리하는 두 개의 리스너와 open()send() 호출이 필요합니다. MDN 문서의 예

function reqListener () {
 
const data = JSON.parse(this.responseText);
  console
.log(data);
}

function reqError (err) {
  console
.log('Fetch Error :-S', err);
}

const oReq = new XMLHttpRequest();
oReq
.onload = reqListener;
oReq
.onerror = reqError;
oReq
.open('get', './api/some.json', true);
oReq
.send();

가져오기

가져오기 요청은 다음과 같습니다.

fetch('./api/some.json')
 
.then(response => {
   
if (response.status !== 200) {
      console
.log(`Looks like there was a problem. Status Code: ${response.status}`);

     
return;
   
}

   
// Examine the text in the response
    response
.json().then(function(data) {
      console
.log(data);
   
});
 
})
 
.catch(err => {
    console
.log('Fetch Error :-S', err);
 
});

fetch() 요청은 XHR 예와 동일한 작업을 실행하는 데 한 번의 호출만 필요합니다. 응답을 처리하려면 먼저 응답 상태가 200인지 확인한 다음 응답을 JSON으로 파싱합니다. fetch() 요청에 대한 응답은 스트림 객체입니다. 즉, json() 메서드를 호출한 후 프로미스가 반환됩니다. 스트림은 비동기식으로 발생합니다.

응답 메타데이터

이전 예에서는 Response 객체의 상태와 응답을 JSON으로 파싱하는 방법을 보여줍니다. 헤더와 같이 액세스하려는 다른 메타데이터를 처리하는 방법은 다음과 같습니다.

fetch('users.json').then(response => {
  console
.log(response.headers.get('Content-Type'));
  console
.log(response.headers.get('Date'));

  console
.log(response.status);
  console
.log(response.statusText);
  console
.log(response.type);
  console
.log(response.url);
});

응답 유형

가져오기 요청을 실행하면 응답에 response.type('basic', 'cors' 또는 'opaque')가 제공됩니다. 이러한 types는 리소스의 출처를 나타내며 이를 사용하여 응답 객체를 처리하는 방법을 결정할 수 있습니다.

브라우저가 동일한 출처의 리소스를 요청하면 응답에는 응답에서 볼 수 있는 항목에 대한 제한이 있는 basic 유형이 있습니다.

다른 출처의 리소스에 대한 요청이 이루어지고 해당 출처에서 CORs 헤더를 반환하면 유형은 cors입니다. cors 응답은 basic 응답과 유사하지만 볼 수 있는 헤더를 Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma로 제한합니다.

opaque 응답은 CORS 헤더를 반환하지 않는 다른 출처에서 가져옵니다. 불투명한 응답을 사용하면 반환된 데이터를 읽거나 요청 상태를 볼 수 없으므로 요청이 성공했는지 확인할 수 없습니다.

특정 요청 유형만 확인되도록 가져오기 요청의 모드를 정의할 수 있습니다. 설정할 수 있는 모드는 다음과 같습니다.

  • same-origin는 동일한 출처의 애셋 요청에 대해서만 성공하고 다른 모든 요청은 거부합니다.
  • cors는 동일한 출처 및 적절한 CORs 헤더를 반환하는 다른 출처의 애셋에 대한 요청을 허용합니다.
  • cors-with-forced-preflight는 요청하기 전에 사전 비행 확인을 실행합니다.
  • no-cors는 CORS 헤더가 없고 opaque 응답을 반환하는 다른 출처에 요청을 보내기 위한 것이지만, 앞서 언급한 대로 현재는 window 전역 범위에서 불가능합니다.

모드를 정의하려면 fetch 요청에 두 번째 매개변수로 옵션 객체를 추가하고 해당 객체에서 모드를 정의합니다.

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
 
.then(response => response.text())
 
.then(text => {
    console
.log('Request successful', text);
 
})
 
.catch(error => {
    log
('Request failed', error)
 
});

Promise 체이닝

약속의 큰 장점 중 하나는 약속을 서로 연결할 수 있다는 점입니다. fetch()의 경우 가져오기 요청 간에 로직을 공유할 수 있습니다.

JSON API를 사용하는 경우 상태를 확인하고 각 응답의 JSON을 파싱해야 합니다. 약속을 반환하는 별도의 함수에서 상태와 JSON 파싱을 정의하고 가져오기 요청을 사용하여 최종 데이터와 오류 사례만 처리하여 코드를 간소화할 수 있습니다.

function status (response) {
 
if (response.status >= 200 && response.status < 300) {
   
return Promise.resolve(response)
 
} else {
   
return Promise.reject(new Error(response.statusText))
 
}
}

function json (response) {
 
return response.json()
}

fetch
('users.json')
 
.then(status)
 
.then(json)
 
.then(data => {
    console
.log('Request succeeded with JSON response', data);
 
}).catch(error => {
    console
.log('Request failed', error);
 
});

이 예에서는 response.status를 확인하고 해결된 Promise를 Promise.resolve()로 반환하거나 거부된 Promise를 Promise.reject()로 반환하는 status 함수를 정의합니다. fetch() 체인에서 호출되는 첫 번째 메서드입니다.

프로미스가 확인되면 스크립트는 json() 메서드를 호출합니다. 이 메서드는 response.json() 호출에서 두 번째 프로미스를 반환하고 파싱된 JSON이 포함된 객체를 만듭니다. 파싱에 실패하면 Promise가 거부되고 catch 문이 실행됩니다.

이 구조를 사용하면 모든 가져오기 요청에서 로직을 공유할 수 있으므로 코드를 더 쉽게 유지 관리, 읽고 테스트할 수 있습니다.

POST 요청

웹 앱에서 POST 메서드로 API를 호출하고 요청 본문에 일부 매개변수를 포함해야 하는 경우가 있습니다. 이렇게 하려면 fetch() 옵션에서 methodbody 매개변수를 설정합니다.

fetch(url, {
    method
: 'post',
    headers
: {
     
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
   
},
    body
: 'foo=bar&lorem=ipsum'
 
})
 
.then(json)
 
.then(data => {
    console
.log('Request succeeded with JSON response', data);
 
})
 
.catch(error => {
    console
.log('Request failed', error);
 
});

가져오기 요청으로 사용자 인증 정보 전송

쿠키와 같은 사용자 인증 정보로 가져오기 요청을 하려면 요청의 credentials 값을 "include"로 설정합니다.

fetch(url, {
  credentials
: 'include'
})