[비동기 프로그래밍] - Fetch

Donggu(oo)·2022년 12월 17일
0

JavaScript

목록 보기
48/49
post-thumbnail

1. Fetch


  • fetch 함수는 특정 URL로 부터 정보를 받아오는데, HTTP 요청을 전송할 URL과 HTTP 요청 메서드, HTTP 요청 헤더, 페이로드 등을 설정한 객체를 전달한다.

  • fetch 함수는 XMLHttpRequest 객체와 마찬가지로 HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 Web API이다.

  • fetch 함수는 프로미스를 지원하기 때문에 비동기 처리를 위한 콜백 패턴의 단점에서 자유롭다.

기본 문법

fetch(url, {options})

매개변수

  • url: 접근하고자 하는 URL
  • options: 선택 매개변수, methodheader, body 등을 지정할 수 있음

1) GET(read) 요청

  • GET 요청은 정보를 요청(조회)하기 위해 사용되는 메서드로 fetch 함수에 첫 번째 인수로 HTTP 요청을 전송할 URL만 전달하면 GET 요청을 전송한다.

  • fetch 함수는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환하므로 후속 처리 메서드 then을 통해 프로미스가 resolve한 Response 객체를 전달받을 수 있다.

  • Response 객체는 HTTP 응답을 나타내는 다양한 프로퍼티를 제공하는데, 예를 들어 fetch 함수가 반환한 프로미스가 래핑하고 있는 MINE 타입이 application/json인 HTTP 응답 바디를 얻으려면 Response 객체에서 HTTP 응답 바디를 역직렬화하는 Response.prototype.json 메서드를 사용한다.

  • fetch API의 응답(response) 객체는 json()을 제공하고 있어 JSON.parse() 대신 사용할 수 있다.

fetch('https://jsonplaceholder.typicode.com/todos/1')
  // json 메서드를 사용하여 Response 객체에서 HTTP 응답 바디를 획득하여 역직렬화한다. 
  .then(response => response.json())
  // json은 역직렬화된 HTTP 응답 바디다.
  .then(json => console.log(json))
  // {userId: 1, id: 1, title: 'delectus aut autem', completed: false}
  • fetch + promise 방식(response, data 변수명 상관없음)
const getQuestion = () => {
    fetch('http://localhost:4000/discussions')
        .then((response) => response.json())  // response 변수명 상관없음
        .then((data) => setQuestion(data));  // data 변수명 상관없음
}
  • fetch + async/await 방식(response, data 변수명 상관없음)
const getQuestion = async () => {
    const response = await fetch('http://localhost:4000/discussions');
    const data = await response.json();
    setQuestion(data);
}

역직렬화하는 JSON.parse()와 response.json()의 차이

  • JSON.parse()에는 응답(response) 바디만을 넣어야 한다. 바디와 헤더가 들어가면 데이터를 읽어오지 못한다.
  • response.json()에는 응답 헤더가 들어와도 바디만 읽어서 불러온다.

2) POST(create) 요청

  • POST 요청은 정보를 전송(추가)하기 위해 사용되는 메서드로 fetch 함수에 첫 번째 인수로 HTTP 요청을 전송할 URL를 전달하고, 두 번째 인수로 method, header, body 등을 지정하여 POST 요청을 전송한다.

  • fetch API를 사용하는 경우 수동으로 JSON.stringify()를 사용해서 객체를 문자열화 한 다음 body할당해야 한다.

  • fetch를 사용하면 명시적으로 Content-Typeapplication/json으로 설정해야 한다.

fetch('https://jsonplaceholder.typicode.com/todos', {
  method: 'POST',
  headers: {
    // JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    userId: 1,
    title: 'JavaScript',
    completed: false
  }),
})
  .then(response => response.json())
  .then(json => console.log(json))
// {userId: 1, id: 201, title: 'JavaScript', completed: false}
  • fetch + promise 방식(response, data 변수명 상관없음)
const handleButtonClick = () => {
    fetch('http://localhost:4000/discussions', {
        method: 'POST',
        // JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            id: question.length + 10,
            createdAt: new Date(),
            author: author,
            title: title,
            url: "#",
            answer: null,
            avatarUrl: 'https://source.boringavatars.com/beam',
        }),
    })
        .then((response) => response.json())
        .then((data) => getQuestion(data));
};
  • fetch + async/await 방식(response, data 변수명 상관없음)
const handleButtonClick = async () => {
    const response = await fetch('http://localhost:4000/discussions', {
        method: 'POST',
        // JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            id: question.length + 10,
            createdAt: new Date(),
            author: author,
            title: title,
            url: "#",
            answer: null,
            avatarUrl: 'https://source.boringavatars.com/beam',
        }),
    })
    const data = await response.json()
    getQuestion(data)
};

3) PUT(replace) 요청

  • PUT 요청은 정보를 완전 대체하기 위해 사용되는 메서드로 fetch 함수에 첫 번째 인수로 HTTP 요청을 전송할 URL를 전달하고, 두 번째 인수로 수정할 특정 필드를 지정하여 PUT 요청을 전송한다.
fetch('https://jsonplaceholder.typicode.com/todos/1', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    completed: true
  }),
})
  .then(response => response.json())
  .then(json => console.log(json))
// {id: 1, completed: false}

4) PATCH(update) 요청

  • PATCH 요청은 정보를 부분적으로 수정하기 위해 사용되는 메서드로 fetch 함수에 첫 번째 인수로 HTTP 요청을 전송할 URL를 전달하고, 두 번째 인수로 수정할 특정 필드를 지정하여 PATCH 요청을 전송한다.
fetch('https://jsonplaceholder.typicode.com/todos/1', {
  method: 'PATCH',
  headers: {
    // JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    completed: true
  }),
})
  .then(response => response.json())
  .then(json => console.log(json))
// {userId: 1, id: 1, title: 'delectus aut autem', completed: true}

PUT과 PATCH의 차이점

  • PUT은 user data 구조가 id, title, body라고 한다면, 회원정보 수정시 PUTid를 찾아 title만 업데이트 하더라도 항상 모든 필드값을 가져와서 모든 필드를 항상 새로운 값으로 교체한다.
  • PUT은 모든 속성을 수정하기 때문에 title 데이터만 보내주면 원래 있던 id, body 데이터는 사라진다.
  • PATCH는 user data의 구조가 id, title, body라고 한다면, 회원정보 수정시 PATCHid를 찾아 title만 업데이트할때 idtitle만 받아와서해당 부분을 업데이트 한다.

5) DELETE 요청

  • DELETE 요청은 정보를 삭제하기 위해 사용되는 메서드로 fetch 함수에 첫 번째 인수로 HTTP 요청을 전송할 URL를 전달하고, 두 번째 인수로DELETE 메서드를 지정하여 DELETE 요청을 전송한다.
fetch('https://jsonplaceholder.typicode.com/todos/1', {
  method: 'DELETE',
})
  .then(response => response.json())
  .then(json => console.log(json))
  • fetch + promise 방식(response 변수명 상관없음)
const handleDeleteClick = (id) => {
    fetch(`http://localhost:4000/discussions/${id}`, {
        method: 'DELETE'
    })
        .then((response) => getQuestion(response))
}
  • fetch + async/await 방식(response 변수명 상관없음)
const handleDeleteClick = async (id) => {
    const response = await fetch(`http://localhost:4000/discussions/${id}`, {
        method: 'DELETE'
    })
    getQuestion(response)
}

0개의 댓글