This is an experimental technology
Check the Browser compatibility table carefully before using this in production.

Fetch API를 이용하면 Request나 Resposne와 같은 HTTP의 파이프라인을 구성하는 요소를 조작하는것이 가능합니다. 또한 fetch() 메서드를 이용하는 것으로 비동기 네트워크 통신을 알기쉽게 기술할 수 있습니다.

이전에 이러한 기능을  XMLHttpRequest에서 제공하고 있었습니다. Fetch는 이러한 API의 대체제로 Service Workers같은 기술로 간단히 이용하는것이 가능합니다. 또한 CORS나 HTTP확장같은  HTTP에 관련한 개념을 모아 정의하고 있습니다.

 

Fetch의 기본 스펙은jQuery.ajax()와 기본적으로 두가지가 다르다는 사실에 유념해야합니다.

  • fetch()로 부터 반환되는 Promise 객체는 HTTP error 상태를 reject하지 않습니다. HTTP Statue Code가 404나 500을 반환하더라도요. 대신 ok 상태가 false인 resolve가 반환되며, 네트워크 장애나 요청이 완료되지 못한 상태에는 reject가 반환됩니다.
  • 보통 fetch쿠키를 보내거나 받지 않습니다.  사이트에서 사용자 세션을 유지 관리해야하는 경우 인증되지 않는 요청이 발생합니다. 쿠키를 전송하기 위해서는 자격증명(credentials) 옵션을 반드시 설정해야 합니다.

 

fetch Request의 작성

기본적인 fetch는 누구라도 알기쉽고 간단하게 작성할 수 있습니다. 아래의 코드를 봐주시기 바랍니다.

var myImage = document.querySelector('img');

fetch('flowers.jpg')
.then(function(response) {
  return response.blob();
})
.then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

 

이것은 네트워크를 통해 사진을 취득하여 <img>요소에  삽입하는 스크립트입니다. fetch()의 가장 간단한 사용법으로 단 하나의 파라미터를 전달합니다. 여기서 전달하는 파라미터는 fetch()에서 취득하고 싶은 리소스나 그에대한 주소입니다. 이 코드는 promise로 감싸고 있는 Response 오브젝트를 반환합니다.

