page router에서 라우트 별 레이아웃 설정
나는 남들만큼 app router를 좋아하지는 않는다. 아직까지는 버그 투성이라 ─ 개발하다보면 계속 dev server를 끄고 .next를 삭제하고의 반복 ─ 토이 프로젝트에 쓰기도 민망한 수준이라 생각한다. 하지만 app router를 쓰고 싶다 생각하게 되는 순간이 가끔 있는데, 특히 라우트를 따라 중첩되는 layout.tsx의 존재가 그렇다.
프로젝트의 공통된 레이아웃 몇 가지를 LayoutWrapper 컴포넌트로 만들어서 각 페이지 마다 가져다 썼지만, 이런 식의 해결책이 썩 만족스럽지는 않았다. 특히 대부분의 페이지에서 공통적으로 사용되는 레이아웃을 반복해서 호출하는 부분이 걸렸다. 때문에 이런 저런 블로그를 뒤적거리다가 생각보다 괜찮은 패턴 하나를 찾을 수 있었다. per-page layout 이라는 이름으로 공유되고 있는 듯한데, 나는 이걸 바탕으로 내 입맛에 맞게 조금 수정하여 사용하기로 했다.
// _app.tsx
type LayoutProps = {
useDefaultLayout?: boolean;
layout?: ({children}: {children: ReactNode}) => ReactNode;
}
type AppPropsWithLayout = AppProps & {
Component: NextPage & LayoutProps;
}
const getLayout = ({useDefaultLayout = true, layout}: LayoutProps) => {
if (useDefaultLayout) return DefaultLayout;
else return layout ?? BasicLayout;
}
export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
const Layout = getLayout(Component)
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
};
기본적인 코드 구조는 위와 같다. 가장 자주 사용하는 레이아웃을 DefaultLayout으로 지정하여 별다른 옵션을 설정하지 않는 한 페이지 컴포넌트에 DefaultLayout이 감싸지도록 했다. 이외의 경우에는 useDefalutLayout과 layout 프로퍼티를 통해 각각의 페이지에서 추가적으로 설정할 수 있는데, 그 방식은 아래와 같다.
export default function Page() {
return <>{...}</>
}
Page.useDefaultLayout = false;
Page.layout = LayoutWithoutSideBar
블로그의 정보
Ayden's journal
Beard Weard Ayden