본문 바로가기

JavaScript

[JavaScript] fetch

fetch 를 사용하면 필요할 때 서버에 네트워크 요청을 보내고 새로운 정보를 받아오는 일을 할 수 있습니다.

AJAX(Asynchronous JavaScript And XML)을 이용하면 페이지를 새로고침하지않고 정보를 받아올 수 있습니다. AJAX는 서버에서 추가 정보를 비동기적으로 가져올 수 있게 해주는 포괄적인 기술을 나타내는 용어로, 만들어진지 오래되었습니다. AJAX에 XML이 포함된 이유는 바로 이때문입니다.

콜백 함수는 자바스크립트의 비동기성을 표현하고 관리하는 가장 일반적인 기법이자 가장 기본적인 비동기 패턴이다. [You don't know Js] 콜백함수는 코드를 통해 명시적으로 호출하는 함수의 개념이 아닙니다. 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출하는 함수를 말합니다. 즉 콜백함수는 어떤 문법적 특징을 가지고 있는 것이 아니라, 호출방식에 의한 구문입니다.

let promise = fetch(url, [options])
  • url : 접근하고자 하는 URL
  • options: 선택매개변수, method, header 지정 가능

option에 아무것도 넣지 않으면 GET메서드로 url 로부터 콘텐츠가 다운로드됩니다.
fetch 요청을 하면 브라우저는 네트워크 요청을 보내고 프라미스를 반환합니다.

서버에서 응답 헤더를 받자마자 fetch 호출시 반환받은 promise가 내장 클래스 Response의 인스턴스와 함께 이행 상태가 됩니다. 이단계는 아직 본문(body)가 도착하기 전이지만, 개발자는 응답 헤더를 보고 요청이 성공적으로 처리되었는지 판단 가능합니다. 네트워크 문제나 존재하지 않는 사이트에 접속하려는 경우같이 HTTP 요청을 보낼 수 없는 상태에서는 프라미스는 거부 상태가 됩니다. HTTP상태 응답 프로퍼티를 사용해 확인할 수 있습니다.

  • status: HTTP 상태 코드 (예: 200)
  • ok : 불린값. HTTP 상태 코드가 200과 299 사이일 경우 true
  • response.headers : 맵과 비슷한 형태의 HTTP 헤더두번째 단계에선 추가 메서드를 호출해 응답 본문을 받습니다.
    response에는 프라미스를 기반으로하는 다양한 메서드가 있습니다. 이 메서드들을 사용하면 다양한 형태의 응답 본문을 처리할 수 있습니다.
 let response = await fetch(url);
 if (response.ok) { 
     let json = response.json()
 } 
 else { 
     alert('http-error: " + response.status); 
 }
  • response.text() - 응답을 읽고 텍스트를 반환합니다.
  • response.json() - 응답을 JSON 형태로 파싱합니다.
  • response.formData() - 응답을 FormData 객체 형태로 반환합니다.
  • response.blob() - 응답을 Blob(타입이 있는 바이너리) 형태로 반환합니다.
  • response.arrayBuffer() - 응답을 ArrayBuffer(바이너리 데이터를 로우 레벨 형식으로 표현한것)형태로 반환합니다.
  • response.body - ReadableStream 객체인 response.body를 사용하면 응답 본문을 청크 단위로 읽을 수 있습니다.

본문을 읽을 때 사용되는 메서드는 딱 하나만 사용할 수 있습니다.

response.text()를 사용해 응답을 얻었다면 본문의 콘텐츠는 모두 처리 된 상태이기 때문에 response.json()은 동작하지 않습니다.

응답 헤더는 response.headers에 맵과 유사한 형태로 저장됩니다.
맵은 아닙니다. 하지만 맵과 유사한 메서드를 지원합니다. 이메서드를 사용해서 헤더 일부만 추출하거나 헤더 전체를 순회가능합니다.

let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');
// 헤더 일부를 추출
alert(response.headers.get('Content-Type')); // application/json; charset=utf-8
// 헤더 전체를 순회
for (let [key, value] of response.headers) {
  alert(`${key} = ${value}`);
}

요청헤더 옵션을 사용하면 fetch에 요청 헤더를 설정할 수 있습니다.

let response = fetch(protectedUrl, {
  headers: {
    Authentication: 'secret'
  }
});

헤더를 설정할 수 없는 것도 존재하는데 이런 제약은 HTTP 목적에 맞고 안전하게 사용할 수 있도록 하려고 만들었습니다. 금지목록에 있는 헤더는 브라우저만 배타적으로 설정, 관리할 수 있습니다.

fetch로 POST요청을 보내려면 추가 옵션을 사용해야합니다.

let user = {
  name: 'John',
  surname: 'Smith'
};

let response = await fetch('/article/fetch/post/user', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  },
  body: JSON.stringify(user)
});