이것은 단순한 HTTP Response이며, 실제 사진이 아닙니다. response 객체로부터 사진을 가져오기 위해서는 blob() 메서드를 사용할 필요가 있습니다. (Body의 믹스인 (역주:php의 트레이드와 같은것입니다. )으로 정의되어, 이것은 Request 객체와 Response 객체의 쌍방에 구현되어 있습니다.

 

노트: http Request와 http Response의 Body mixin은 Body 컨텐츠를 다른 mine 타입으로 사용하는 비슷한 메서드를 제공하고 있습니다.  상세한 내용은 Body 섹션을 참고해 주시기 바랍니다.

objectURLBlob으로부터 추출된 것으로 img에 삽입됩니다.

Fetch Reqeust는 검색된 리소스로부터의 지시가 아닌 CSPconnect-src의 디렉티브(directive)에 의해 제어됩니다.

리퀘스트의 옵션 적용

fetch() 메서드에 두번째 파라미터를 적용하는것도 가능합니다. 다수의 설정을 컨트롤할 수 있는 초기화 옵션입니다.

var myHeaders = new Headers();

var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

fetch('flowers.jpg',myInit)
.then(function(response) {
  return response.blob();
})
.then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

모든 설정 가능한 옵션의 상세 설명은 fetch()를 참고해주시기 바랍니다.

 

자격 증명(credentials)이 포함된 Request 요청

자격 증명이 포함된 인증서를 보내도록 하려면 fetch 메서드에 credentials: 'include'를 추가하도록 합니다. 이것은 cross-origin 요청에서도 사용됩니다.

fetch('https://example.com', {
  credentials: 'include'  
})

요청하려는 URL이 호출 스크립트와 동일한 origin을 가지고 있을때만 자격증명을 전송하려면 credentials: 'same-origin'를 추가해 주시기 바랍니다.

// The calling script is on the origin 'https://example.com'

fetch('https://example.com', {
  credentials: 'same-origin'  
})

브라우저의 보안을 유지하는것 대신 자격증명을 포함하지 않는것을 원한다면 credentials: 'omit'를 작성해 주시기 바랍니다.

fetch('https://example.com', {
  credentials: 'omit'  
})

 

fetch의 성공 여부를 체크

네트워크 에러가 발생한 경우, fetch() promise는 TypeError를 반환하여 reject 상태가 됩니다. 네트워크 에러는 권한에 관련한 문제가 해당됩니다. 그렇지만 404 상태는 네트워크 에러를 구성하지 않습니다.fetch()의 성공여부를 명확하게 판별하기 위해서는 promise가  resolve 상태인가, Response.ok프로버티가 true를 반환하는가를 판단의 기준으로 둡니다. 다음의 코드를 봐 주시기 바랍니다.

fetch('flowers.jpg').then(function(response) {
  if(response.ok) {
    response.blob().then(function(myBlob) {
      var objectURL = URL.createObjectURL(myBlob);
      myImage.src = objectURL;
    });
  } else {
    console.log('Network response was not ok.');
  }
})
.catch(function(error) {
  console.log('There has been a problem with your fetch operation: ' + error.message);
});

request 객체를 fetch로 전달

fetch()를 사용해 요청한 리소스의 경로를 전달하는것 대신Request() 생성자를 사용해 Request 객체를 작성하여 fetch() 메서드를 인수로 전달하는것도 가능합니다.

var myHeaders = new Headers();

var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

var myRequest = new Request('flowers.jpg',myInit);

fetch(myRequest,myInit)
.then(function(response) {
  return response.blob();
})
.then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

fetch()메서드의 인수와 똑같은 인수를 Request()객체에 전달하여 적용하는것이 가능합니다. 또한 Request 객체의 클론을 생성하기 위해 이미 존재하는 Request 객체를 전달하는것도 가능합니다.

var anotherRequest = new Request(myRequest,myInit);

이것은 Request와 Resposne의 Body를 하나만 사용하고 있으므로 사용성이 높습니다.필요하면 init 객체를 변화시켜 Response나 Request를 재사용할 수 있도록 복사합니다.

노트: clone() 메서드를 사용해 Request 객체의 클론을 생성할 수 있습니다. 다른 카피 메서드와 약간 다른 의미가 있습니다. 이전 요청의 body가 이미 읽어들여진 경우 전자는  실패하지만 clone()메서드는 실패하지 않습니다. 이 기능은 Response와 동일합니다.

Headers

Headers 인터페이스에서  Headers() 생성자를 사용해 헤더 객체를 생성할 수 있습니다. 헤더 객체는 Key와 Value로 이루어진 간단한 Map입니다.

var content = "Hello World";
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");

똑같이 배열을 전달하거나 객체 리터럴을 생성자에 전달하는것으로 생성할 수 있습니다.

myHeaders = new Headers({
  "Content-Type": "text/plain",
  "Content-Length": content.length.toString(),
  "X-Custom-Header": "ProcessThisImmediately",
});

다음과 같은 코드로 헤더의 내용을 들여다 볼 수 있습니다.

console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue");
 
console.log(myHeaders.get("Content-Length")); // 11
console.log(myHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]
 
myHeaders.delete("X-Custom-Header");
console.log(myHeaders.getAll("X-Custom-Header")); // [ ]

이러한 몇몇개의 조작법은 ServiceWorkers에서밖에 도움되지 않지만 헤더를 조작하기 위해서 보다 나은 API를 제공하고 있습니다.

모든 Header 메서드는 유효한 HTTP 헤더가 전달되지 않았을 경우 TypeError을 반환합니다. immutable Guard(다음 섹션 참고)가 설정되어 있는 경우에도 TypeError를 반환합니다. TypeError를 반환하지 않고 실패하는 경우도 있습니다. 다음 예를 참고해주시기 바랍니다.

var myResponse = Response.error();
try {
  myResponse.headers.set("Origin", "http://mybank.com");
} catch(e) {
  console.log("은행이 아니잖아요!!");
}

헤더의 좋은 사용법으로 처리하기 전에 컨텐츠 타입으로 올바른가의 여부를 판별하는 방법이 있습니다. 예를 들어,

fetch(myRequest).then(function(response) {
  var contentType = response.headers.get("content-type");
  if(contentType && contentType.indexOf("application/json") !== -1) {
    return response.json().then(function(json) {
      // process your JSON further
    });
  } else {
    console.log("Oops, we haven't got JSON!");
  }
});

가드

헤더는 리퀘스트를 송신할 수 있으며 리스폰스를 수신할 수 있습니다. 어떤 정보를 수정할 수 있게 하기 위해, 혹은 수정하기 위해 여러 종류의 제어가 가능합니다. 헤더는 guard 프로퍼티는 이것을 가능하게 합니다. 가드는 Request나 Response에 포함되지 않지만  헤더 객체에서 조작 가능한 여러 메서드들의 사용 가능 여부에 영향을 미칩니다.

가드의 설정값은 다음과 같습니다.

  • none: 기본치
  • request: (Request.headers)에서 얻은 헤더 객체에 대한 가드
  • request-no-cors: Request.mode no-cors에 생성된 (Request.headers)에서 사용할 수 있는 값만 헤더에 확보함
  • response: (Response.headers) Response에서 얻은 객체애 대한 가드
  • immutable: 대개 ServiceWorker에서 사용됨. 헤더의 설정을 읽기 전용으로 바꿈.

메모: request에서 가드된 헤더의Content-Length 헤더는 추가나 변경할 수 없는 가능성이 있습니다.  마찬가지로 리스폰스 헤더에 Set-Cookie를 삽입하는것은 불가능합니다.ServiceWorker는 동기 Reponse를 추출하여 쿠키를 설정합니다.

Response 객체

위에서 본 바와 같이 Response 인스턴스들은 fetch() promise가 resolve됬을때 반환됩니다.

Response 객체는 개발자의 손에 의해 동적으로 만드는것이 가능합니다. 이 방법은 ServiceWorkers내에서 활약할 때가 많습니다. 예를들어 Request를 획득했을 때  respondWith()메서드에 의해 커스텀된 리스폰스를 반환하는 경우가 있습니다.

var myBody = new Blob();

addEventListener('fetch', function(event) {
  event.respondWith(
    new Response(myBody, {
      headers: { "Content-Type" : "text/plain" }
    })
  );
});

Response() 생성자는 파라미터로써 두개의 객체를 전달하는것이 가능합니다.첫번째는 Response Body, 두번째는 초기화 객체(Request()의 클론을 생성하는 방법과 비슷합니다.) 입니다.

아래는 어떤 리스폰스 객체라도 공통으로 사용되는 리스폰스 프로퍼티입니다.

  • Response.status — HTTP Status의 정수치, 기본값 200
  • Response.statusText — HTTP Status 코드의 메서드와 일치하는 문자열, 기본값은 "OK"
  • Response.ok 상술한 프로퍼티에서 사용한 HTTP Status 코드가 200에서 299중 하나임을 체크하는 값, Boolean를 반환

付記: 정적 메서드 error()는 단순한 에러 Response를 반환합니다. redirect() 메서드 또한 지정한 URL에 리다이렉트할 Response를 반환합니다. 이것들은 Service Workers에서만 사용되고 있습니다.

Body

Request, Resposne 둘다 Body를 가지고 있습니다. body는 아래에서 기술한 타입들 중 하나의 인스턴스입니다.

Body 믹스인은 RequestResponse에 구현되어, 콘텐츠를 추출하기 위해 아래의 메서드가 정의되어 있습니다. 이러한 메서드들은 전부 최종적으로 요청으로 반환된 값을 내장하고 있는 promise를 반환합니다.

이것들은 비 텍스트 데이터를 XHR보다 훨씬 간단하게 사용하는것을 도와줍니다.

Request 바디는 body 파라미터를 전달하는 것으로 설정할 수 있습니다.

var form = new FormData(document.getElementById('login-form'));
fetch("/login", {
  method: "POST",
  body: form
})

Request와 Resposne(fetch() 함수의 확장) 둘 다 컨텐츠 타입을 알아서 결정하려고 합니다. Request 또한 함수 내부적으로 자동으로 컨텐츠 타입 헤더가 설정되어 있습니다.

사양 스테이터스 코멘트
Fetch Living Standard 초기정의

Polyfill

Fetch를 지원하지 않는 브라우저를 위해 미지원 브라우저를 위한 Fetch Polyfill이 지원되고 있습니다.

브라우저 구현 현황

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

기능 Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
기본지원 42
41 behind pref
 
39 (39)
34 behind pref
No support

29
28 behind pref

No support
기능 Android Firefox Mobile (Gecko) Firefox OS (Gecko) IE Phone Opera Mobile Safari Mobile Chrome for Android
기본지원 No support No support No support No support No support No support No support

관련항목

문서 태그 및 공헌자

이 페이지의 공헌자: BANIP
최종 변경: BANIP,