Front-end/Nextjs

Next.js _app과 _document에 대하여

아지송아지 2022. 5. 9. 16:27

안녕하세요!

오늘은 Next.js의 _app과 _document에 대하여 알아보겠습니다.

 

next.js를 처음 설치하면 pages 폴더 안에 _app파일이 보이실 겁니다.

_document가 없을 경우 따로 만드시면 됩니다.

저는 타입스크립트여서 .tsx 입니다.

 

 

1. _app

가장 먼저 실행되는 컴포넌트로, 모든 페이지는 _app을 통해 실행됩니다.

 

다음과 같은 특성들이 있습니다.

 

1. 페이지가 변경되어도 레이아웃과 상태 값을 유지합니다.

2. "componentDidCatch"를 통해 에러 핸들링이 가능합니다.

3. 페이지에 추가적인 데이터를 삽입할 수 있습니다.

4. Global CSS는 이곳에 추가합니다.

5. 헤더와 푸터같이 공통적으로 사용하는 레이아웃은 이곳에 추가합니다.

 

import '../styles/globals.css'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />
}

export default MyApp

기본적인 _app.tsx의 구조입니다.

props로 Component와 pageProps를 받아오는데요.

 

Component

Component는 현재 페이지를 의미합니다.

페이지가 변경되면 Component가 변경됩니다.

 

"http://localhost:3000/"은 index.tsx를 가리키며, "http://localhost:3000/about"은 about 컴포넌트를 가리킵니다.

 

 

pageProps

getInitialProps, getStaticProps, getServerSideProps 를 통해 가져온 초기 속성값을 의미합니다.

위의 값들이 없다면 빈 객체를 반환합니다.

// about.tsx
...
export async function getStaticProps() {
  const test = "Hello";
  return {
    props: {
      test,
    },
  };
}
_app.tsx
...
function MyApp({ Component, pageProps }: AppProps) {
  console.log(pageProps); // {test: 'Hello'}
  return <Component {...pageProps} />;
}

만약 위와 같이 about.tsx에서 getStaticProps를 사용한다고 했을 때,

_app.tsx에서 pageProps를 콘솔로 찍으면 {test: 'Hello'}가 출력됩니다.

 

 

_app - getStaticProps, getServerSideProps

* _app은 getStaticProps와 getServerSideProps를 지원하지 않습니다.

 

 

_app - getInitialProps

* _app에서 getInitialProps를 사용한다면 Automatic Static Optimization이 비활성화되어 모든 페이지가 서버 사이드 렌더링 됩니다.

import App from 'next/app'

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

MyApp.getInitialProps = async (appContext) => {
   const appProps = await App.getInitialProps(appContext);
   return { ...appProps }
 }

export default MyApp
Custom App
When you add getInitialProps in your custom app, you must import App from "next/app", call App.getInitialProps(appContext) inside getInitialProps and merge the returned object into the return value.

_app에서 getInitialProps에서 사용할 때는 getInitialProps 안에 App을 통해 불러온 App.getInitialProps를 통해 반환해야 합니다.

 

 

 

 

 

2. _document

모든 페이지에서 공통적으로 사용하는 html, head(meta) 혹은 body 태그 안에 들어가는 커스텀할 때 사용합니다.

 

1. 서버에서만 렌더링 됩니다.

2. onClick 같은 이벤트나 CSS는 사용하지 않습니다.

어플리케이션 로직은 넣으면 안 됩니다. 필요하다면 _app에서 넣어야 합니다.

 

 

3. 반드시 HTML, Head, Main, NextScript를 포함해야 합니다.

 

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

기본적인 _document 구조입니다.

 

모든 페이지에서 공통적으로 적용되어야 하는 <head>만 _document에 넣으며,

title 같이 페이지마다 바뀌는 것들은 각 페이지 별로 넣어야 합니다.

_document 에서는 "next/document"의 Head를 사용하며 그 외 컴포넌트에서는 "next/head"의 Head를 사용합니다.

 

 

_document - getStaticProps, getServerSideProps

* _documnet 또한  getStaticProps와 getServerSideProps를 지원하지 않습니다.

 

 

 

 

정리

모든 페이지는 _app과 _document 를 거쳐갑니다.

_app 이후에 _document가 실행됩니다.

_app은 어플리케이션 로직, 글로벌 스타일 등을 다룹니다.

_document는 HTML 마크업 자체에 집중합니다.

 

 

참고 :

https://nextjs.org/docs/advanced-features/custom-app

https://nextjs.org/docs/advanced-features/custom-document