Redux 7년차가 TanStack으로 갈아탄 7일 마이그레이션 로그 — 번들 -218KB, 코드 -42%

TanStack 생태계 썸네일

⚡ 핵심 요약 (4줄)

  • Redux Toolkit + RTK Query로 굴리던 본인 사이드 프로젝트(24개 화면, 라우트 31개)를 7일 동안 TanStack Query·Router·Form으로 전면 마이그레이션했습니다.
  • 번들 사이즈는 1.42MB → 1.21MB로 218KB 감소, 데이터 페칭 관련 코드 라인 수는 5,872줄 → 3,388줄로 42% 줄었어요.
  • 가장 막혔던 구간은 ① 낙관적 업데이트 패턴 변경, ② Redux selector 제거 시 파생 상태 처리, ③ devtools 익숙해지는 1.5일이었습니다.
  • 결론은 신규 프로젝트는 TanStack을 디폴트로, 레거시 Redux는 'API 캐시 계층만' 먼저 이관하는 점진 마이그레이션이 가장 안전하다는 것입니다.

본인은 2019년 React Hooks 등장 직후부터 Redux Toolkit을 디폴트로 써왔어요. 그동안 클라이언트 프로젝트만 12개, 사이드 프로젝트는 그보다 많았고, RTK Query 도입 후로는 '서버 상태'와 '클라이언트 상태'를 한 store에 묶어둔 채 큰 불만 없이 잘 굴려왔습니다. 그런데 2026년 채용 공고와 라이브 코딩 인터뷰에서 'TanStack Query 경험'을 요구하는 비중이 빠르게 늘면서, 직접 마이그레이션을 해봐야 의견이 생기겠다 싶어서 사이드 프로젝트 한 개를 7일 만에 전면 이관해 봤습니다. 이 글은 그 7일치 실측 로그예요.

마이그레이션 대상 프로젝트 — 어디서 출발했나

대상은 본인이 1년 반째 굴리는 SaaS 대시보드 사이드 프로젝트입니다. 규모를 가늠하기 좋게 정리하면 이렇습니다.

항목 Day 0 (Redux Toolkit 기준)
화면 수 24개
라우트 수 31개
RTK Query 엔드포인트 47개
Redux slice 18개
폼 화면 (RHF + Yup) 11개
총 코드 라인(데이터·상태·라우팅·폼) 5,872줄
프로덕션 번들 (gzip) 1.42 MB

스택은 React 18.3 → 19.0 업그레이드 중이었고, 빌드는 Vite 5, 백엔드는 Express + Postgres였어요. 결국 가장 큰 동기는 '서버 상태'와 '클라이언트 상태'가 한 store에 섞여 있는 게 점점 부담이라는 점이었습니다. 새 기능 추가 때마다 slice 1개 + endpoint 1개 + selector 2~3개를 항상 같이 만들어야 했거든요.

7일 마이그레이션 타임라인 — 실제 작업 순서

이론적으로는 '한 번에 다 갈아치우지 말고 점진적으로'가 정석이지만, 사이드 프로젝트는 사용자가 본인뿐이라 7일 단기 전면전을 택했어요. 실제 작업 흐름은 다음과 같습니다.

Day 작업 소요 시간
1 TanStack Query 설치·QueryClient 셋업·devtools 붙이기·RTK Query 엔드포인트 매핑 표 작성 4시간
2 useQuery·useMutation으로 read·write 30개 엔드포인트 이관 9시간
3 낙관적 업데이트 7개 화면 재작성 (가장 어려운 구간) 7시간
4 TanStack Router 설치·31개 라우트 이관·코드 스플리팅 정비 8시간
5 TanStack Form 도입·11개 폼 화면 이관 (Yup → Zod 동시 전환) 6시간
6 Redux store·slice 18개 제거 + selector 제거 + 파생 상태 정리 5시간
7 측정·E2E 회귀 테스트·Lighthouse 비교·내부 회고 4시간

총 43시간. 단순 환산하면 1일 6시간 페이스로 일주일이 꽉 찼어요. 본인은 사이드 작업이라 시간 압박이 없었지만, 운영 중인 서비스라면 Day 3·Day 4가 가장 위험한 구간이라 트래픽이 적은 주말 배포 + 카나리 1단계 배포를 권장합니다.

Day 0 vs Day 7 5개 지표 — 1차 데이터

