Custom App
Next.js 에서는 App 컴포넌트를 사용하여 페이지를 초기화합니다.
이를 재정의하면 페이지 초기화 시 다양한 작업을 수행할 수 있습니다.
예를 들어:
- 공통 레이아웃을 생성할 수 있습니다.
- 페이지에 추가적인 데이터를 주입할 수 있습니다.
- 전역 CSS 를 추가할 수 있습니다.
사용 방법
기본 App 컴포넌트를 제정의하려면 pages/_app 파일을 아래와 같이 생성합니다.
// pages/_app.tsx
import type { AppProps } from 'next/app';
export default function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
- Component 속성은 현재 활성 페이지를 나타내며, 경로 간 이동 시 Component 는 새로운 페이지로 변경됩니다. 따라서 Component 에 전달하는 모든 props 는 해당 페이지에서 받을 수 있습니다.
- pageProps 는 Next.js 의 데이터 페칭 메서드에 의해 미리 로드된 초기 props 를 포함하는 객체입니다. 데이터가 없을 경우 빈 객체가 됩니다.
App 컴포넌트에서는 Next.js 의 데이터 페칭 메서드 (getStaticProps, getServerSideProps) 를 사용할 수 없습니다.
getInitialProps 와 App
App 컴포넌트에서 getInitialProps 를 사용하면 getStaticProps 가 없는 페이지에 대해 자동 정적 최적화가 비활성화됩니다. 이 패턴은 권장되지 않지만, 점진적으로 App 라우터를 도입해 페이지와 레이아웃의 데이터를 쉽게 가져오는 것이 좋습니다.
// pages/_app.tsx
import App, { AppContext, AppInitialProps, AppProps } from 'next/app';
type AppOwnProps = { example: string };
export default function MyApp({
Component,
pageProps,
example,
}: AppProps & AppOwnProps) {
return (
<>
<p>Data: {example}</p>
<Component {...pageProps} />
</>
);
}
MyApp.getInitialProps = async (
context: AppContext
): Promise<AppOwnProps & AppInitialProps> => {
const ctx = await App.getInitialProps(context);
return { ...ctx, example: 'data' };
};
- MyApp 컴포넌트: Component, pageProps, 추가 속성을 받아서 렌더링합니다.
- getInitialProps 함수: App 컴포넌트에서 데이터를 가져오며, 이를 통해 페이지 전역 데이터를 제공할 수 있습니다. 이 함수는 context 객체를 받아 필요한 데이터를 가져옵니다.
Custom Document
커스텀 Document 를 사용하면 페이지를 렌더링할 때 사용되는 <html> 및 <body> 태그를 업데이트할 수 있습니다.
기본 Document 를 재정의하려면 아래와 같이 pages/_document 파일을 생성합니다.
// pages/_document.tsx
import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
• _document는 서버에서만 렌더링되므로, onClick 같은 이벤트 핸들러를 사용할 수 없습니다.
• <Html>, <Head>, <Main>, <NextScript>는 페이지가 제대로 렌더링되기 위해 필요합니다.
- _document 에서 사용되는 <Head> 컴포넌트는 next/head 와 다릅니다. 여기서 사용하는 헤드 컴포넌트는 모든 페이지에 공통으로 들어가는 <head> 코드를 위해서만 사용해야 합니다. <title> 태그와 같은 경우는 페이지나 컴포넌트에서 next/head 를 사용하는 것이 좋습니다.
- <Main> 바깥의 React 컴포넌트는 브라우저에서 초기화되지 않습니다. 여기서 애플리케이션 로직이나 커스텀 CSS 를 추가하면 안됩니다. 모든 페이지에 공통된 컴포넌트 (메뉴, 툴바 등) 가 필요하다면, Layouts 를 참조하세요.
- Document 는 현재 getStaticProps 나 getServerSideProps 와 같은 Next.js 데이터 페칭 메서드를 지원하지 않습니다.
renderPage 커스터마이징
renderPage 커스터마이징은 고급 기능으로, CSS-in-JS 라이브러리가 서버 사이드 렌더링을 지원하도록 하는 데 필요합니다. 내장된 styled-jsx 지원에는 필요하지 않습니다.
이 패턴의 사용은 권장되지 않습니다. 대신, App 라우터를 점진적으로 도입하여 페이지와 레이아웃의 데이터를 더 쉽게 가져오는 방법을 고려하는 것이 좋습니다.
// pages/_document.tsx
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
DocumentInitialProps,
} from 'next/document';
class MyDocument extends Document {
static async getInitialProps(
ctx: DocumentContext
): Promise<DocumentInitialProps> {
const originalRenderPage = ctx.renderPage;
// React 렌더링 로직을 동기적으로 실행
ctx.renderPage = () =>
originalRenderPage({
// 전체 React 트리를 래핑하는 데 유용
enhanceApp: (App) => App,
// 페이지별로 래핑하는 데 유용
enhanceComponent: (Component) => Component,
});
// 부모 `getInitialProps`를 실행하고, 이제 커스텀 `renderPage`가 포함됨
const initialProps = await Document.getInitialProps(ctx);
return initialProps;
}
render() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
• _document의 getInitialProps는 클라이언트 측 전환 중에 호출되지 않습니다.
• _document의 ctx 객체는 getInitialProps에서 받는 것과 동일하며, 여기에 renderPage가 추가로 포함됩니다.
결론
커스텀 App
Next.js에서 커스텀 App 컴포넌트를 사용하면 애플리케이션 초기화 시 다음과 같은 작업을 수행할 수 있습니다:
- 공통 레이아웃 생성: 모든 페이지에 적용될 공통 레이아웃을 정의할 수 있습니다.
- 추가 데이터 주입: 페이지 초기화 시 필요한 추가 데이터를 전역적으로 주입할 수 있습니다.
- 전역 CSS 추가: 애플리케이션 전체에 적용되는 전역 CSS를 설정할 수 있습니다.
주요 포인트:
pages/_app.tsx
파일을 생성하여 커스텀 App 컴포넌트를 정의합니다.Component
와pageProps
를 사용하여 현재 페이지와 페이지 props를 전달합니다.- App 컴포넌트에서는
getStaticProps
와getServerSideProps
를 사용할 수 없으며,getInitialProps
를 사용하면 자동 정적 최적화가 비활성화됩니다.
권장 사항:
- 페이지에서 직접 데이터 페칭 메서드를 사용하고, App 라우터를 도입하여 데이터 페칭을 쉽게 관리하는 것이 좋습니다.
커스텀 Document
커스텀 Document를 사용하면 페이지를 렌더링할 때 사용되는 <html>
및 <body>
태그를 업데이트할 수 있습니다. 이를 통해 전역적인 HTML 구조와 메타 정보를 설정할 수 있습니다.
주요 포인트:
pages/_document.tsx
파일을 생성하여 커스텀 Document 컴포넌트를 정의합니다.<Html>
,<Head>
,<Main>
,<NextScript>
컴포넌트를 사용하여 페이지가 제대로 렌더링되도록 설정합니다._document
는 서버에서만 렌더링되므로 이벤트 핸들러를 사용할 수 없습니다.
주의사항:
<Head>
컴포넌트는 모든 페이지에 공통으로 들어가는 코드를 위해 사용해야 하며, 페이지별 메타 정보는next/head
를 사용하는 것이 좋습니다.<Main>
바깥의 React 컴포넌트는 브라우저에서 초기화되지 않으므로, 여기서 애플리케이션 로직이나 커스텀 CSS를 추가하지 않아야 합니다.- Document는 현재
getStaticProps
나getServerSideProps
와 같은 데이터 페칭 메서드를 지원하지 않습니다.
결론적으로, 커스텀 App과 커스텀 Document를 활용하면 Next.js 애플리케이션의 초기화와 전역 설정을 효율적으로 관리할 수 있습니다.
'Next.js' 카테고리의 다른 글
[Next.js] 자동 정적 최적화 (0) | 2024.08.22 |
---|