javascript

[Javascript] fetch

sewonzzang123 2022. 1. 13.
반응형

 

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

네트워크 요청은 다음과 같은 경우에 이뤄집니다.

  • 주문 정보
  • 사용자 정보 읽기
  • 서버에서 최신 변경분 가져오기
  • etc..

그런데 이 모든 것들은 페이지 새로 고침 없어도 가능합니다.

AJAX(Asynchronous Javascript And XML, 비동기적 Javascript와 XML)라는 용어를 들어보았을 겁니다.

AJAX는 서버에서 추가 정보를 비동기적으로 가져올 수 있게 해주는 포괄적인 기술을 나타내는 용어로, 만들어진지 오래되었습니다.

 

AJAX 이외에도 서버에 네트워크 요청을 보내고 정보를 받아올 수 있는 방법은 다양합니다.

이번에는 fetch() 메서드에 대해 글을 작성해보았습니다. 

 

fetch() 기본 문법은 다음과 같습니다.

 
let promise = fetch(url, [options]);

url

  • 접근하고자 하는 URL

options

  • 선택 매개변수, method나 header 등을 지정할 수 있음.

options에 아무것도 넘기지 않으면 요청은 GET 메서드로 진행되어 url 로부터 콘텐츠가 다운로드 됩니다.

fetch()를 호출하면 브라우저는 네트워크 요청을 보내고 프로미스가 반환됩니다. 반환되는 프로미스는 fetch()를 호출하는 코드에서 사용됩니다.

 

응답은 대개 두 단계를 거쳐 진행됩니다.

먼저, 서버에서 응답 헤더를 받자마자 fetch 호출 시 받은 promise가 내장 클래스 Response의 인스턴스와 함께 이행 상태가 됩니다.

이 단계는 아직 본문(body)이 도착하기 전이지만, 개발자는 응답 헤더를 보고 요청이 성공적으로 처리되었는지 아닌지를 확인할 수 있습니다.

네트워크 문제나 존재하지 않는 사이트에 접속할 경우같이 HTTP 요청을 보낼 수 없는 상태에선 프로미스는 거부상태가 됩니다.

HTTP 상태는 응답 프로퍼티를 사용해 확인할 수 있습니다.

  • status - HTTP 상태 코드 (ex) 200)
  • ok - boolean 값, HTTP 상태 코드가 200과 299 사이일 경우 true

 

let response = await fetch(url);


if(response.ok){ // HTTP 상태 코드가 200~299일 경우
    // 응답 본문을 받습니다.
    let json = await response.json();
}else{
    alert("HTTP-Error: "+response.status);
}

 

두 번째 단계에선 추가 메서드를 호출해 응답 본문을 받습니다.

response 에는 프로미스를 기반으로 하는 다양한 메서드가 있습니다. 이 메서드들을 사용하면 다양한 형태의 응답 본문을 처리할 수 있습니다.

  • response.text() - 응답을 읽고 텍스트를 반환합니다.
  • response.json() - 응답을 JSON 형태로 파싱합니다.
  • response.formData() - 응답을 FromData 객체 형태로 반환합니다.
  • response.blob() - 응답을 Blob(타입이 있는 바이너리 데이터) 형태로 반환합니다.
  • response.arrayBuffer() - 응답을 ArrayBuffer(바이너리 데이터를 로우 레벨 형식으로 표현한 것) 형태로 반환합니다.

JSON형태로 받아보는 예시

1)

 
let url = 'http://domain.com';
let response = await fetch(url);


let result = await response.json(); // 응답 본문을 읽고 JSON 형태로 파싱합니다.

2) await없이 Promise만 사용하기

 
fetch('url')
    .then(response=>response.json())
    .then(result=>console.log(result));

3) 응답을 텍스트 형태로 얻기 위해 .json() 대신 response.text()를 사용하기

 
let response = await fetch('url');


let result = await response.text(); // 응답 본문을 텍스트 형태로 읽습니다.
console.log(result);

4) blob로 받아오기

let response = await fetch('http://domain/com');

let blob = await response.blob(); // 응답을 Blob 객체 형태로 다운로드받습니다.

// 다운로드받은 Blob을 담을 <img>를 만듭니다.
let img = document.createElement('img');
img.style = 'position:fixed;top:10px;left:10px;width:100px';
document.body.append(img);

// 이미지를 화면에 보여줍니다.
img.src = URL.createObjectURL(blob);

setTimeout(() => { // 3초 후 이미지를 숨깁니다.
  img.remove();
  URL.revokeObjectURL(img.src);
}, 3000);

 

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

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

