Ajax with Fetch


이 글은 기존의 XHR과 jQuery.ajax 메서드로 작성했던 간단한 애플리케이션을 fetch를 이용한 방법에 대해 알아보고자 합니다. 이전 글을 참고하시려면 아래 링크를 클릭해 주세요.

XMLHttpRequest 링크 jQuery.ajax 링크

목차 - Fetch Request 보내기 - HTTP Method 변경하기 - Response 처리하기 - Error 처리하기

Fetch Request 보내기

XMLHttpReqeust로 서버에 요청하기 위해서, XHR 객체를 생성하고 open, send 메서드르 이용해야 합니다. 절차가 다소 복잡하고 또한 코드도 장황하게 느껴집니다. Fetch를 이용하면 별도의 라이브러리를 사용하지 않고도 간결하게 Ajax를 구현할 수 있습니다. Fetch는 Network 요청을 보내는데 작업을 수월하게 해주며, Promises를 바탕으로 작동합니다. 하지만, 가장 큰 단점은 브라우저 호환성입니다. 구버전의 Internet Explorer는 fetch를 지원하지 않습니다.

아래는 기존의 XHR, jQuery 방식과 비교한 Fetch를 이용해 요청을 보내는 코드입니다.

// XMLHttqRequest
var req = new XMLHttpRequest();
req.open('GET', `https://api.unsplash.com/search/photos?page=1&query=flowers`);

// jQuery
$.ajax({
  url: `https://api.unsplash.com/search/photos?page=1&query=flowers`
});

// Fetch
fetch(`https://api.unsplash.com/search/photos?page=1&query=flowers`);

크롬 콘솔에서 위 fetch 코드를 실행시키면 Promise가 반환되는 것을 확인할 수 있습니다. 그리고 fetch 역시 자원을 요청하기 위해서 Cross-origin protocol을 준수해야 합니다. 따라서, 사이트의 같은 도메인에서만 데이터를 요청할 수 있습니다.

이전 글에서 언급했듯이, unsplash의 API를 이용하기 위해서 Authorization header를 포함해야 합니다. header를 추가하기 위해서는 fetch에 두 번째 argument로 전달하면 됩니다.

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch

fetch();
fetch(`https://api.unsplash.com/search/photos?page=1&query=flowers`, {
  header: {
    Authorization: 'Client-ID abc123'
  }
});

// or

const requestHeaders = new Headers();
requestHeaders.append('Authorization', 'Client-ID abc123');
fetch(`https://api.unsplash.com/search/photos?page=1&query=flowers`, {
  headers: requestHeaders
});

##### HTTP Method 변경하기 Fetch의 HTTP method의 기본값은 'GET'입니다. 해당 값을 변경하고 싶으면 동일하게 두 번째 인자로 전달하는 객체를 통해 설정할 수 있습니다. ```javascript fetch(`https://api.unsplash.com/search/photos?page=1&query=flowers`, { method: 'POST" }); ```
##### Response 처리하기 위에서 fetch를 통해 HTTP request를 요청하는 법을 알아봤습니다. 이번에는 요청 후 response를 처리하는 방법에 대해 알아보도록 하겠습니다.

일단 fetch를 통해 HTTP request 요청을 보내면, promises를 반환합니다. 따라서, fetch의 반환값을 promises를 이용해 처리할 수 있으며, .then 메소드를 사용할 수 있습니다.

fetch(`https://api.unsplash.com/search/photos?page=1&query=${searchedForTExt}`, {
  headers: {
    Authorization: 'Client-ID abc123'
  }
}).then(function(response) {
  debbuger;
});

위의 코드를 각자의 API 키를 추가해 실행시킨 후, then 메소드에서 Fetch request가 성공적일 때 response가 반환된 것을 확인할 수 있습니다. response 객체가 반환되었지만, 실제 우리가 요청한 데이터를 사용하기 위해서는 json 메소드를 호출해야 합니다. fetch에서 반환된 객체는 response 자체에 대한 정보이기 때문입니다.

fetch(`https://api.unsplash.com/search/photos?page=1&query=${searchedForTExt}`, {
  headers: {
    Authorization: 'Client-ID abc123'
  }
}).then(function(response) {
  response.json();
});

.json()가 반환하는 것 또한 promises이기에, 우리는 .then()을 이용해 함수를 호출하고 데이터를 이용할 수 있습니다.

fetch(`https://api.unsplash.com/search/photos?page=1&query=${searchedForTExt}`, {
  headers: {
    Authorization: 'Client-ID abc123'
  }
})
  .then(function(response) {
    response.json();
  })
  .then(addImage);

function addImage(data) {
  debugger;
}

Response 객체에는 여러 method들이 있습니다. 예로 .json()은 객체를 JSON으로 변경하거나 JSON에서 객체로 변경을 해줍니다. 이미지를 가져오고 싶을때는 .blob()를 사용할 수 있습니다. .blob()은 Image body에서 image를 추출합니다.

Making fetch requests https://davidwalsh.name/fetch

위 코드를 ES6를 사용하면, 아래와 같이 좀 더 명료하게 작성할 수 있습니다.

fetch(`https://api.unsplash.com/search/photos?page=1&query=${searchedForTExt}`, {
  headers: {
    Authorization: 'Client-ID abc123'
  }
})
  .then(response => response.json())
  .then(addImage);

function addImage(data) {
  debugger;
}

##### Error 처리하기 대부분 HTTP request가 성공적이겠지만, 우리는 그렇지 않은 경우도 대비를 해야 합니다. 에러가 발생하는 경우는 어떠한 것들이 있을까요? 아래와 같은 이슈를 생각해 볼 수 있습니다. \- 네트워크 문제 \- fetch request 문제 \- 서버 측에서 요청한 정보를 찾을 수 없을 때

셋 중 마지막 사항은 addImage function에서 처리할 수 있습니다. 나머지 두 개에 대해서 우리는 .catch()를 사용할 수 있습니다. .catch()는 Promise API에서 이용할 수 있고, fetch()는 Promise를 반환하기 때문에 다음과 같이 .catch()를 이용할 수 있습니다.

fetch(`https://api.unsplash.com/search/photos?page=1&query=${searchedForTExt}`, {
  headers: {
    Authorization: 'Client-ID abc123'
  }
})
  .then(response => response.json())
  .then(addImage)
  .catch(e => requestError(e, 'image'));

function addImage(data) {
  debugger;
}

function requestError(e, part) {
  console.log(e);
  responseContainer.insertAdjacentHTML(
    'beforeend',
    `<p class="network-warning">Oh no! There was an error making a request for the ${part}.</p>`
  );
}

위와 같이 작성함으로써, 에러가 발생할 경우 .catch()에 error object가 전달되고 이것을 콘솔창에 출력할 수 있습니다. Promises가 reject되면 위의 requestError 함수가 실행이 됩니다.