fetch() 소개

fetch()를 사용하면 XMLHttpRequest (XHR)와 유사한 네트워크 요청을 실행할 수 있습니다. 주요 차이점은 Fetch API가 프로미스를 사용한다는 것입니다. 프로미스에는 XMLHttpRequest API의 복잡한 콜백을 피할 수 있도록 더 간단한 API가 포함되어 있습니다.

브라우저 지원

  • 42명
  • 14
  • 39
  • 10.1

소스

이전에 프로미스를 사용한 적이 없다면 자바스크립트 프로미스 소개를 확인하세요.

기본 가져오기 요청

다음은 XMLHttpRequest로 구현한 다음 fetch로 구현한 예입니다. URL을 요청하고 응답을 받아 JSON으로 파싱하려고 합니다.

XMLHttpRequest

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

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

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

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

가져오기

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

fetch('./api/some.json')
  .then(
  function(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(function(err) {
    console.log('Fetch Error :-S', err);
  });

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

응답 메타데이터

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

fetch('users.json').then(function(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);
});

응답 유형

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

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

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

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

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

  • same-origin는 동일한 출처의 애셋에 대한 요청에서만 성공하고 다른 모든 요청은 거부합니다.
  • cors는 동일한 출처의 애셋과 적절한 COR 헤더를 반환하는 다른 출처에 대한 요청을 허용합니다.
  • cors-with-forced-preflight는 요청을 하기 전에 실행 전 검사를 수행합니다.
  • no-cors는 CORS 헤더가 없는 다른 출처에 대해 요청을 실행하여 opaque 응답을 발생시키기 위한 것이지만 언급된 바와 같이 현재 창 전역 범위에서는 불가능합니다.

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

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
    .then(function(response) {
    return response.text();
    })
    .then(function(text) {
    console.log('Request successful', text);
    })
    .catch(function(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(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

이 예에서는 response.status를 확인하고 확인된 프로미스를 Promise.resolve()로 반환하거나 거부된 프로미스를 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(function (data) {
    console.log('Request succeeded with JSON response', data);
    })
    .catch(function (error) {
    console.log('Request failed', error);
    });

가져오기 요청을 사용하여 사용자 인증 정보 전송

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

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