코드네임 :

⚛️ React 심화 - React 비동기 처리와 데이터 패칭 라이브러리 본문

👥Club/☁️9oormthon univ☁️

⚛️ React 심화 - React 비동기 처리와 데이터 패칭 라이브러리

비엔 Vien 2025. 6. 22. 13:06

원리 이해보다는 어떻게 쓰는지 초점 맞춰서 다시하기 

 

 

비동기 : 어떤 작업을 요청한 후, 그 작업의 완료를 기다리지 않고 다음 작업을 바로 이어서 수행하는 방식

- 코드 흐름이 멈추지 않고 계속 진행되는 처리 방식

- 응답을 기다리지 않고 다음 작업을 계속 할수 있는 구조

- 응답이 도착했을 때 어떤 처리를 할지 콜백 또는 비동기 처리방식이 무조건 피료함!

요청 → 다음 작업 → 응답 도착 후 별도로 처리,

 

 

 

Promise

:  비동기적으로 실행하는 작업의 결과(성공 or 실패)를 나타내는 객체

- 지금 당장은 결과가 없지만, 나중에 성공하거나 실패했을 때 그 결과를 줄 약속된 객체!!!!!

- 비동기의 결과를 객체화 시킨다!!!

 

- 네트워크 요청 같은 비동기 작업은 시간이 걸리기 때문에 코드가 멈추지 않고 계속 진행할 수 있게 해야 ㄹ함

- 과거에는 callback을 썻는데 복잡햇음 -> Promise

const promise = new Promise((resolve, reject) => {
  // 비동기 작업 수행
  const success = true;

  if (success) {
    resolve("성공했어요!");
  } else {
    reject("실패했어요!");
  }
});

promise
  .then((result) => {
    console.log(result); // 성공했어요!
  })
  .catch((error) => {
    console.error(error); // 실패했어요!
  });

⬇️ promise 이라는 Promise 객체는 3가지 상태를 가짐

- 대기(pending) : 아직 실행되지 않은 초기 상태, 작업 중 상태 (진행 중)

- 이행(fulfilled) : 작업 성공 (resolve())

- 거부(rejected) : 작업 실패 (reject())

 

const promise = new Promise((resolve, reject) => {
  // 비동기 작업
  if (성공) {
    resolve("성공 결과");
  } else {
    reject("에러 발생");
  }
});
//.then()과 .catch()로 결과를 다루기
promise
  .then((result) => {
    console.log("성공:", result);
  })
  .catch((error) => {
    console.error("실패:", error);
  });

https://velog.io/@cyranocoding/2019-08-02-1808-작성됨-5hjytwqpqj

 

JavaScript 비동기 처리를 위한 promise 이해하기

배경지식 JavaScript는 엔진은 Single Thread이다. 그래서 동시에 두 가지 작업을 할 수 없다. 그렇다면 여러 작업이 동시에 요청이 될 때 이 전 작업이 마무리 될 때까지 기다려야 하는가? 그렇다. 그래

velog.io


fetch

- 저번에 알아봤듯이 fetch()로 url을 통해 원하는 API의 결과값을 받아올 수 있음

- fetch() “응답이 도착하면 알려줄게!“라는 Promise를 반환

const result = fetch("https://jsonplaceholder.typicode.com/users/1");
console.log(result); //Promise { <pending> }

 

fetch().then()

- 이 결과값을 제대로 사용하거나 보기 위해서는 .json()을 사용하여 response JSON 으로 바꿔주고, 다시 .then()을 사용

fetch("https://jsonplaceholder.typicode.com/users/1")
  .then((res) => res.json())  // 응답이 오면 처리해줘
  .then((data) => console.log(data)) // json 파싱된 데이터를 출력

 

+ then()

then() 메서드는 Promise를 리턴하고 두 개의 콜백 함수를 인수

하나는 Promise가 이행했을 때, 다른 하나는 거부했을 때를 위한 콜백 함수

const promise1 = new Promise((resolve, reject) => {
  resolve('Success!');
});

promise1.then((value) => {
  console.log(value);
  // expected output: "Success!"
});

 

 


 

 

async/await

