본문 바로가기
react deep dive

[ZIMZIM] next.js(app router)+tanstack-query로 리팩토링하기

by rami_ 2024. 9. 10.

react + vite + redux-toolkit + redux-toolkit-query로 되어있던 프로젝트를 next.js+recoil+tanstack-query로 변경하기로 했다.

 

1. nextjs를 설치

npm i next

 

2. package.json의 script를 변경

 

3. vite와 관련된 디펜던시, 파일 삭제

next.js는 빌드시 webpack을 사용하는데 기존 프로젝트는 vite로 되어있었기 때문에 vite를 삭제하고 관련 파일들을 지워야했다.

 

npm uninstall vite vite-plugin-svgr

vite.config.ts 삭제

 

4. next.config.ts 파일 생성

root에 next.config.ts를 만든 후 next docs에 설명되어있는대로 설정해주었다.

 

5. react router 제거 및 pages 디렉토리 구조에 맞게 라우트 구성

next docs

기존 페이지 폴더 구조

 

 

main.tsx삭제

 

 

app router로 변경된 폴더구조

 

6. env파일에 VITE_ 로 시작되었던 접두사 삭제하고 NEXT_ 붙이기 & public 폴더 만들기

7. react-router-dom 제거

next.js에서는 next/navigation에 있는 useRouter를 사용한다.

next.js에서는 router.push('/path')를 사용해 이동하고, replace로 페이지를 교체한다.

 

useNavigate -> useRouter, useParams -> router.query로 변경한다.

 

7. 페이지 별로 서버컴포넌트, 클라이언트 컴포넌트로 구분하기

일반적으로 서버컴포넌트는 SSR 방식으로 데이터 페칭을 처리하는데 적합하고 api 호출 후 데이터를 렌더링할 때는 서버컴포넌트가 이상적이다. 그 외에도 SEO가 중요한 경우나 상태관리가 필요없는 경우, 보안이 필요한 경우에 적합하다고 한다.

클라이언트 컴포넌트는 상호작용(클릭, 드랙, 폼 제출 등 사용자와의 상호작용)이 필요할 경우, 브라우저 전용 api를 사용해야 할 경우(window, document, localStorage), 상태관리와 이벤트 핸들링이 필요한 경우, useRouter와 useNavigation과 같은 네비게이션 훅이 필요할 때 적합하다고 한다.

 

지금 ZIMZIM은 로그인, 회원가입, 대시보드, 운동 기록 리스트 페이지, 운동 기록 상세 페이지, 운동 기록 수정 페이지, 운동기록 등록 페이지가 있다.

로그인, 회원가입, 운동기록 수정페이지, 운동기록 등록페이지, 운동기록 리스트페이지는 클라이언트 컴포넌트, 대시보드, 운동기록 상세페이지는 서버컴포넌트로 만들기로 했다.

최종적으로 모든 페이지의 컴포넌트들이 클라이언트 컴포넌트로 구성되어있다. 이후에 서버컴포넌트가 필요하다고 느끼면 서버컴포넌트로 변경할 예정이다.

 

8. 서버컴포넌트에서 useEffect, useState, useRouter사용 하는 곳을 분리시키기

기존코드

 

기존 프로젝트를 리팩토링하며 redux-toolkit의 state를 사용하지 않고 있어 제거할 필요가 있었다. 그렇게 되면 redux-toolkit-query도 사용할 필요가 없어진다. 그래서 데이터 패칭과 캐싱에 특화되어있킄 tanstack-query를 도입하기로 했다.

 

tanstack-query에서 사용하는 useQuery, useMutation을 axios instance랑 같이 사용하고 재사용하기 위해 custom hook으로 분리했다.

 

그리고 assets에 있던 것들은 모두 최상위의 public폴더 안으로 옮겨주었다.

next.js에서 정적인 자원들은 모두 public에 위치한다.

 

공통으로 적용하던 layout을 /exercise, /water에 적용하려다 보니 같은 코드를 가진 파일을 2개 만들어야 될 것 같아 상위에 user라는 경로를 만들고 그 아래에 두기로 했다(이후에 i18n을 적용하면서 [locale] 폴더 밑으로 모두 이동시켰다).

 

아, 그리고 Index.html과 App.tsx는 더이상 필요가 없다. 왜냐면 이제 next.js에서 서버에서 파일을 만들어 가져올것이기 때문이다.