_app.jsx(tsx)

```tsx
// pages/_app.tsx

import { AppProps } from 'next/app';

const MyApp = ({ Component, pageProps }: AppProps) => {
	return <Component {...pageProps} />
};

export default MyApp;
```
  • _app.jsx(tsx) 내의 컴포넌트는 모든 페이지를 렌더할 때 항상 호출됩니다. 그래서 모든 페이지에 필요한 공통 로직의 경우 App 컴포넌트에 추가할 수 있습니다.

_app.jsx(tsx) 필요한경우

  • 페이지 이동할 때마다 유지해야 하는 스타일이나 레이아웃 적용
  • 페이지 이동할 때 유지해야할 state 관리
  • componentDidCatch 라이프사이클로 공통 에러 처리
  • 페이지에 공통 로직을 통해 데이터를 주입해야하는 경우
  • 모든 페이지에 필요한 css를 적용하는 경우

_app.jsx(tsx)의 site title tag

site의 title 또한 _app.tsx에서 추가하는데 아래와 같이 next/head에서 Head 컴포넌트를 import해서 사용하면 됩니다.

```tsx
import { AppProps } from 'next/app';
import Head from 'next/head';

const MyApp = ({ Component, pageProps }: AppProps) => {
    return (
        <>
            <Head>
                <title>제목 여기에</title>
            </Head>
            <Component {...pageProps} />
        </>
    );
};
export default MyApp;
```

동적 title이 필요할 때는 pages 폴더 하위에 개별 컴포넌트마다 title 태그를 추가하면 overwrite 됩니다.

import React from 'react';
import Head from 'next/head';
import {
  MainSection,
  FeaturesSection,
  ReviewsSection,
  CommunityPoolSection,
} from 'components/Business';

const Business: React.FC = () => {
  return (
    <>
      <Head>
        <title>동적 제목 여기에</title>
      </Head>

      <MainSection />
      <FeaturesSection />
      <ReviewsSection />
      <CommunityPoolSection />
    </>
  );
};

export default Business;

_document.jsx(tsx)

Next.js에는 SPA에서 하나의 html역할을 하는 index.html이 물리적으로 존재하지 않습니다.

하지만, 링크로 font 파일을 가져오거나, script 태그로만 넣을 수 있는 라이브러리가 필요하거나, Google Analytics 같은 것을 설정할 때 html의 head태그와 body태그가 필요합니다.

이때, Next.js에서 이 역할을 하는 것이 _document.js입니다.


_document.jsx(tsx) 파일 추가

pages폴더 바로 밑에 _document.jsx(tsx) 이름으로 생성해야 하며, 다음 코드와 똑같이 작성해주세요.

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

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

  render() {
    return (
      <Html>
        <Head>
          <link
            href="https://fonts.googleapis.com/css?family=Noto+Sans+KR|Poppins&display=swap"
            rel="stylesheet"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;
  • next/document 에서 import한 Html, Head, Main, NextScript 컴포넌트는 build후에 html, head, main, script 태그가 됩니다.
  • 이 컴포넌트를 import하지 않으면 Next.js가 제대로 서버 사이드 렌더링을 할 수가 없습니다. getInitialProps는 서버사이드렌더링을 위한 메서드이며, 추후에 설명할 예정입니다.
  • 주의할 점은 _document.js는 서버에서만 실행되는 파일이므로 window같은 브라우저 전역객체를 사용할 수 없습니다. 또한 컴포넌트에 필요한 공통 로직의 경우 _document.js가 아닌 _app.js에서 추가해야 합니다.
  • 위의 예제에서는, 구글 폰트를 추가해보았습니다.

_error.jsx(tsx)

존재하지 않는 라우트에 접근하여 “없는 페이지”라고 안내하는 404 페이지나 서버 500 에러의 응답 페이지 또한 customizing할 수 있습니다.

// pages/404.tsx

export default function Custom404() {
  return <h1>404 - Page Not Found</h1>;
}
// pages/_error.tsx

import { NextPageContext } from 'next';
import { ErrorProps } from 'next/error';

const Error = ({ statusCode }: ErrorProps) => {
  return (
    <p>
      {statusCode ? `An error ${statusCode} occurred on server` : 'An error occurred on client'}
    </p>
  );
};

Error.getInitialProps = ({ res, err }: NextPageContext) => {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
  return { statusCode };
};

export default Error;

next.config.js

프로젝트에 추가적으로 환경 설정을 하고 싶을 때 package.json 과 같은 위치인 루트 경로에 **“next.config.js”**라는 이름으로 설정파일을 추가하고 활용합니다.

next.config.js 옵션이 있나?

  • .next 라는 빌드 결과물의 폴더 이름을 변경하거나 빌드 할 때마다 생성되는 build id 등을 고정할 수도 있습니다.
  • 실무에서 프로젝트를 할 때 dev 모드, production 모드, staging 모드에 따라 api url이 다른 경우가 있습니다. 아래와 같이 **NODE_ENV**로 환경을 확인하여 api url을 분기할 수 있습니다.
  • https://nextjs.org/docs/api-reference/next.config.js/introduction

next.config.js 실습 - 개발 모드에 따라 API 분기하기

  • “yarn dev”로 프로젝트를 실행하면 아래 코드에서 env는 ”development“이고, “yarn build”로 실행하면 env는 ”production“이 됩니다.
const env = process.env.NODE_ENV;

switch (env) {
	case 'development':
		API_URL = 'http://localhost:8080;
		break;
	case 'staging':
		API_URL = 'https://stg.api.evereathing.com';
		break;
	case 'production':
		API_URL = 'https://api.evereathing.com';
		break;
	default:
		API_URL = 'https://api.evereathing.com';
}

module.exports = {
	env: {
		API_URL
	}
};
  • staging을 추가하고 싶을 때는 package.json의 “scripts”에 스크립트를 추가하면 됩니다.
"scripts": {
	"dev": "next",
	"build:staging": "NODE_ENV=staging next build",
	"build": "next build",
	"start": "next start -p 80"
},
  • 이렇게 설정한 API_URL은 아래와 같이 사용할 수 있습니다.
// utils/config.ts
export const API_URL = process.env.API_URL;
// API_URL 사용 예제
import { API_URL } from 'utils/config';

//생략
fetch(`${API_URL}/users`).then().then();