관리 메뉴

즐겁게, 코드

Next.js의 _document와 _app에 대하여 본문

🎨 프론트엔드/Next.js

Next.js의 _document와 _app에 대하여

Chamming2 2021. 5. 29. 02:15

Next.js에는 두 가지 중요한 기본 페이지가 있는데요, 바로 _document_app 입니다.

_document_app에는 페이지에 공통적으로 적용될 내용을 작성하곤 하는데, 둘이 정확히 어떻게 다른지와 어떤 내용을 작성해야 하는지에 대해 정리해 보겠습니다.

📝 App 페이지

_app은 서버로 요청이 들어왔을 때 가장 먼저 실행되는 컴포넌트로, 페이지에 적용할 공통 레이아웃의 역할을 합니다.

🎯 주요 사용 목적

  • 모든 컴포넌트에 공통으로 적용할 속성 관리
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp

⚙️ 규칙

1. Component 속성값은 서버에 요청한 페이지가 됩니다.

(Ex. http://localhost:3000/home에 접속하면, Component는 home 컴포넌트를 가리킵니다.)

2. pageProps는 getInitialProps, getStaticProps, getServerSideProps 중 하나를 통해 페칭한 초기 속성값이 됩니다.

 

3. _app에서도 getInitialProps를 사용해 모든 페이지에서 사용할 공통 속성값을 지정할 수 있으나, 이럴 경우 자동 정적 최적화(Automatic Static Optimization)이 비활성화되어 모든 페이지가 서버 사이드 렌더링을 통해 제공됩니다. (※ 출처 - 공식 문서 중)

 

4. 만약 _app에서 getInitialProps를 사용하고자 한다면, 꼭 아래처럼 App 객체를 불러온 후 getInitialProps를 통해 데이터를 불러와야 합니다.

import App from 'next/app'

function app({ Component, pageProps }) {
    return <Component {...pageProps} />
  }
   
app.getInitialProps = async (appContext) => {
  const appProps = await App.getInitialProps(appContext);
  
  return { ...appProps }
}

📝 Document 페이지

_document_app 다음에 실행되며, 공통적으로 활용할 <head> (Ex. 메타 태그)나 <body> 태그 안에 들어갈 내용들을 커스텀할때 활용합니다.

🎯 주요 사용 목적

  • 폰트 임포트
  • charset, 웹 접근성 관련 태그 설정
// 기본적인 _document의 형태

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

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    return { ...initialProps }
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument

⚙️ 규칙

1. _document를 작성할 때는 Document 클래스를 상속받는 클래스 컴포넌트로 작성해야만 하며, 렌더 함수는 꼭 <Html>, <Head>, <Main>, <NextScript> 요소를 리턴해줘야 합니다.

 

2. _document에서 사용하는 <Head> 태그는 next/head가 아닌 next/document 모듈에서 불러와야 하는데요, _document의 <Head> 태그에는 모든 문서에 공통적으로 적용될 내용(Ex. charset, 뷰포트 메타태그 등)이 들어가야 합니다.

import Document, { Html, Head, Main, NextScript } from "next/document";

export default class MyDocument extends Document {

  render() {
    return (
      <Html>
        <Head>
          <!-- 모든 페이지의 제목이 C17AN's Devlog로 변합니다. -->
          <title>C17AN's Devlog</title>
          <meta charSet="utf-8"></meta>
          <body>
            <Main />
            <NextScript />
          </body>
        </Head>
      </Html>
    );
  }
}

(+ 만약 페이지의 제목(<title>)이나 open graph 등 페이지별로 다르게 적용되어야 하는 내용들은 각 페이지별로 처리해야 합니다.)

 

4. _document언제나 서버에서 실행되므로 브라우저 api 또는 이벤트 핸들러가 포함된 코드는 실행되지 않습니다.

또한 <Main /> 부분을 제외한 부분은 브라우저에서 실행되지 않으므로 이곳에 비즈니스 로직을 추가해서는 안되며, _app과 마찬가지로 getStaticPropsgetServerSideProps 를 통해 데이터를 불러올 수 없습니다.

 

🧮 요약

  • _app은 로직, 전역 스타일 등 컴포넌트에 공통 데이터를 다룬다. (보다 JS스러운?)
  • _document는 공통적으로 적용할 HTML 마크업을 중심으로 다룬다.

 

🎯 참고 & 읽어보면 아주 좋을 글

 

Next js 구동방식 과 getInitialProps

Next js가 React Project의 SSR을 가능하게 한다. 라고는 하는데, 어떤 방식으로 SSR을 가능하게 할까, SSR과 CSR의 구분은 어떻게 되어 있을까.이 궁금증을 해결하기 위해, 먼저 알아야 할 것은 Next js의 구

velog.io

 

Advanced Features: Custom `App` | Next.js

Control page initialization and add a layout that persists for all pages by overriding the default App component used by Next.js.

nextjs.org

 

Advanced Features: Custom `Document` | Next.js

Extend the default document markup added by Next.js.

nextjs.org

 

반응형
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