본문 바로가기

Timo

[초기세팅] TanStack Query & Axios 초기 세팅

[뭐부터 먼저하지]

Tanstack Query & Axios 설정이랑 Sentry 설정했어야 했는데

Sentry는 에러 모니터링 도구라 실제 API 호출 흐름이 있어야 의미가 있었다. 

→  Axios interceptor에서 에러를 잡아서 Sentry에 보낼거라 Tanstack 설정 먼저 함. 

 

[Axios와 TanStack Query를 왜 쓰냐]

<axios>

원래 fetch로 데이터를 받아올 수 있는데

fetch는 요청이 실패했을 때 자동으로 에러를 던져주지 않아서 매번 직접 처리해야 함. 

// fetch 사용 시
const res = await fetch('/todos')
if (!res.ok) {
  if (res.status === 401) // 직접 처리
  if (res.status === 404) // 직접 처리
}

근데! axios를 쓰면 interceptor라는 기능으로 에러 처리를 한 곳에서 관리할 수 있음. 

axios.ts 파일에 에러 처리 로직 "한 번만" 작성해두면 API 호출할 때마다 자동 적용 ! 

<tanstack query>

데이터를 받아올 때 1. 데이터 불러오는 중인지, 2. 에러가 났는지, 3. 데이터가 잘 도착했는지 

이런 상태를 직접 관리하려면 컴포넌트마다 useState로 상태 만들고 관리해야함. 

Tanstack Query가 이거 자동으로 해줌. 

isLoading, isError, data 같이 상태 알아서 관리 + !!캐싱!!

캐싱 여러 컴포넌트에서 같은 데이터 요청해도 실제 API 호출은 한 번만 진행한다. 

 

★ 그래서 둘이 같이 쓰면 

useQuery(() => axios.get('/todos'))

queryFn 안에서 axios로 요청하고 tanstack query가 그 결과를 캐싱하고 관리하는 구조가 됨. 

 

[파일별 역할]

lib/axios.ts — API 요청 도구 설정
"모든 요청은 이 베이스 URL로 보내고, 에러나면 이렇게 처리해"
Axios 인스턴스를 만들어두면 나중에 API 호출할 때마다 이 인스턴스를 가져다 쓴다.

lib/query-client.ts — 캐싱 전략 설정
"데이터 5분간 신선하게 유지하고, 윈도우 포커스 시 재요청 하지 마"
TanStack Query가 데이터를 어떻게 관리할지 규칙을 정해두는 파일이다.

lib/providers.tsx — 앱 전체에 규칙 적용
"위에서 정한 규칙을 앱 전체에 씌워줘"
layout.tsx에서 이 Provider로 앱을 감싸면 모든 페이지에서 TanStack Query를 쓸 수 있다.

app/layout.tsx — Provider 연결
앱의 최상단 레이아웃에서 Providers로 감싸주는 역할이다.

 

[전체 흐름]

layout.tsx
  └── providers.tsx (QueryClientProvider)   ← query-client.ts 규칙 적용
        └── 각 페이지
              └── useQuery(() => axios.get('/todos'))  ← axios.ts 인스턴스 사용
                    └── 결과 캐싱 → 다음 요청 시 캐시에서 반환

 

[프로젝트에 맞춰서 설정값 정하기]

staleTime : 5분

데이터 5분동안 신선하게~

우리 프로젝트가 투두 앱인데 투두 목록은 내가 직접 추가하거나 완료 처리하기 전까지 바뀔 일이 없음. 

타이머 기록도 다른 기기나 다른 사람이 건드리지 않음. 

혼자 쓰는 앱이니까 staleTime 넉넉하게 5분으로 ~ 

refetchOnWindowFocus : false

탭 나갔다가 돌아왔을 때 API 다시 호출하지 않게~

공부하면서 쓰는 앱이라 탭 이동이 잦을것.. 

그 사이에 투두 목록이 바뀌었을까..? 놉놉 직접 수정하지 않은 이상 바뀔 일 없음. 

탭 돌아올 때마다 API 호출은 낭빈듯

retry : 1

API 호출 실패했을 때 1번만 다시 시도하자..

401(로그인 필요), 404(없는 데이터)는 재시도해봤자 똑같이 실패하갯지..

재시도가 의미 있는 건 서버가 죽었을 때(500)

인증 방식 아직 확정되지 않은 시점이라 그냥 1회 재시도로 지금은 설정해놓고 

나중에 에러 코드별로 분기하는 방식 고려해도 될듯

gcTime : 10분

캐시 데이터를 메모리에서 10분 유지~

staleTime보다 넉넉~하게~

0분        5분        10분
|----------|----------|
  신선함      stale      캐시 삭제
 (staleTime)  (gcTime)

요런 흐름으로. 

사용자가 잠깐 다른 페이지 갔다가 7분 후에 돌아와도 캐시된 데이터 볼 수 있음.

 

[providers.tsx에 use client 왜?]

queryClient가 파일 최상단에 선언되는데 

만약 이게 서버에서 실행되면 여러 사용자가 같은 queryClient instance를 공유하게 된다. 

그러면 A 사용자의 투두 데이터가 B 사용자한테 보일수도?

그래서 use client를 붙여서 이 파일이 브라우저에서만 실행되도록 설정함. 

 

[코드리뷰 반영]

1. 폴더명 lib  api로 변경
lib은 다양한 유틸리티를 담는 범용 폴더 느낌이고,

지금 담기는 내용이 API 관련 설정이라 api가 더 의도가 명확.

2. providers.tsx  provider/QueryProvider.tsx로 분리
Provider를 별도 폴더로 분리해서 구조를 명확하게 가져가는 방향으로 수정.