Next.js 레이아웃 다루기

이민영·2023년 11월 20일
post-thumbnail

서론

Next.js로 개인프로젝트를 하는 중 공통 레이아웃으로 모든 페이지에 레이아웃을 적용하는게 아닌 각 페이지마다 각각 다른 레이아웃을 적용해야 했다. React만 쓰다가 Next.js로 넘어온 지 얼마 안 돼서 여러모로 익숙지 않아 공식 문서를 보면서 해봤다.

공통 레이아웃 하나로 모든 페이지에 적용하는 방법과 각 페이지마다 개별 레이아웃을 적용하는 방법은 각각 다르다. 상황에 따라 각 방법을 적용하는 법을 알아보자.

공식 문서

https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern

공통 레이아웃으로 모든 페이지 적용하기

헤더와 푸터를 모든 페이지에 적용하려면 공통 레이아웃을 만들고 _app.tsx에 공통 레이아웃을 적용하면 된다.

components/layout/layout.tsx

import Header from '../header/header';
import Footer from '../footer/footer';
import { ReactNode } from 'react';

export default function AppLayout(props: { children: ReactNode })

{
  return (
    <>
      <Header />
      <main>{props.children}</main>
      <Footer />
    </>
  );
}

pages/_app.tsx

import AppLayout from "components/layout/layout";

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

각 페이지마다 개별 레이아웃 적용하기

1. 공통 레이아웃 제작

공통으로 사용할 레이아웃 만든다.

components/layout/layout.tsx

import Header from '../header/header';
import Footer from '../footer/footer';
import { ReactNode } from 'react';

export default function AppLayout(props: { children: ReactNode })

{
  return (
    <>
      <Header />
      <main>{props.children}</main>
      <Footer />
    </>
  );
}

2. 개별 레이아웃 제작

개별 페이지에 사용할 레이아웃을 만든다.

components/layout/MypageLayout.tsx

import { ReactNode } from 'react';
import MypageCategory from '../mypage/mypageCategory';

const MypageLayout = (props: { children: ReactNode }) => {
  return (
    <>
      <MypageCategory />
      {props.children}
    </>
  );
};

export default MypageLayout;

3. getLayout 적용

_app.tsx에 getLayout 적용하기 위해 설정한다.

pages/_app.tsx

import '../styles/globals.css';
import type { ReactElement, ReactNode } from 'react';
import type { NextPage } from 'next';
import type { AppProps } from 'next/app';

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

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

export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
  const getLayout = Component.getLayout ?? ((page) => page);

  return {getLayout(<Component {...pageProps} />)};
}

4-1. 공통 + 개별 레이아웃 적용

pages/mypage/index.tsx

import { NextPageWithLayout } from '../_app';
import { ReactElement } from 'react';
import AppLayout from '../../components/layout/layout';
import MypageLayout from '../../components/layout/mypageLayout';

const Mypage: NextPageWithLayout = () => {
  return <h1>마이페이지</h1>;
};

Mypage.getLayout = function getLayout(page: ReactElement) {
  return (
    <AppLayout>
      <MypageLayout>{page}</MypageLayout>
    </AppLayout>
  );
}

export default Mypage;

4-2. 공통 레이아웃 적용

pages/index.tsx

import { ReactElement } from 'react';
import { NextPageWithLayout } from './_app';
import AppLayout from '../components/layout/layout';

const Home: NextPageWithLayout = () => {
  return (
      <h1>메인페이지</h1>
  );
};

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

export default Home;

4-3. 개별 레이아웃 적용

pages/mypage/heart.tsx

import { NextPageWithLayout } from '../_app';
import { ReactElement } from 'react';
import MypageLayout from '../../components/layout/mypageLayout';

const Heartpage: NextPageWithLayout = () => {
  return <h1>좋아요페이지</h1>;
};

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

export default Heartpage;
profile
Frontend Developer

0개의 댓글