let text = await response.text();   // 응답 본문이 소비됩니다.
let parsed = await response.json(); // 실패

 

응답 헤더

 

응답 헤더는 response.headers 에 맵과 유사한 형태로 저장됩니다.

맵은 아니지만, 맵과 유사한 메서드를 지원합니다.

이 메서드들을 사용하면 헤더 일부만 추출하거나 헤더 전체를 순회할 수 있습니다.

 
let response = await fetch('http://domain.com');


// 헤더 일부를 추출
console.log(response.headers.get('Content-Type'));
// application/json ; charset=utf-8


// 헤더 전체를 순회
for (let [key, value] of response.headers){
    console.log(`${key} = ${value}`);
}

요청 헤더

 

headers 옵션을 사용하면 fetch에 요청 헤더를 설정할 수 있습니다. headers엔 아래와 같이 다양한 헤더 정보가 담긴 객체를 넘기게 됩니다.

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

그런데 headers를 사용해 설정할 수 없는 헤더도 있습니다.

참고 : https://fetch.spec.whatwg.org/#forbidden-header-name

 

Fetch Standard

 

fetch.spec.whatwg.org

 

POST 요청

 

GET 이외의 요청을 보내려면 추가 옵션을 사용해야 합니다.

  • method - HTTP 메서드( ex) POST)
  • body - 요청 본문으로 다음 항목 중 하나여야 합니다.
    - 문자열( ex) JSON 문자열)
    - FormData 객체 - form/multipart 형태로 데이터를 전송하기 위해 쓰입니다.
    - Blob나 BufferSource - 바이너리 데이터 전송을 위해 쓰입니다.
    - URLSearchParams - 데이터를 x-www-form-urlencoded 형태로 보내기 위해 쓰이는데, 요즘엔 잘 사용하지 않습니다.

 

대부분은 JSON을 요청 본문에 실어 보내게 됩니다.

 

user 객체를 본문에 실어 보내는 예시를 살펴봅시다.

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


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


let result = await response.json();
console.log(result.message);

POST 요청을 보낼 때 주의할 점은 요청 본문이 문자열일 때 Content-Type 헤더가 text/plain; charset=UTF-8로 기본 설정된다는 점입니다.

하지만 위 예시에선 JSON을 전송하고 있기 때문에 headers에 제대로 된 Content-Type인 application/json을 설정해 주었습니다.

 

이미지 전송하기

 

Blob나 BufferSource 객체를 사용하면 fetch로 바이너리 데이터를 전송할 수 있습니다.

예시

 
async function submit() {
  let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
  let response = await fetch('/article/fetch/post/image', {
    method: 'POST',
    body: blob
  });

  // 전송이 잘 되었다는 응답이 오고 이미지 사이즈가 얼럿창에 출력됩니다.
  let result = await response.json();
  console.log(result.message);
    }

요약

 

일반적인 fetch 요청은 두 개의 await 호출로 구성됩니다.

let response = await fetch(url, options); // 응답 헤더와 함께 이행됨
let result = await response.json();       // json 본문을 읽음

 

물론 await 없이도 요청을 보낼 수 있습니다.

 
fetch(url, options)
    .then(resposne => response.json())
    .then(result => /*결과 처리*/)

응답 객체의 프로퍼티는 다음과 같습니다.

  • response.status - 응답의 HTTP 코드
  • response.ok - 응답 상태가 200과 299 사이에 있는 경우 true
  • response.headers - 맵과 유사한 형태의 HTTP 헤더

 

응답 본문을 얻으려면 다음과 같은 메서드들 사용하면 됩니다.

  • response.text() - 응답을 읽고 텍스트를 반환합니다.
  • response.json() - 응답을 JSON 형태로 파싱합니다.
  • response.formData() - 응답을 FromData 객체 형태로 반환합니다.
  • response.blob() - 응답을 Blob(타입이 있는 바이너리 데이터) 형태로 반환합니다.
  • response.arrayBuffer() - 응답을 ArrayBuffer(바이너리 데이터를 로우 레벨 형식으로 표현한 것) 형태로 반환합니다.

 

지금까지 배운 fetch 옵션은 다음과 같습니다.

  • method - HTTP 메서드
  • headers - 요청 헤드가 담긴 객체(제약 사항이 있음)
  • body - 보내려는 데이터(요청 본문)로 String이나 FormData, BufferSource, Blob, UrlSearchParams 객체 형태

 

 

출처 : https://ko.javascript.info/fetch

 

fetch

 

ko.javascript.info

 

반응형

댓글