본문 바로가기

main/Next.js

[Next.js] 기존 React 프로젝트 Next.js로 바꾸기 - 2 (공통 페이지)

Next.js의 구동방식을 알아보며 _app과 _document에 대해 알아보겠다.

 

_app / _document

위 두 파일은 없어도 Next의 실행에는 문제가 없다. 커스터마이징이 필요할 때 사용하게 되는 파일이다.

Server Only File으로, Next Client에서 사용하는 로직(eventlistener 등의 window/DOM 로직)을 사용하면 안된다. window is not defined 라는 에러를 보게 된다면 해당 사항을 체크해봐야 한다. (!!이 에러가 나는게 그래서였군..)

 

최초로 실행되는 것은 _app.js이다. 요청한 페이지를 먼저 Component에서 띄우게 된다.

그 다음 _document.js가 실행된다. _app.js에서 구성한 HTML이 어떤 형태로 들어갈지 구성하게 된다.

 

✏ _app

App 컴포넌트는 모든 페이지의 공통 페이지이다.

- 페이지들의 공통된 레이아웃

- 페이지를 탐색할 때 상태 유지

- 추가 데이터를 페이지에 주입

- 글로벌 CSS 추가

import React, { useEffect, useState } from "react";
import styled from "styled-components";

import Header from "../components/Header";
import Footer from "../components/Footer";
import GlobalStyle from "../styles/GlobalStyle";

const App = ({ Component, pageProps }) => {
  return (
  <>
    <GlobalStyle />
    <Header />
    <Content>
      <Component {...pageProps} />
    </Content>
    <Footer />
  </>
  );
};

const Content = styled.section`
  display: block;
  width: auto;
  height: auto;
`;

export default App;

App 컴포넌트는 Component라는 props를 받게 되는데, Component는 불러오는 페이지이다.

Component는 pageProps를 props로 받고 있는데, 이는 pages 안의 파일에서 getServerSideProps, getStaticProps 혹은 getInitialProps로 페이지에 전달해주는 props이다.

 

✏ _document

Document 는 일반적으로 <html> 및 <body> 태그를 보강하는 데 사용된다. 모든 페이지의 공통 페이지이다.

- <title>, <meta> 등 정보를 제공하는 HTML 코드 작성

- 폰트 등의 외부 api, cdn 등을 불러옴

import Document, { Html, Head, Main, NextScript, DocumentContext } from "next/document";
import { ServerStyleSheet } from "styled-components";

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }

  render() {
    return (
      <Html>
        <Head>
          <link
            href="https://fonts.googleapis.com/css?family=Noto+Sans:400,700&display=swap"
            rel="stylesheet"
          />
          <script defer src="https://developers.kakao.com/sdk/js/kakao.js" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

 

 

✏ getServerSideProps / getStaticProps

웹 페이지에는 각 페이지마다 사전에 불러와야할 데이터들이 있다.

react 로직에 따라 componentDidmount / useEffect로 컴포넌트가 마운트된 후 Data Fetching 된다.

이 과정을 서버에서 미리 처리하도록 도와주는 것이 getInitialProps이다.

Next 9.3 이상부터는 getInitialProps보다 getServerSideProps / getStaticProps를 사용하는 것이 권장된다.

 

import fetch from "isomorphic-unfetch";

export const getServerSideProps = async ({ query }) => {
  try {
    const res = await fetch(`url`);
    if (res.status === 200) {
      const user = await res.json();
      return { props: { user } };
    }
    return { props: {} };
  } catch (e) {
    console.log(e);
    return { props: {} };
  }
};

getServerSideProps는 이름 그대로 서버 측에서 props를 받아오는 기능을 하게 된다. 페이지 요청 시마다 실행되며 서버에서 실행되기 때문에 콘솔 출력이 터미널에서 되는 것을 확인할 수 있다.

 

getStaticProps는 getServerSideProps와 다르게 빌드 시에 데이터를 불러와 결과를 json으로 저장하여 사용하게 된다. 따라서 일관된 데이터를 보여주게 된다.

 

 

공통된 Data Fetching이 필요하다면 _app에, 페이지별로 필요하다면 페이지에 붙이면 된다.

다만, 한 페이지에는 하나의 getInitialProps 로직만 실행된다. 예를 들어 _app에서 사용하면 그 하부 페이지에서는 실행되지 않는다. 때문에 커스터마이징 과정이 필요하다.

이 부분은 아직 직접 코드를 통해 이해하지 못해서 글로 기록만 해 둔다. 예제로 구현하게 되면 첨부하도록 하겠다.

 

 

 

next.js 클론코딩 책과 다음 링크를 참조하여 작성했다.

 

Next js 구동방식 과 getInitialProps

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

velog.io