- Promise를 더 간단하고 읽기 쉽게 다루기 위한 문법

- 기존의 .then().catch() 체인은 중첩되고 읽기 어려움 -> async/await 동기 코드처럼 보이면서도 비동기 처리

가능!!!

 

함수의 앞에 async 라는 예약어를 붙인 뒤, HTTP 통신을 하는 비동기 처리 코드 앞에 await를 붙임

주의해야 할 점은 비동기 처리 메서드가 꼭 프로미스 객체를 반환해야함 (일반적으로 Axios 등 프로미스를 반환하는 API 호출 함수)

async function 함수명(){
	await 비동기_처리_메서드_명();
}
//async 함수는 항상 Promise를 반환

async function hello() {
  return "안녕!";
}

hello().then((msg) => console.log(msg));  // 안녕!
//await은 Promise가 처리될 때까지 기다림

function delay() {
  return new Promise((resolve) => {
    setTimeout(() => resolve("끝!"), 1000);
  });
}

async function run() {
  console.log("시작");
  const result = await delay();  // 1초 기다림
  console.log(result);           // "끝!"
  console.log("완료");
}

run();

 

 

 

const res = await fetch("https://jsonplaceholder.typicode.com/users/1");

fetch() Promise 반환

- await 그 Promise가 끝날 때까지 기다렸다가 응답(res)을 받아오는 것

 

 

async와 await은 비동기 처리 API 중에 가장 최근에 도입된 문법으로 기존의 불편함을 보완하기 위해 나온 편리한 구문

⬇️ 기존 방식의 문제점

function callAsync() {
    const data = fetch('데이터url')
    
    if(data.id === 1) {
      console.log(data.name);
    }
  }

위와 같은 함수가 있다고 할 때 콘솔창에는 과연 무엇이 나올까? fetch는 비동기로 동작하기 때문에 콘솔창의 결과는 장담할 수가 없다. 콜백함수로 처리해야만 결과를 보장받을 수 있다. 이의 단점을 보완하기 위해 등장한 것이 async와 await 이다.

 

⬇️

 

async & await

function callAsync() {
    const data = fetch('데이터url')
    
    if(data.id === 1) {
      console.log(data.name);
    }
  }

async라고 비동기 함수를 선언해주고, 비동기 작업에 await를 붙여주면 그 뒤에 이 결과를 사용하는 작업에서 동기처럼 처리가 된다. 즉, 비동기 작업이 이루어진 후에 그 결과로 작업이 수행된다.

 

 

https://velog.io/@kimbangul/fetch와-asyncawait로-비동기-처리하기

 

[JavaScript] fetch()와 async/await로 비동기 처리하기

대표적인 비동기 처리 방법 Callback, Promise, Async/await 중 Promise와 Async 처리 방법

velog.io

https://babycoder05.tistory.com/entry/Promise-Fetch-Async-Await-에-대해-알아보자

 

Promise, Fetch, Async, Await 에 대해 알아보자

Promise, Fetch, Async, Await 에 대해 알아보자 Promise Promise는 JavaScript의 비동기 처리에 사용되는 객체로써 비동기로 처리되는 결과를 동기처럼 반환한다. 실제로 동기처럼 처리되는 것이 아니라 미래

babycoder05.tistory.com

 


 

 

React에서 비동기처리

: useEffect()는 비동기 코드에서 데이터 요청에 활용됨

- 상태관리로 로딩/에러/결과 분기 처리

 

useEffect()

- 컴포넌트가 마운트될 때 비동기 작업(데이터 요청 등)을 처리하는 React 훅.. 햇자나,,,

 

 

 


 

useSWR

useSWR(key, fetcher)

 

: 동기식 API를 제공하는 데이터 가져오기용 React Hooks 라이브러리

- API 데이터 요청 처리에서 캐싱 문제를 해결하기 위한 최소한의 API를 제공

- 간단하게 데이터를 가져오는 경우

- API 메서드를 호출할 때, useSWR에서 데이터 가져오기를 자동으로 조정하고 구성 요소로 반환

- useSWR은 API, 데이터베이스 및 서버 측 렌더링을 포함한 모든 소스에서 데이터를 가져올 수 있음

