개발 지식 정리

[NextJS] per-page Layout을 사용한 공통 레이아웃 적용

Geonwoo 2023. 3. 14. 23:56

프로젝트를 진행하다보면 해당 애플리케이션의 레이아웃이 존재하게 되는데, 모든 페이지마다 레이아웃을 적용하기엔 반복적인 코드가 들어가기 마련이다.

그래서 오늘은 프로젝트 레이아웃을 공통적으로 적용하는 방법에 대해서 정리하면서, Nextjs 문서에서 소개하는 per-page Layout을 이용하여 다수의 레이아웃을 사용할 수 있는 방법에 대해서도 소개하도록 하겠다.

 

들어가기 전

일단 공통 레이아웃을 작성하기 전에 Nextjs의 구조를 한 번 살펴보자.

pages 폴더 내부에 존재하는 _app.tsx 파일은 서버에 요청이 들어가면 가장 먼저 실행되는 최상위 컴포넌트를 담당한다.

모든 페이지가 초기화 되기 전 해당 파일을 거쳐가기 때문에 애플리케이션의 전체적인 설정을 해줄 수 있는 공간이라고 표현해보겠다.

그렇다면 공통 레이아웃은 어떤 페이지에서 작성하면 될까? 위에서 살펴본 것처럼 _app.tsx 파일에서 작성해주면 된다.

공통 레이아웃 작성

import '@/styles/globals.css'
import type { AppProps } from 'next/app'
import {AppLayout} from "components/layout"

export default function App({ Component, pageProps }: AppProps) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

 

애플리케이션의 레이아웃에 맞게 Layout 컴포넌트를 하나 작성해서 _app.tsx 파일 내에서 사용한다.

Layout 컴포넌트로 감싸진 Component는 하나의 페이지를 뜻한다.

 

다수 레이아웃 사용( feat. per-page Layout)

애플리케이션의 레이아웃을 공통적으로 사용하지 않고 페이지마다 다른 레이아웃을 사용해야한다면 Nextjs에서는 per-page Layout을 사용하라고 권고한다.

페이지마다 다른 레이아웃을 지정해주는 getLayout 함수를 보면 Null 병합 연산자를 통해 Component.getLayout이 undefined 또는 null이 아닌 경우 해당 페이지에서 지정한 레이아웃을 사용하도록 한다.

// _app.tsx
import '@/styles/globals.css';
import { NextPage } from 'next';
import type { AppProps } from 'next/app';
import { ReactElement, ReactNode } from 'react';
import Layout from '@/components/common/Layout';

export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
  getLayout?: (page: ReactElement) => ReactNode;
};

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout;
};

export default function App({ Component, pageProps }: AppPropsWithLayout) {
  const getLayout = Component.getLayout ?? ((page) => <Layout>{page}</Layout>);
  return getLayout(
  	<Component {...pageProps} />
  );
}

 

특정 페이지 내에서 레이아웃을 지정해주는 경우에는 아래처럼 getLayout을 통해 레이아웃을 설정해줄 수 있다

// Auth/index.tsx
import { ReactElement } from 'react';
import { NextPageWithLayout } from '../_app';
import AuthLayout from '@/components/common/AuthLayout';

export const Auth: NextPageWithLayout = () => {
  return <div>auth</div>
};

Auth.getLayout = function getLayout(page: ReactElement) {
  return <AuthLayout>{page}</AuthLayout>
};

export default Auth;

만약 공통 레이아웃 내에 중첩 레이아웃이 필요한 경우에는 공통 레이아웃 내부에 특정 페이지 레이아웃을 지정해주면 된다.

 

 

이제 페이지 코드의 중복도 줄이고 작성하면서 일일이 레이아웃으로 감싸주지 않고도 공통 레이아웃을 작성할 수 있을것이다.

이번 포스팅도 많은 개발자 분들에게 도움이 되었으면 좋겠다.