HTML&CSS&Javascript/JS

fetch() API 의 사용법

킹우현 2023. 2. 5. 15:37
fetch('http://example.com/movies.json')
  .then((response) => response.json())
  .then((data) => console.log(data));

fetch 함수는 XMLHttpRequest 객체보다 최근에 나온, HTTP 요청 전송 기능을 제공하는 Web API다.

 

fetch 함수는 HTTP response 객체를 래핑한 Promise 객체를 반환한다. 따라서 프로미스의 후속 처리 메서드인 then()을 사용하여 resolve한 객체를 전달받을 수 있다. (물론 catch, finally도 마찬가지)

 

fetch 함수로 받은 Response 객체에는 HTTP 응답을 나타내는 프로퍼티들이 있다. 그 중 json() 내장 함수가 있는데, response.json 메서드 사용 시 HTTP 응답 body 텍스트를 JSON 형식으로 바꾼 프로미스를 반환한다(.then(res ⇒ res.json())의 의미)

 

 

사용법 정리 : fetch() 함수는 첫번째 인자로 URL, 두번째 인자로 옵션 객체를 받고, Promise 타입의 객체를 반환합니다. 반환된 객체는, API 호출이 성공했을 경우에는 응답(response) 객체를 resolve하고, 실패했을 경우에는 예외(error) 객체를 reject합니다.

 

옵션(options) 객체에는 HTTP 방식(method), HTTP 요청 헤더(headers), HTTP 요청 전문(body) 등을 설정해줄 수 있습니다.

응답(response) 객체로 부터는 HTTP 응답 상태(status), HTTP 응답 헤더(headers), HTTP 응답 전문(body) 등을 읽어올 수 있습니다.

 

참고로 fetch() 함수는 엄밀히 말해, 브라우저의 window 객체에 소속되어 있기 때문에 window.fetch()로 사용되기도 합니다.

 

1. GET 호출

fetch("https://jsonplaceholder.typicode.com/posts/1")
  .then((response) => response.json())
  .then((data) => console.log(data));

fetch() 함수는 Default로 GET 방식으로 작동하고 GET 방식은 요청 전문을 받지 않기 때문에 옵션 인자가 필요가 없습니다.

 

대부분의 REST API들은 JSON 형태의 데이터를 응답하기 때문에, 응답(response) 객체는 json() 메서드를 제공합니다.

이 메서드를 호출하면, 응답(response) 객체로 부터 JSON 포멧의 응답 전문을 자바스크립트 객체로 변환하여 얻을 수 있습니다.

 

2. POST 호출

fetch("https://jsonplaceholder.typicode.com/posts", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Test",
    body: "I am testing!",
    userId: 1,
  }),
})
  .then((response) => response.json())
  .then((data) => console.log(data));

원격 API에서 관리하고 있는 데이터를 생성해야 한다면 요청 전문을 포함할 수 있는 POST 방식의 HTTP 통신이 필요할 것입니다.

method 옵션을 "POST"로 지정해주고, headers 옵션을 통해 JSON 포멧을 사용("Content-Type" : "application/json")한다고 알려줘야 하며, 요청 전문을 JSON 포멧으로 직렬화하여 가장 중요한 body 옵션에 설정해줍니다.

 

마찬가지 방법으로 응답 객체의 json() 메서드를 호출하면 응답 전문을 객체 형태로 얻을 수 있습니다.

 

3. PUT, DELETE 호출

fetch("https://jsonplaceholder.typicode.com/posts/1", {
  method: "PUT",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Test",
    body: "I am testing!",
    userId: 1,
  }),
})
  .then((response) => response.json())
  .then((data) => console.log(data));

 

원격 API에서 관리하는 데이터의 수정과 삭제를 위해서 PUT과 DELETE 방식의 HTTP 호출을 해야할 때가 있습니다.

 

PUT 방식은 method 옵션만 PUT으로 설정한다는 점 빼놓고는 POST 방식과 매우 흡사합니다.

 

fetch("https://jsonplaceholder.typicode.com/posts/1", {
  method: "DELETE",
})
  .then((response) => response.json())
  .then((data) => console.log(data));

DELETE 방식에서는 보낼 데이터가 없기 때문에, headers와 body 옵션이 필요가 없습니다.

 

+ + 추가적인 Tip

 

fetch() 함수는 사용법이 아주 간단하지만, 계속 사용하다보면 똑같은 코드가 반복된다는 것을 알 수 있습니다.

 

예를 들어, 응답 데이터을 얻기 위해서 response.json()을 매번 호출하거나, 데이터를 보낼 때, HTTP 요청 헤더에 "Content-Type": "application/json"로 설정해주는 부분이 반복됨을 알 수 있습니다.

 

이럴 때는 fetch() 함수를 직접 사용하시기 보다는, 별도의 함수나 모듈로 빼서 사용하는 것이 좋습니다.

 

프로젝트의 상황에 맞게 다음과 같이 async/await 키워드를 이용하여 HTTP 방식별로 비동기 함수를 작성하고 모듈화하여 사용할 수 있습니다.

 

async function post(host, path, body, headers = {}) {
  const url = `https://${host}/${path}`;
  const options = {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      ...headers,
    },
    body: JSON.stringify(body),
  };
  const res = await fetch(url, options);
  const data = await res.json();
  if (res.ok) {
    return data;
  } else {
    throw Error(data);
  }
}

post("jsonplaceholder.typicode.com", "posts", {
  title: "Test",
  body: "I am testing!",
  userId: 1,
})
  .then((data) => console.log(data))
  .catch((error) => console.log(error));