- SWR은 먼저 캐시에서 데이터를 반환한 다음, 서버에 데이터를 가져오는 요청을 보내고, 마지막으로 최신 데이터를 제공하는 전략

 

 

import useSWR from 'swr'
 
function Profile() {
  const { data, error, isLoading } = useSWR('/api/user', fetcher)
 
  if (error) return <div>failed to load</div>
  if (isLoading) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

 useSWR hook은 key 문자열과 fetcher 함수를 받습니다. 

key는 데이터의 고유한 식별자이며(일반적으로 API URL) fetcher로 전달될 것입니다. fetcher는 데이터를 반환하는 어떠한 비동기 함수도 될 수 있습니다.

네이티브 fetch 또는 Axios와 같은 도구를 사용할 수 있습니다.

hook은 세 개의 값을 반환합니다: 요청의 상태에 기반한 data, isLoading 그리고 error

 

 

블로그에서 따온 것,,, 아니 근데 왜 설명을 아무도 안해주시지,,, ㅜㅜㅜ

import useSWR from 'swr'

function Profile() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

// or 

export const useXXX = () => {
  const { data, isValidating, error } = useSWR<ReturnDataType>(
    'key', async () => {
      // 비동기 통신 부분
      const res = await ...
      return res.data
    },
  );

  return {
    data,
    isLoading: isValidating,
    error,
  };
};
const { data, isValidating, error }

 

const { data, isValidating, error }
  • data는 비동기 통신으로 받아온 데이터이다. 타입스크립트에서 useState 타입을 지정해 주는 것 처럼 간단하게 선언해 줄 수 있다.
  • isValidating은 react-query에서 isFetching | isLoading 처럼 fetching 중인지를 알 수 있는 boolean 값이다.

 

 

//useSWR은 데이터 패칭을 간편하게 도와주는 훅(hook) - 자동 캐싱, 재요청, 리페치, 로딩/에러 처리까지 깔끔하게 관리
import useSWR from "swr";


// 데이터를 실제로 가져오는 방식
// fetch()로 URL 요청 → res.json()으로 응답을 JSON으로 변환하는 함수
// SWR이나 React Query 같은 데이터 패칭 라이브러리에서 데이터를 어떻게 가져올지 알려주는 “데이터 요청 로직”
const fetcher = (url) => fetch(url).then((res) => res.json());



function PostsSWR() {
  // useSWR 훅
  // "https://..."가 이 요청의 키이며 동시에 fetch(fetcher함수의 인자)에 사용됨!!
  /// data: 성공 시 응답 데이터
  /// error: 실패 시 에러 정보
  /// isLoading: 아직 로딩 중이면 true
  const { data, error, isLoading } = useSWR(
    "https://jsonplaceholder.typicode.com/posts",
    fetcher
  );


  // 조건부 렌더링 (로딩과 에러)
  if (isLoading) return <div>로딩중...</div>;
  if (error) return <div>에러: {error.message}</div>;
  
  // 정상적으로 data가 있을 경우, post 리스트 렌더링 (data는 각 post의 title을 보여줌)
  return (
      <div>
        <h3>포스트 목록</h3>
        <ul style={{ textAlign: "left", maxWidth: 600, margin: "0 auto" }}>
          {data && data.map((post: any) => (
            <li key={post.id}>
              <strong>{post.title}</strong>
            </li>
          ))}
        </ul>
      </div>
  );
}

 

장점

-  자동 리페치 (revalidation, 최신 데이터 유지)

-  브라우저 포커스 시 자동 업데이트

-  캐싱되어 재요청 줄임

-  코드 간결함

 

 

TanStackQuery (= React Query)

useQuery(queryKey, fetchFn)

 

- React에서 비동기 데이터를 관리하기 위한 라이브러리

데이터 캐싱 및 기능적으로 더 많은 제어가 필요한 경우 (더 다양한 기능과 복잡한 캐싱전략)

- 크게 React Apollo의 클라이언트를 기반으로 하지만 기능이 적고 크기가 작음

- React 앱에서 비동기 데이터를 가져오고, 캐시하고, 업데이트하기 위한 일련의 hooks 및 tools를 제공

- 핵심 hooks 외에도 React Query는 데이터 관리, 오류 처리 및 페이지네이션등 유용한 유틸리티를 제공

- 리액트 애플리케이션에 서버 상태를 가져오고, 캐싱하고, 동기화하고, 업데이트하는 것을 쉽게 해 줌

 

- TanStack Query 활용해서 데이터를 가져올 때는 항상 쿼리 (queryKey) 지정하게 됨
쿼리 키는 캐시된 데이터와 비교해 새로운 데이터를 가져올지, 캐시된 데이터를 사용할지 결정하는 기준이 됨

import { useQuery } from '@tanstack/react-query'

export default function DelayedData() {
  const { data } = useQuery({
    queryKey: ['delay'],
    queryFn: async () => (await fetch('https://api.heropy.dev/v0/delay?t=1000')).json()
  })
  return <div>{JSON.stringify(data)}</div>
}

 

... 아니 모르겠슨데ㅣ,,,,,,,ㅠㅠ

 

 

 

??>????

// useQuery()는 react-query의 핵심 훅 - 비동기 요청, 캐싱, 상태 관리, 로딩/에러 처리 등을 자동화
import { useQuery } from "@tanstack/react-query";


// fetch() 기반 비동기 함수
// useQuery에서 queryFn으로 쓰일 예정
function fetchPosts() {
  return fetch("https://jsonplaceholder.typicode.com/posts").then((res) =>
    res.json()
  );
}

function Posts() {
  // useQuery 훅
  // queryKey : 쿼리를 식별하는 키 (캐시 구분용). 배열로 작성하는 게 규칙
  // queryFn : 데이터를 실제로 패칭하는 함수 (fetchPosts)
  
  // queryKey가 같으면 캐시를 재사용하고, 다르면 새로운 요청이 발생함
  const { data, error, isLoading } = useQuery({
    queryKey: ["posts"],
    queryFn: fetchPosts,
  });


  // 조건부 렌더링
  if (isLoading) return <div>로딩중...</div>;
  if (error) return <div>에러: {error.message}</div>;
  
  //데이터 렌더링
  return (
    <ul>
      {data.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

 

장점

-  자동 캐싱 (불필요한 네트워크 요청 방지

-  자동 리페치 (최신 데이터 유지)

- 로딩/에러/성공 상태 자동 관리

- 서버 상태 동기화 유지

...

 

 

+

useSWR React Query
단일 API 엔드포인트에서 데이터 가져오는 것으로 제한됨 여러 API 엔드포인트에서 데이터 가져올수 있음
API 엔드포인트에서 최신 데이터 반환 (but 경쟁조건(race condition)으로 이어질 수 있음 API 엔드포인트에서 데이터를 가져오는 빈도를 제어할 수 있는 내장 캐싱 메커니즘이 있음 ( 데이터를 가져올 때 좀 더 안정적) 
API 엔드포인틍서 데이터를 가져올 때 오류를 처리하는 방법을 제공하지 않음  오류가 정상적으로 발생할 때 처리할 수 있는 에러 핸들링 시스템이 내장되어 있음
React hooks용으로 명시적으로 설계되어있음 React hooks의 기존 클래스 기반 구성 요소와 호환됨
SWR 위에 구축되어있음 Axios위로 구축되어있음
데이터 소스를 원격으로 쿼리할 수 있음 애플리케이션의 API에서 데이터 캐싱 및 가져오기에 중점
종속성이 변경되면 자동으로 데이터를 다시 가져옴  데이터를 다시 가져올 시기와 빈도를 결정할 수 있음
첫 번째 요청이 완료될 때까지 초기화되지 않은 값을 반환 캐시된 값을 즉시 반환

 

 

 

https://swr.vercel.app/ko

 

데이터 가져오기를 위한 React Hooks – SWR

SWR is a React Hooks library for data fetching. SWR first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again.

swr.vercel.app

 

https://voyage-dev.tistory.com/159

 

useSWR vs React(TanStack) Query를 비교해보자

원문 : https://codedamn.com/news/javascript/useswr-vs-react-query-differences-and-which-one-should-you-choose https://blog.logrocket.com/swr-vs-tanstack-query-react/ https://tech.madup.com/react-query-vs-swr/ https://sihyungyou.github.io/iOS-race-conditi

voyage-dev.tistory.com

https://velog.io/@jiyaho/서버-상태-관리-라이브러리-SWR과-React-Query-비교-및-기본-사용법

 

서버 상태 관리 라이브러리 SWR과 React Query(Tanstack Query) 비교 및 기본 사용법

SWR과 React Query와 같은 서버 상태 관리 및 Data fetching 라이브러리와 그 필요성에 대해 서술하기 전에 먼저, React에서 사용하는 State(상태)를 구분할 필요가 있습니다.Local State(지역 상태): React 컴포

velog.io

https://www.heropy.dev/p/HZaKIE

 

TanStack Query(React Query) 핵심 정리

TanStack Query는 서버로부터 데이터 가져오기, 데이터 캐싱, 캐시 제어 등 데이터를 쉽고 효율적으로 관리할 수 있는 라이브러리로, React Query라는 이름으로 시작했지만, v4부터 Vue나 Svelte 등의 다른

www.heropy.dev

https://voyage-dev.tistory.com/158

 

API를 호출할 때 useState 대신 useSWR을 사용해야 하는 이유

원문 : https://javascript.plainenglish.io/why-you-should-use-useswr-instead-of-usestate-when-calling-apis-8b6de5dc18fc https://velog.io/@ysg81/React-useSwr-사용하기 https://github.com/vercel/swr https://swr.vercel.app/ko/docs/revalidation SWR이란

voyage-dev.tistory.com

https://velog.io/@ysg81/React-useSwr-사용하기

 

[React] 비동기 통신 useSWR의 모든것

리액트를 다루면서 사용할 수 있는 비동기 통신은 여러개가 있다. 내가 알고 있는 방법으로는 redux-saga, useSwr, react-query 정도? 가 있는 것 같다. 자주 사용했던 것은 redux-saga, 간단해 보여서 사용하

velog.io

 

 

https://yzlosmik.tistory.com/98

 

[SWR] useSWR 장점

https://swr.vercel.app/ko 현재 우리 프로젝트에서 쓰고있는 data fetch react hook. 도입되자마자 구현하느라, 공부해볼 시간이 없었다. 이참에 정리해보고자 한다. 장점 1. Cache Stale-While-Revalidate 의 줄임말

yzlosmik.tistory.com

 


[상태 분기]

 

loaading (로딩상태)

: 요청이 진행 중일 때 보여주는 상태

if (isLoading) return <p>로딩 중...</p>;

 


error (에러 처리) 

: 요청이 실패했을 때 사용자에게 알려주는 상태

- 여러 에러 처리....(API 실패, .....

if (error) return <p>데이터를 불러오지 못했습니다.</p>;

 

 

retry (재요청)

: 에러가 발생했을 때 자동/수동으로 요청을 다시 시도하는 기능

- 모바일 환경에서 네트워크가 불안정할 때 유용

useQuery({
  queryKey: ['user'],
  queryFn: fetchUser,
  retry: 3  // 실패 시 최대 3번 자동 재시도
});

 

 

cache (캐싱)

: 한번 불러온 데이터를 다시 요청하지 않고 재사용하는 것

- 속도 향상 + 서버 비용 절감

- 같은 데이터를 여러 컴포넌트에서 사용할 때 필수

- 유효기간, 갱신 시점 등을 함께 고려해야 함

const { data } = useSWR("/api/user"); // 이전에 불렀으면 빠르게 보여줌

 

 

revalidate (재검증)

: 데이터를 백그라운드에서 새로 가져와 최신으로 만드는 과정 (보여주는 건 캐시지만, 백그라운드에서 “혹시 바뀌었나?” 체크함)

- 사용자 입장에서는 빠르고, 최신 데이터도 보장

- 성능과 실시간성의 균형을 맞추는 기술

const { data } = useSWR("/api/user");
// 캐시 보여줌 + 백그라운드에서 fetch 재실행 (자동)