⚠️ 본 포스트는 프로젝트 리펙토링 과정을 담은 개인 기록입니다. Next.js 13 버전의 특징이나 사용법에 대한 학습을 원하신다면, 공식 문서를 참조하시기 바랍니다.
서버 컴포넌트를 사용할 수 있는 next.js@13.4
버전이 정식으로 릴리즈되면서 실무에서 적용된 page router를 app router으로 업그레이드 하기전에 개인 프로젝트에 적용을 해봤다.
next.config.js
파일에 아래 코드를 추가하고 app/
경로에 파일을 생성해서 코드를 작성하면 된다
module.exports = {
experimental: {
appDir: true,
},
// Other configuration options
};
기존 Next.js 앱에는 애플리케이션의 모든 페이지와 뷰를 관리하는데 중요한 두 가지구성 요소를 제공한다.
기존 Next.js@12 에서는 특정 라우팅 하위에 레이아웃을 구성하는 것이 불가능했으며, 이로 인해 코드를 중복으로 작성해야 하는 불편함이 있었다.
관련 이슈
공통적으로 사용하는 레이아웃은 _app.jsx
파일이나 _document.jsx
에 적용할 수 있었지만, /main/first
/main/second
와 같아 특정 라우트 하위에서 공통 레이아웃을 구성하는 것은 불가능 해서 이로인해 코드의 중복 작성을 해야했다.
그러나 Next.js 13버전 app폴더 구조에서는 이 문제를 해결했다. 특히 layout.tsx을 공유하는 페이지를 탐색할 때 레이아웃이 리렌더링이 되지 않는다. 이를 통해 불필요한 렌더링을 줄이고, 웹 성능을 향상시킬 수 있었다.
- app
📂 main
- layout.tsx
📂 first
- page.tsx
📂 second
- page.tsx
main
세그먼트에 작성된 layout.tsx
파일은 Leaf 세그먼트인 /first
와 /second
에도 영향을 준다. 따라서, 하위 라우트는 모두 <body>{chlidren}</body>
안에 구성된다. 이로써, 중복된 레이아웃 코드 작성을 방지하고, 더 효율적인 코드 구조를 만들 수 있게 됐다.
// app/main/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
next.js@13
에서는 모든 컴포넌트가 서버 컴포넌트로 기존에 사용하던 getServerSideProps
, getStaticProps
함수가 필요 없어졌다. 그러면 Next 13버전에서는 어떻게 데이터를 가져올까?
fetch API를 사용한다
Next.js 13에서는 fetch 함수에서 cache
옵션과 next
옵션 값을 줘서 SSR, ISR, SSG 와 같은 통신을 구현할 수 있다.
1. SSG
직접 무효화 하기 전까지는 request가 캐싱된다.
빌드 시점에 fetch를 하고 요청 시 캐싱된 데이터를 반환해서 getStaticProps`방식과 비슷하다.
force-cache 옵션은 default 값으로 생략 가능하다.fetch(URL, { cache: 'force-cache' });
2. SSR
매번 요청 때마다 refetch 된다 (getServerSideProps 방식과 비슷하다)
fetch(URL, { cache: 'no-store' });
3. ISR
// 일정 시간 동안만 캐싱
fetch(URL, { next: { revalidate: 20 } });
니콘내콘 프로젝트에서는 데이터를 가져오는 데 SSR
, ISR
, SSG
세 가지 방법을 모두 사용하고 있었다.
/
) : ISR/brand/[id]
): SSR/itemList/[id]
): ISR (dynamic routes로 getStaticPaths
사용)/items/[id]
): SSR메인 페이지에서는 '카테고리 종류' 및 '땡처리 콘' 데이터를 가져오기 위해 두 가지 별도의 통신을 사용하여 데이터를 가져와 화면에 표시하고 있었다. 그러나 화면 상단에 보여지는 카테고리 종류
데이터는 자주 변경되지 않았기 때문에 SSG 방식으로 구현해도 충분했으나, 떙처리 콘
데이터는 자주 변경되는 데이터라 불필요하게 revalidate 값을 설정하여 데이터를 주기적으로 업데이트하고 받아왔다.
위와 같은 문제를 App router의 서버컴포넌트를 도입하면서 페이지 단위가 아닌 컴포넌트 단위로 캐시 전략을 세울 수 있어서 한 페이지에서 통신마다 revalidate속성값을 줄 수 있게 되면서 서버의 부하를 최소화 시켰다.
App router의 서버 컴포넌트를 도입함으로써 페이지 단위가 아닌 컴포넌트 단위로 캐시 전략을 수립할 수 있게 됐다.
App Router로 마이그레이션한 결과, Pages Router 방식에 비해 TTFB가 감소한 것을 확인할 수 있었다. 아래 두 가지 링크에서 비교할 수 있다.
Next.js page router Link : https://ncnc-9ytztvgzd-hyjoong.vercel.app/
Next.js app router Link: https://ncnc.vercel.app/
App Router의 Intercepting Routes을 이용하여, 페이지 이동 시 soft navigation으로 모달 형태로 상세 정보를 표시하고, hard navigation으로 페이지 이동 시 상세 페이지를 보여주도록 구현했다.