[React] fetch( )를 이용하여 API 호출하기 (feat.일기장)

Hyun·2022년 1월 6일
5

React

목록 보기
13/22
post-thumbnail

🔱필요한 개념

💡fetch()란?

  • 자바스크립트 내장 객체 (API 호출하는 역할)
  • fetch() 함수는 엄밀히 말해, 브라우저의 window 객체에 소속되어 있기 때문에 window.fetch()로 사용되기도 한다.

▶️ fetch()사용 방법

fetch(url, options)
  .then((response) => console.log("response:", response))
  .catch((error) => console.log("error:", error));
  • 첫번째 인자로 (API의)URL, 두번째 인자로 옵션 객체를 받고
    • 옵션(options) 객체에는 HTTP 방식(method), HTTP 요청 헤더(headers), HTTP 요청 전문(body) 등을 설정해줄 수 있습니다. 응답(response) 객체로 부터는 HTTP 응답 상태(status), HTTP 응답 헤더(headers), HTTP 응답 전문(body) 등을 읽어올 수 있습니다.
  • Promise 타입의 객체를 반환합니다.⭐️
    • API호출이 성공했을 경우(then)에는 응답(response) 객체를 resolve하고
    • 실패했을 경우(catch)에는 예외(error) 객체를 reject합니다.

▶️ GET 호출

원격 API에 있는 데이터를 가져올 때 쓰이는 GET방식의 HTTP 통신
fetch() 함수는 디폴트로 GET방식으로 작동하고 GET 방식은 요청 전문을 받지 않기 때문에 옵션 인자가 필요가 없습니다.
대부분의 REST API들은 JSON 형태의 데이터를 응답하기 때문에, 응답(response) 객체는 json() 메서드를 제공합니다.

fetch(URL)
  .then((response) => response.json());

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

▶️ POST 호출

원격 API에서 관리하고 있는 데이터를 생성해야 한다면 요청 전문을 포함할 수 있는 POST 방식의 HTTP 통신
동일한 API를 대상으로 이번에는 새로운 포스팅를 생성하기 위해서 fetch() 함수를 사용

fetch("URL", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Test",
    body: "Testing!",
    userId: 1,
  }),
})
  .then((response) => response.json())

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

PUT, DELETE 호출

원격 API에서 관리하는 데이터의 수정과 삭제를 위해서 PUT과 DELETE 방식의 HTTP 호출

  • PUT방식 = method 옵션만 PUT으로 설정한다는 점 빼놓고는 POST방식과 매우 흡사
  • DELETE방식 = 보낼 데이터가 없어서 headers와 body 옵션이 필요가 없다.

💡async, await

앞에 정리한내용 보기

💡slice()란?

JS의 함수
어떤 배열의 begin부터 end까지(end 미포함)에 대한 새로운 배열 객체로 반환하고, 원본 배열은 바뀌지 않는다.

arr.slice(begin, end)
  • 매개변수 begin
    • begin이 undefined인 경우에는, 0번 인덱스부터 slice
    • begin이 배열의 길이보다 큰 경우에는, 빈 배열을 반환
    • 음수 인덱스는 배열의 끝에서부터의 길이
      (slice(-2) 는 배열에서 마지막 두 개의 엘리먼트를 추출)
  • 매개변수 end
    • slice 는 end 인덱스를 제외하고 추출
    • end가 생략되면 slice()는 배열의 끝까지(arr.length) 추출
    • end 값이 배열의 길이보다 크면, silce()는 배열의 끝까지(arr.length) 추출
    • 음수 인덱스는 배열의 끝에서부터의 길이
      (slice(2,-1) 는 세번째부터 끝에서 두번째 요소까지 추출)

💡Math.floor()란?

JS의 함수
주어진 숫자와 같거나 작은 정수 중에서 가장 큰 수를 반환한다.(=소수점 이하를 버림)

Math.floor(숫자)

Math객체

  • 수학에서 자주 사용하는 상수,함수들을 구현한 JS표준 내장 객체
  • 다른 전역 객체와는 달리 생성자(constructor)가 존재하지않아서 인스턴스를 생성하지 않아도 Math 객체의 모든 메소드나 프로퍼티를 바로 사용가능하다.
  • 대부분의 Math 메소드는 웹 브라우저마다 다른 결과를 가져올 수 있으므로 아주 정확한 결과값이 필요할경우엔 Math 메소드는 사용하지 않는 것이 좋다!