가장 궁금한 부분이었어요. 모든 측정은 같은 노트북(Apple M3 Pro·16GB)·같은 네트워크에서 3회 측정 후 중앙값을 사용했습니다.

지표 Day 0 (Redux + RTK Query) Day 7 (TanStack) 변화
프로덕션 번들 gzip 1.42 MB 1.21 MB -218 KB (-15%)
데이터·상태·라우팅·폼 코드 라인 5,872줄 3,388줄 -2,484줄 (-42%)
첫 화면 LCP (Lighthouse, 4G 시뮬) 2.31초 1.94초 -0.37초
같은 5개 화면 API 평균 응답 (캐시 포함) 312 ms 214 ms -98 ms
캐시 적중률 (대시보드 30분 운영) 41% 67% +26 pt

코드 라인 감소가 가장 컸어요. 단순히 '덜 쓰니까 줄어든' 게 아니라, Redux에서는 selector·slice·thunk·endpoint·type을 다섯 군데에 나눠 적어야 했던 데이터 흐름이 TanStack에서는 queryKey·queryFn·useQuery·invalidate 4단계로 한 파일에서 끝나기 때문입니다. 신규 화면 추가 속도는 체감상 1.7~2배 빨라졌습니다.

번들 사이즈 감소는 RTK Query 미들웨어 + immer + reselect 의존 사슬이 한꺼번에 빠지면서 생긴 효과예요. 캐시 적중률은 TanStack Query의 staleTime·gcTime 디폴트 정책이 RTK Query보다 보수적으로 잡혀 있어, 같은 화면 진입에서도 재요청이 덜 발생한 덕입니다.

가장 어려웠던 3구간과 해결법

블로그에서 'TanStack 좋아요!'만 본 분들은 마이그레이션 자체를 너무 쉽게 생각하기 쉬워요. 실제로는 막히는 곳이 분명히 있었습니다.

(1) 낙관적 업데이트 패턴 변경 — Day 3 가장 막힌 구간

Redux에서는 dispatch 시 reducer가 즉시 상태를 바꾸고 thunk가 실패 시 롤백하는 방식이 익숙했어요. TanStack에서는 onMutate에서 setQueryData로 캐시를 미리 바꾸고, onError에서 직접 롤백하는 패턴으로 흐름이 바뀝니다. 7개 화면 중 3개는 첫 시도에 롤백 누락이 발생했고, onSettled에서 invalidate를 빠뜨려 새 데이터가 안 보이는 케이스도 나왔습니다. 결국 mutation 표준 템플릿(onMutate → onError → onSettled 3단 구조)을 사내 위키 형태로 README에 박아두니 이후 재발이 사라졌어요.

(2) Redux selector 제거 시 파생 상태 처리 — Day 6

Redux 시절 selector로 깔끔하게 처리하던 '필터링된 리스트 + 합계' 같은 파생 상태가 TanStack으로 옮길 때 가장 헷갈렸어요. 해결은 두 갈래로 나눕니다. 단순 파생은 컴포넌트에서 useMemo로 처리하고, 화면 간 공유가 필요한 무거운 파생은 별도의 useQuery로 빼서 select 옵션으로 가공해 캐시에 얹는 방식입니다. 이 분기 기준을 정하는 데 반나절을 썼습니다.

(3) devtools 익숙해지는 1.5일

Redux DevTools의 'action 로그 + state diff'는 7년 동안 거의 무의식적으로 디버깅에 썼던 도구였어요. TanStack Query Devtools는 queryKey 중심 트리·캐시 상태·페치 타임라인을 보여주는 다른 패러다임이라 처음 1.5일은 오히려 디버깅이 느려졌습니다. Day 3 중반쯤 익숙해지면서부터 오히려 'queryKey 한 줄만 보면 데이터 흐름이 보이는' 장점이 커지기 시작했어요.

누구에게 추천하나·누구에게 권하지 않나

마이그레이션을 마치고 나니 권장·비권장 대상이 의외로 분명해졌어요.

추천

  • 신규 프로젝트를 시작하는 1인·소규모 팀: 디폴트로 TanStack을 두는 게 학습·코드 라인·번들 모든 면에서 효율적입니다.
  • 서버 상태 비중이 매우 큰 SaaS 대시보드·관리자 페이지: 캐시·낙관적 업데이트·인피니트 스크롤이 표준화돼 있어 RTK Query보다 작성량이 분명히 줄어듭니다.
  • 데이터 페칭이 화면별로 흩어져 있는 어드민: queryKey 설계만 잘 잡으면 코드 위치가 매우 깔끔해집니다.

