pages/_app.js 파일의 App 컴포넌트에 공통 레이아웃을 적용할 수 있다.import Header from '@/components/Header';
import { ThemeProvider } from '@/lib/ThemeContext';
import '@/styles/globals.css'; // 전체에 적용할 CSS style
export default function App({ Component, pageProps }) {
return (
<ThemeProvider> // 리액트 context 적용
<Header /> // 모든 페이지 상단에 공통적으로 Header 컴포넌트 적용
<Component {...pageProps} />
</ThemeProvider>
);
}
커스텀 App 컴포넌트의 Props는 Component와 pageProps가 있다. /pages 폴더의 페이지들이 Component Prop으로 전달되고 여기에 내부적으로 필요한 Props는 pageProps라는 값으로 전달된다.
전역에서 Theme 를 관리하는 useContext() 만들기
// /lib/ThemeContext.js import { createContext, useContext, useEffect, useState } from 'react' export const ThemeContext = createContext() // Context를 사용할 범위를 감쌀 context.Provider 생성 export function ThemeProvider({ children }) { const [theme, setTheme] = useState('dark') useEffect(() => { document.body.classList.add(theme) return () => { document.body.classList.remove(theme) } }, [theme]) return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider> } // 실제 Theme context를 사용하는 곳에서 context를 꺼낼 수 있는 커스텀 훅 생성 export function useTheme() { const themeContext = useContext(ThemeContext) if (!themeContext) { throw new Error('ThemeContext 안에서 써야 합니다') } return themeContext }
pages/_document.js 파일의 <Document> 컴포넌트는 HTML 코드의 뼈대를 수정하는 용도로 사용한다. 코드는 React 컴포넌트이지만 일반적인 컴포넌트처럼 동작하지는 않기 때문에 useState나 useEffect처럼 브라우저에서 실행이 필요한 기능들은 사용할 수 없다.
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html lang="ko">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}