fetch() 소개

fetch() API가 창 객체에 방문하며 XHR을 대체하려고 합니다.

너무 긴 XMLHttpRequest

fetch()를 사용하면 XMLHttpRequest(XHR)와 유사한 네트워크 요청을 실행할 수 있습니다. 주요 차이점은 Fetch API가 프로미스를 사용한다는 것입니다. 프로미스를 사용하면 더 간단하고 깔끔한 API를 사용할 수 있으므로 콜백 헬기를 피하고 XMLHttpRequest의 복잡한 API를 기억할 필요가 없습니다.

브라우저 지원

  • 42
  • 14
  • 39
  • 10.1

소스

Fetch API는 Chrome 40부터 서비스 워커 전역 범위에서 사용할 수 있었지만 Chrome 42의 창 범위에서 사용 설정될 예정입니다. 현재 사용할 수 있는 GitHub by polyfill을 가져오는 방법도 있습니다.

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

기본 가져오기 요청

먼저 XMLHttpRequestfetch로 구현된 간단한 예를 비교해 보겠습니다. URL을 요청하고 응답을 받아 JSON으로 파싱하려고 합니다.

XMLHttpRequest

XMLHttpRequest에는 성공 및 오류 사례를 처리하고 open()send() 호출을 처리하려면 리스너 2개를 설정해야 합니다. 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);
    });

먼저 응답을 JSON으로 파싱하기 전에 응답 상태가 200인지 확인합니다.

fetch() 요청의 응답은 Stream 객체입니다. 즉, json() 메서드를 호출하면 스트림 읽기가 비동기식으로 발생하므로 프로미스가 반환됩니다.

응답 메타데이터

이전 예에서는 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입니다. corsbasic 응답은 cors 응답이 볼 수 있는 헤더를 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의 주요 기능 중 하나는 함께 연결하는 기능입니다. 가져오기의 경우 가져오기 요청 간에 로직을 공유할 수 있습니다.

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'
})

FAQ

fetch() 요청을 취소하려면 어떻게 해야 하나요?

현재 가져오기를 취소할 수 있는 방법은 없지만 GitHub에서 논의 중입니다. 이 링크의 H/T @jaffathecake입니다.

폴리필이 있나요?

GitHub에는 가져오기를 위한 폴리필이 있습니다. 이 문제를 알려주신 H/T @Nexii입니다.

서비스 워커에서는 'no-cors'가 지원되지만 창에서는 지원되지 않는 이유는 무엇인가요?

이는 보안 문제로 인한 것으로, 여기에서 자세히 알아보세요.