SWR vs Fetch

단순 데이터 요청을 넘어서, ‘데이터 상태’를 관리하는 기술.

Fetch, 브라우저가 제공하는 가장 기본적인 API

fetch()는 네트워크 요청을 수행하는 웹 표준 내장 함수다.

단순히 “서버에서 데이터를 가져오는” 기능에 초점이 맞춰져 있다.

async function getUser() {
  const res = await fetch('/api/user');
  const data = await res.json();
  return data;
}

이 방식은 간단하고 직관적이지만, 데이터 요청 이후의 문제들을 직접 해결해야 한다.

Fetch 단독 사용 시 처리해야 하는 항목

  • 로딩 상태 관리(isLoading)
  • 에러 처리(try / catch)
  • 캐싱 및 재검증(데이터를 다시 가져와야 할 시점 제어)
  • 중복 요청 방지
  • 포커스 복귀 시 데이터 갱신

즉, fetch는 요청-응답 단위의 도구일 뿐, 데이터 생명주기(Data Lifecycle)에 대한 개념은 없다.

SWR: Data Fetching + Caching Layer

SWR은 Vercel에서 만든 React용 데이터 패칭 라이브러리다.

이름의 의미부터가 Stale-While-Revalidate 전략을 의미한다.

(오래된 데이터를 먼저 보여주고, 백그라운드에서 최신화)

import useSWR from 'swr';

const { data, error, isLoading } = useSWR('/api/user', fetcher);

SWR의 핵심은 데이터를 한 번 가져온 이후의 상태를 자동으로 관리하는 데 있다.

SWR이 제공하는 핵심 기능

기능설명fetch와의 차이
자동 캐싱동일 key 요청은 결과를 저장해 재사용.fetch는 매번 새요청
Stale-While-Revalidate캐시 데이터를 즉시 보여주고, 백그라운드에서 최신 데이터로 갱신fetch는 즉시성 없음
중복 요청 방지(Deduplication)동일 요청을 하나로 합침fetch는 병령 요청 시 중복 발생
포커스 시 재검증탭 복귀 시 최신 데이터 작동 갱신fetch는 수동 갱신 필요
오프라인 복구네트워크 끊김 후 재연결 시 자동 재요청fetch는 수동 재시도 필요
로딩/에러 상태 자동관리Hook 반환값으로 바로 제공fetch는 상태 관리 수동 구현

Stale-While-Revalidation 전략이 왜 중요할까

사용자는 데이터를 볼 때 실시간성보다 즉시성을 먼저 기대한다.

즉, 화면이 즉시 뜨고 나중에 백그라운드에서 최신 데이터로 갱신되는 것이 더 자연스럽다.

SWR은 이를 자동으로 구현한다.

  1. 캐시에 데이터가 있으면 즉시 반환
  2. 동시에 API 재요청(revalidate)
  3. 새로운 데이터로 갱신 후 자동 리렌더링.

이 접근 방식은 UX 측면에서 로딩 스피너보다 훨씬 부드럽고 빠른 체감을 준다.

SWR의 내부구조

SWR의 데이터 흐름은 다음과 같다:

  1. 요청: useSWR(key, fetcher) 호출
  2. 캐시 확인: key에 해당하는 데이터가 있으면 즉시 반환
  3. Revalidate: 비동기로 fetcher 실행 → 최신 데이터 가져오기
  4. Mutate: 결과를 캐시에 저장하고 구독 중인 컴포넌트 자동 업데이트

실무에서의 Fetch와 SWR

Fetch는 요청 1회성에 강하고, SWR은 데이터 유지/갱신에 강하다.

언제 Fetch만 써도 괜찮을까

  • 단일 요청 (로그인, 로그아웃, POST 폼 전송 등)
  • 데이터가 자주 바뀌지 않는 페이지
  • 별도 캐싱이 필요 없는 임시 요청

언제 SWR이 Fetch보다 유리할까

  • 다수의 컴포넌트가 같은 데이터를 참조할 때
  • 페이지 전환이 잦고 데이터 캐시가 필요할 때
  • 오프라인/포커스 복귀 후 자동 갱신이 필요할 때
  • Optimistic Update, Infinite Scroll 등 UI 일관성이 중요한 곳

결국 SWR은 단순 데이터 요청 도구가 아니라, 데이터 상태 관리 라이브러리에 가깝다.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다