let result = await response.json();
alert(result.message);

POST 요청을 보낼 때 주의할 점은 요청 본문이 문자열일 때 Content-Type 헤더가 text/plain;charset=UTF-8로 기본 설정된다는 점입니다.하지만 위 예시에선 JSON을 전송하고 있기 때문에 headers에 제대로 된 Content-Type인 application/json을 설정해 주었습니다

콜백함수가 실행되었다는 것은 요청한 작업이 끝났음을 알리고 작업의 결과물은 콜백함수를 통해 사용가능하게 됩니다. 콜백은 순차적 실행이 필요한 경우에 비동기처리를 중첩시켜 표현하기에 에러나 예외처리가 불편하고, 중첩으로 인한 복잡도도 증가한다는 단점이 있습니다. 이런 단점들로 ES6에서부터 Promise를 지원합니다. Promise는 비동기를 간편하게 처리하도록 도와주는 객체입니다. Promise는 비동기 작업을 수행한후 정상적으로 기능이 수행되었다면 성공의 메세지와 함께 결과값을 전달하고 문제가 발생한 경우에 에러를 전달해주게 됩니다. 비동기 코드에서 성공과 실패를 분리해서 메서드를 호출해줍니다. 순차적이지 않은 비동기 함수의 실행 순서를 제어할 수 있게 도와주고 콜백함수에 비해 코드 가독성이 좋고 반환된 결과물을 사용하기 편리한 것이 특징입니다. axios 같은 라이브러리들이 비동기 통신을 하고 완료되면 Promise(객체)를 반환합니다.

fetch는 ES6부터 JavaScript 내장 라이브러리로, 서버로 네트워크 요청을 보내고 응답을 받을 수 있도록 해주는 메서드입니다. 또한 fetch는 XMLHttpRequest와 다르게 Promise 기반입니다.

XMLHttpRequest란 -> 대부분의 웹브라우저에서 서버로부터 데이터를 요청하는 XML객체들을 내장하고 있습니다. 이름만 보면 XML 데이터만 핸들링 할 것 같지만 모든 데이터를 다룹니다. XMLHttpRequest를 이용하면 웹페이지를 전부 로딩하고도 서버로부터 데이터를 요청하거나 전송 받을 수 있으며 웹페이지를 전부 로딩하지 않고도 일부만 갱신하는게 가능해집니다.

AJAX (Asynchronous JavaScript And XML ) 은 언어나 기술이 아닌 비동기 방식의 통신 기법을 말합니다. 자바스크립트를 이용해 서버와 브라우저가 비동기 방식으로 XML데이터를 교환할 수 있는 통신기능이고, 데이터를 이동하고 화면을 구성하는데 있어서 전체 페이지를 새로 고침없이 페이지의 일부만을 위한 데이터 로드기법입니다.

출처 eassy 님 블로그

참고

'JavaScript' 카테고리의 다른 글

[JavaScript] new.target  (0) 2022.05.12
[Core JavaScript] VariableEnvironment & LexicalEnvironment  (0) 2022.03.06
[Core JavaScript] class  (0) 2022.03.04
[Modern JavaScript Deep Dive] Array  (0) 2022.03.03
[Modern JavaScript Deep Dive] Iterable  (0) 2022.03.02