우리는 한다, 개발을.

Fetch API

⌛ 6 mins

Fetch API란

서버와 비동기적으로 통신하기 위해 XMLHttpRequest를 사용해왔습니다.
하지만 사용성이 까다로워 jQuery.ajax, axios 등과 같은 라이브러리를 사용하고 있습니다.
Fetch API는 사용성 개선을 위한 라이브러리, 플러그인 설치의 번거로움을 해결하기 위해 브라우저에서 제공하는 API 입니다.
Fetch API가 제공하는 전역 fetch() 메서드로 비동기적으로 서버와의 통신할 수 있습니다.

기본적인 Fetch 요청

fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(response => response.json())
    .then(data => console.log(data))

async, await

const getData = async () => {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
    return await response.json()
}
const data = await getData()
console.log(data)

결과

{
    userId: 1, 
    id: 1,
    title: 'delectus aut autem', 
    completed: false
}

응답은 Response 객체로 전달되고, JSON 형태로 바로 받지 못합니다.
Response는 HTTP 응답 전체를 나타내는 객체로, JSON 본문 콘텐츠를 추출하기 위해서는 json() 메서드를 호출해야 합니다.
json()은 응답 본문 텍스트를 JSON으로 파싱한 결과를 담은 프로미스를 반환합니다.

에러 catch

fetch()로부터 반환되는 Promise 객체는 404나 500와 같은 HTTP ERROR 상태를 reject 하지 않습니다.
대신 Response.ok 상태가 false인 resolve가 반환됩니다.
네트워크 연결이 실패하는 경우를 포함, 아예 요청을 완료하지 못한 경우 TypeError로 reject가 반환됩니다.
따라서 fetch()가 성공했는지를 정확히 알아내려면 프로미스의 이행 여부를 확인한 후, Response.ok 속성의 값이 true인지도 확인해야 합니다.

예시)

fetch(url)
    .then(response => {
        console.log(response.ok)
        if (response.ok) {
            return response.json()
        } else {
            console.error('ERROR')
        }
    })
    .then(data => console.log(data))
    .catch(err => console.error(err))

async, await

const getData = async () => {
    try {
        const response = await fetch(url)
        console.log(response.ok)
        if (response.ok) {
            return await response.json()
        } else {
            console.error('ERROR')
        }
    } catch (err) {
        console.error(err)
    }
}

const data = await getData()
console.log(data)

catch 결과

요청 URL https://jsonplaceholder.typicode.com/todos/1

fetch-success-1

요청 URL https://jsonplaceholder.typicode.com/todos/123456789

fetch-error-1

요청 URL https://jsonplaceholder.typicodes.com/todos/1

fetch-error-2

요청 옵션 제공

fetch() 는 선택적으로 두 번째 매개변수로 옵션 객체를 넣을 수 있습니다.
옵션 객체를 사용하면 여러가지 설정을 할 수 있습니다.

async function postData(url, data) {
  // 옵션 기본 값은 *로 강조
  const init = {
        method: 'POST', // *GET, POST, PUT, DELETE 등
        mode: 'cors', // no-cors, *cors, same-origin
        cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
        credentials: 'same-origin', // include, *same-origin, omit
        headers: {
            'Content-Type': 'application/json', // 'Content-Type': 'application/x-www-form-urlencoded',
        },
        redirect: 'follow', // manual, *follow, error
        referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
        body: JSON.stringify(data), // body의 데이터 유형은 반드시 "Content-Type" 헤더와 일치해야 함
    }
  const response = await fetch(url, init);
  return response.json(); // JSON 응답을 네이티브 JavaScript 객체로 파싱
}

postData(url, { answer: 42 }).then((data) => {
  console.log(data); 
});
  • method : 사용할 메소드를 선택 'GET', 'POST', 'PUT', 'DELETE'
  • mode : ‘cors’ 등의 값을 설정 'cors', 'no-cors', 'same-origin'
  • cache : 캐쉬 사용 여부 'no-cache', 'reload', 'force-cache', 'only-if-cached'
  • credentials : 자격 증명을 위한 옵션 설정 'include', 'same-origin', 'omit'
  • headers : 헤더에 전달할 값 { 'content-Type': 'application/json' }
  • referrerPolicy : 헤더에 포함되어야 하는 리퍼러 정보의 양 'no-referrer', 'no-referrer-when-downgrade', 'origin', ...more
    Referrer-Policy 더보기
  • redirect : 리다이렉트 설정 'manual', 'follow', 'error'
  • body : 바디에 전달할 값 JSON.springfy(data)]()

자격 증명 요청

credentials 옵션을 제공하지 않은 경우, fetch()는 쿠키를 전송하지 않습니다.
쿠키를 전송하기 위해선 자격 증명을 전송 해야합니다.
아래 자격 증명 요청 옵션을 참고하여 브라우저 요청시 fetch()의 옵션 객체에 설정을 추가해보세요.

credentials 옵션

  • include : 동일 출처와 교차 출처 요청 모두에 사용
  • same-origin : 요청 URL이 스크립트와 동일 출처일 때 자격 증명 전송
  • omit : 자격 증명을 전송하지 않음

Redirect

Fetch API를 통해 브라우저 요청 후 서버에서 리다이렉트를 하려고 할때 바로 리다이렉팅 페이지로 이동이 불가합니다.
리다이렉트를 하기 위해선 fetch()의 두번째 파라미터 옵션 객체에서 redirect의 설정이 필요합니다.

redirect 옵션

  • manual : 리다이렉트를 허용하지 않는다.
  • error : 리다이렉트 응답을 에러로 처리한다.
  • follow : 리다이렉트 응답을 허용한다.

요청 후 Response객체의 redirected 의 boolean 값을 통해 redirect 여부를 검사한다.

redirected 값

  • true : 리다이렉트 요청
  • false : 리다이렉트 미요청

사용 예)

fetch(url)
  .then((response) => {
      if (response.redirected) response.redirect(response.url)
  })

Fetch API에 대해 더 알아보고 싶다면

Fetch API 사용하기 문서

참고 자료