💡Math.random()란?

JS의 함수
0~1사이의 난수(랜덤숫자)를 무작위로 생성합니다. 난수의 범위지정은
곱하기(*)로 (0에는 어떤 수를 곱해도 0이므로 1에 곱하여) 최대값을 지정
더하기(+)로 최소값을 지정한다. (약간의 이해 필요)

사용방법

Math.random()

기본적으로 0~1 사이의 난수가 나온다 (0.2194, 0.73849 이런식)

최대값 지정할 경우(*)

Math.random() * 최대값

최대값을 10으로 설정할 경우, 0~10사이의 난수가 나옴

최소값 지정할 경우(+)⭐️

Math.random() * (최대값 - 최소값) + 최소값 
//최대값은 제외, 최소값은 포함

Math.random() * (최대값 - 최소값in + 1) + 최소값 
//최대값은 포함, 최소값은 포함

최대값과 달리 최소값을 더하기로 들어가므로 최대값도 동시에 변하게된다
따라서 위와같이 괄호로 묶어줘야 한다


📖예제

useEffect를 이용하여 컴포넌트 Mount시점에 API호출하고(자바스크립트 API호출내장함수인 fetch를 사용하여 API호출 + await함수) 해당 API의 결과값을 일기데이터에 초기값으로 이용하기(API의 응답 데이터를 App.js컴포넌트가 가지고있는 일기데이터인 dataState에 저장 해서 일기데이터에 초기값을 설정)

App.js 코드

import { useEffect, useRef, useState } from "react";
import "./App.css";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";

const App = () => {
  const [data, setData] = useState([]);
  const dataId = useRef(0);

  const getData = async () => {
    const res = await fetch(
      "https://jsonplaceholder.typicode.com/comments"
    ).then((res) => res.json());

    const initData = res.slice(0, 20).map((it) => {
      return {
        author: it.email,
        content: it.body,
        emotion: Math.floor(Math.random() * 5) + 1,
        created_date: new Date().getTime(),
        id: dataId.current++,
      };
    });
    setData(initData);
  };

  useEffect(() => {
    getData();
  }, []);

  const onCreate = (author, content, emotion) => {
    const created_date = new Date().getTime();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      id: dataId.current,
    };
    dataId.current += 1;
    setData([newItem, ...data]);
  };

<코드설명>

1)const getData = async () => {
const res = await fetch(
"https://jsonplaceholder.typicode.com/comments"
).then((res) => res.json());

=await함수를 써야하므로 async키워드를 붙여서 getData함수가 promise를 반환하는 비동기함수로 만들어줌
fetch에 API의URL을 넣어주고, then으로 그 결과값을 json매서드를 통해서 json형식으로 받음
(console.log(res);를 해보면 아래와 같은 값이 500개 나오는 것을 확인할 수 있다.)

2)const initData = res.slice(0, 20).map((it) => {
return {
author: it.email,
content: it.body,
emotion: Math.floor(Math.random() * 5) + 1,
created_date: new Date().getTime(),
id: dataId.current++,
};
});
setData(initData);
};

= initData는 500개를 가진 API정보에서 0~19(20개)까지만 사용하고, 밑에조건의 새로운 배열만 map한다
작성자는 API정보의 email, 내용은 API정보의 body, 감정은 JS함수의 random으로하여 1~5까지의 난수를 랜덤하고 floor함수로 감싸 소수점을 떨궈내준 후 1~5까지 정수로 나타내준다. 날짜는 새로운 시간을 가져와주고, 아이디는 현재아이디에 +1을 해준다.
setData에 initData를 넣어 일기리스트 상태를 바꿈

3)useEffect(() => {
getData();
}, []);

= App.js컴포넌트가 Mount되자마자 getData함수를 호출하겠다
(*빈배열을 전달해야 Mount시점에만 실행된다는점)

🖥결과 화면


🚀참고자료

fetch()
MDN-slice()
MDN-Math.random()
React강의-이정환강사

profile
FrontEnd Developer (with 구글신)

0개의 댓글