단순 데이터 요청을 넘어서, ‘데이터 상태’를 관리하는 기술.
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은 이를 자동으로 구현한다.
- 캐시에 데이터가 있으면 즉시 반환
- 동시에 API 재요청(revalidate)
- 새로운 데이터로 갱신 후 자동 리렌더링.
이 접근 방식은 UX 측면에서 로딩 스피너보다 훨씬 부드럽고 빠른 체감을 준다.
SWR의 내부구조
SWR의 데이터 흐름은 다음과 같다:
- 요청: useSWR(key, fetcher) 호출
- 캐시 확인: key에 해당하는 데이터가 있으면 즉시 반환
- Revalidate: 비동기로 fetcher 실행 → 최신 데이터 가져오기
- Mutate: 결과를 캐시에 저장하고 구독 중인 컴포넌트 자동 업데이트
실무에서의 Fetch와 SWR
Fetch는 요청 1회성에 강하고, SWR은 데이터 유지/갱신에 강하다.
언제 Fetch만 써도 괜찮을까
- 단일 요청 (로그인, 로그아웃, POST 폼 전송 등)
- 데이터가 자주 바뀌지 않는 페이지
- 별도 캐싱이 필요 없는 임시 요청
언제 SWR이 Fetch보다 유리할까
- 다수의 컴포넌트가 같은 데이터를 참조할 때
- 페이지 전환이 잦고 데이터 캐시가 필요할 때
- 오프라인/포커스 복귀 후 자동 갱신이 필요할 때
- Optimistic Update, Infinite Scroll 등 UI 일관성이 중요한 곳
결국 SWR은 단순 데이터 요청 도구가 아니라, 데이터 상태 관리 라이브러리에 가깝다.
답글 남기기