Next.js Page Router에서 App Router로 옮기기 전에

개발하고싶은편·2024년 12월 17일

Next.js를 12 버전 때부터 쓰면서 편리한 SSR 처리 뿐 아니라, pages 폴더의 디렉토리 구조에 따라 편하게 라우팅 처리를 할 수 있는 점 등에서 매력을 느끼고 그동안 쭉 써왔다.

그런 와중, Next.js 13 버전부터 React 18 버전 이후에 도입된 '서버 클라이언트'(RSC) 개념에 맞춰, 서버에 더 많은 업무를 넘겨주며 탄생한 App Router가 메인으로 등장하기 시작했다. 그 무렵 내가 새로운 사이드 프로젝트를 시작하게 되면서, App Router 도입을 고민했지만 몇 가지 이유로 Page Router로 진행하게 되었다.

  1. 아직 불안정하다. 내가 즐겨쓰는(익숙한) 라이브러리와의 호환성이 불분명했다. 게다가 나온 지 얼마 안된 라우팅 방식이다.
  2. 불필요한 폴더와 파일이 많이 생긴다. 페이지 하나를 만들기 위해, /sub.tsx 하나로 해결될 일을 /sub/page.tsx로 해결해야 한다. 프로젝트 규모가 커질 수록, 파일과 폴더 관리가 복잡해진다고 생각했다.

하지만 옮겼죠

시간이 흐르면서 Next.js 팀은 App Router에 최우선으로 집중하는 것으로 보였고, 기능 개선도 App Router 위주로 돌아가고, 프론트엔드 추세도 다시 Client가 주도권을 가지던 분위기에서 Server가 되찾는 쪽으로 변하고 있다고 느꼈다.
그리고 개인적으로 한국도 프론트엔드 직무의 중요도와 필요성이 커지면서 프론트엔드 부분에서 해결할 수 있는 성능과 사용성 개선을 고민하다보니 밀리초 단위까지 성능 개선을 달성하기 위해 프론트엔드 커뮤니티 내에서 다양한 논의들이 오가는 것 같았다. 그 방법이 결국 클라이언트가 주도권을 가지면서 커졌던 번들 사이즈를 줄이는 방식으로 갈 수 밖에 없는 것 같았다. 그래서 나도 그 흐름에 올라타고 싶었다.

파일 구조만 바꾸면 되는 줄 알았지

사실 Page Router에서 App Router로 옮기는 것은 의외로 그렇게 어렵지 않다.(그런 줄 알았다)

  1. page 폴더를 app으로 이름을 바꾼다.
  2. _App.tsx, _document.tsx 파일을 page.tsxlayout.tsx로 바꾼 뒤 그 내용을 적절히 수정한다. (공식 문서 참고)
  3. 하위 .tsx 파일들을 모두 Next.js App Router의 라우팅 방식에 맞춰, page.tsx로 바꿔 옮겨준다.

이렇게 구조를 바꾸고 나면, 높은 확률로 'use client' 이슈를 마주하게 될 것이다.
클라이언트 컴포넌트와 달리 서버 컴포넌트가 기본인 Next.js에서는 JavaScript 하이드레이션 과정이 없는 방식으로 렌더링하기 때문에, onClick, useState 등 클라이언트 이벤트에 따라 리렌더링이 발생하는 요소가 있는 페이지들은 모두 'use client'를 선언하여 사용해야 하기 때문이다. 당연히 온갖 군데에 이 기능들이 사용되었으니 그때부터 고민이 들었다.

'use client'를 다 달아야 하나?

프론트엔드 개발, React 기반 개발을 하면서 각종 이벤트와 Hook을 사용하는 것은 너무나도 당연했고, 이걸 사용하기 위해서 번거로운 'use client'를 써야한다는 것이 선뜻 납득되지 않았다.

실제로 나같은 고민을 하는 사람이 있었고, 어떤 사람은 루트 layout.tsx에 'use client'를 쓰는 경우도 봤다. (그럴거면 왜 이걸 써요...? 😂)

하지만 그 '어떤 사람'은 나였다...

사실 RSC와 RCC를 잘 분리해서 사용하면 해결될 일이긴 하다.

서버와 응집도가 높은 컴포넌트, 클라이언트에서 해야할 일이 많은 컴포넌트로 쪼개고 이를 적절히 잘 섞어서 쓰면 된다. 실제로 Next.js 공식 문서에서도 이렇게 사용하는 걸 예시로 보여주고 있다.
React 개발에서 컴포넌트를 적절히 잘 쪼개는 것은 매우 중요한 능력 중 하나이지만, 쪼개는 기준에 대해서는 각자만의 방식이 있다. 그런데 RSC 개념이 도입되면서 어떻게 보면 쪼개는 명확한 기준이 확립된 셈이다. 프론트엔드 개발 협업 시에 이런 점은 확실한 강점이 될 것 같다.

아무튼 이렇게 프로젝트 주로 사용되는 페이지부터 쪼개고 'use client'를 지워서 RSC로 작동되기를 바랐는데.. 어째서인지 여전히 'use client'를 넣으라는 에러가 나왔다.

CSS in JS

나는 프로젝트에서 @emotion 기반의 CSS in JS를 도입해서 사용하고 있었다. 그런데 알다시피 'CSS in JS'는 이름 그대로 CSS 스타일을 JavaScript로 정의하는 방식이다 보니, 런타임 환경에서 JavaScript가 하이드레이션 되어 화면을 보여주는 기존 RCC 방식에서만 사용할 수 있다.

Next.js - Styling CSS in JS

게다가 내가 사용하는 @emotion만 이에 대응이 준비되지 않은 상황이었다.

이런 이유로
1. Zero-Runtime CSS in JS 도입하기
2. Next.js에서 밀어주는 (것 같은) Tailwind로 교체하기

등을 고민하게 되었다. 개인적으로 간단하게 데모 프로젝트를 만드는 정도가 아닌 이상 Tailwind를 선호하지 않는다. 자유도가 낮아서 디자이너의 요구사항을 반영하기 까다롭고 클래스명을 사용하여 JSX 내부에 inline하게 사용되어 스타일 코드가 혼재되는 방식이 영... 마음에 들지 않았다.

아마도 대안이 되는 CSS in JS나 유사한 라이브러리를 도입하게 될 것 같다. 그 전까지는 'use client'를 강제로 사용할 수 밖에 없다.

결론

Page Router에서 App Router로 전환하기까지 많이 찾아보고 결심을 내린 것이었지만, 실제로 부딪혀보면 역시 예상치 못한 이슈를 마주하게 된다.

profile
이야기를 좋아합니다.

0개의 댓글