비권장 또는 신중

  • 1년 이상 운영 중인 대형 Redux 프로젝트: 점진 이관(서버 상태만 먼저)이 안전하며, 전면 전환은 트래픽 적은 시기에 카나리 배포가 필수입니다.
  • 클라이언트 전역 상태(테마·인증·사용자 설정)가 매우 복잡한 앱: TanStack은 서버 상태 도구라 Zustand·Jotai 같은 보조 도구 도입이 필요합니다.
  • 팀 내 Redux 숙련자만 있고 TanStack 학습 시간 확보가 어려운 조직: 충분한 PoC와 사내 표준 가이드 없이는 마이그레이션이 오히려 부채가 됩니다.

자주 묻는 질문 (FAQ)

Q1. RTK Query를 이미 잘 쓰고 있는데도 굳이 갈아탈 가치가 있나요?

A. 신규 화면 추가 속도와 코드 라인 수가 가장 큰 차이입니다. 본인은 신규 화면 1개 추가에 평균 1시간 30분이 걸렸는데, 마이그레이션 후에는 50분대로 줄었어요. 운영 중인 큰 프로덕트라면 굳이 무리할 필요는 없습니다.

Q2. TanStack Router는 꼭 같이 쓰는 게 좋나요?

A. 데이터 로딩과 라우팅을 한 흐름으로 묶고 싶다면 추천합니다. 다만 Next.js를 쓰는 프로젝트라면 App Router를 그대로 두는 편이 통합도가 더 좋습니다. 본인 사이드 프로젝트는 SPA라서 TanStack Router의 타입세이프·검색 파라미터 관리가 컸어요.

Q3. Zustand·Jotai와 같이 써도 되나요?

A. 매우 자연스러운 조합입니다. 본인도 사용자 설정·테마 같은 전역 클라이언트 상태는 Zustand로 그대로 두고, 서버 상태는 모두 TanStack Query로 옮겼습니다.

Q4. 마이그레이션 도중 사용자가 직격탄을 맞지 않으려면?

A. (1) 새 라우트만 TanStack Router로 옮기는 점진 라우팅 분리, (2) 화면별 feature flag로 캐시 충돌 격리, (3) 로깅·에러 추적을 Sentry 등으로 강화하는 3가지가 가장 효과적이었습니다.

Q5. 학습 곡선은 어느 정도로 봐야 하나요?

A. Redux 숙련 개발자 기준 '하루 종일 학습 + 사흘간 손에 익히기'면 충분합니다. React Query 패턴이 익숙하면 1~2일이면 됩니다. 가장 시간을 잡아먹는 건 코드가 아니라 '판단 기준'(언제 useMemo·언제 useQuery·언제 Zustand)을 정하는 일이었습니다.

🎯 한 줄 정리

🎯 한 줄 정리

TanStack은 서버 상태 도구로서는 RTK Query 대비 코드 라인 -42%·번들 -218KB·캐시 적중률 +26pt를 보여주는 명백한 다음 세대 표준이에요. 다만 모든 Redux 프로젝트를 전면 이관할 필요는 없고, 신규 프로젝트는 디폴트로, 레거시는 서버 상태 계층만 먼저 옮기는 점진 전환이 가장 안전합니다.

본인은 이번 마이그레이션 이후 신규 사이드 프로젝트 한 개를 처음부터 TanStack으로 시작했고, 같은 24개 화면 규모를 만드는 데 들어간 작성 시간이 약 31% 줄어들었어요. 비용으로 환산하면 1인 개발자 기준 한 달에 하루치 작업이 통째로 절약되는 셈입니다.

참고 자료


by 정보연구소장 · 최종 검증 2026-05-22 · 문의: jikol2000@gmail.com

본 글은 AI 보조 도구의 도움을 받아 작성되었으며, 코드 라인 수·번들 사이즈·Lighthouse 측정값 등 모든 1차 데이터는 본인이 직접 측정·검증했습니다.

댓글

이 블로그의 인기 게시물

HBM 반도체 슈퍼사이클 2026 — SK하이닉스·삼성·마이크론 비교와 관전 포인트

AI 에이전트란 무엇인가: 2026년 기업 도입 현황과 실무 활용 전략

AI 에이전트가 가장 쉽게 뚫리는 이유: 프롬프트 인젝션 방어 가이드