📢 어렵고 정석적인 개념 설명보다는 저같은 초보자도 이해하기 쉽게 정리하는 것을 원칙으로 포스팅하고 있습니다. 😄

[Next.js] 레이아웃 구성하기 : 공통 요소들은 한 곳에서 관리하자!

_app.js와 _document.js

next.js를 설치하면 pages안에 _app.js_document.js가 기본적으로 들어있는 것을 확인할 수 있다.

리액트와 비교했을 때 _app.js는 App.js와 같고 _document.js는 index.html과 같다. _app.js는 root 컴포넌트로 다른 컴포넌트를 자식 컴포넌트로 받아와서 렌더링 한다. _document.js는 모든 페이지에 공통적으로 들어가는 html 문서 역할을 하며, 메타 태그나 폰트 등 전체 페이지에서 적용되는 html 태그들을 관리한다.

🙋🏻‍♂️ 각 파일 간 포함 관계 정리 (렌더링 과정)
1) _document.js의 <Main />에는 _app.js가 래핑된다.
2) _app.js의 <Component />에는 index.js에서 정의한 페이지 컴포넌트가 같이 렌더링된다.
3) 정리하자면, _document.js 안에 _app.js 안에 index.js인 것.

 

Layout 컴포넌트로 레이아웃 만들기

// Layout.js
export default function Layout({ children }) {
    return (
        <>
            <header>로고</header>
            <main>{children}</main>
        </>
    )
}

// _app.js
export default function App({ Component, pageProps }) {
    return (
        <Layout>
            <Component {...pageProps} />
        </Layout>
    )
}

보통 애플리케이션을 개발한다고 할 때, 어떤 페이지든 간에 헤더와 푸터는 고정적으로 들어가 있는 경우가 많다.

이렇게 모든 컴포넌트에 고정적으로 들어가 있는 요소들은 Layout 컴포넌트로 따로 만들어준 다음 _app.js에서 Component를 감싸준다. (참고로 부모 컴포넌트에서 자식 컴포넌트를 받아올 때는 children 파라미터를 사용한다.)

 

// SubLayout.js
export default SubLayout({ children }) {
    return (
        <div>
            {children}
            <footer>푸터입니다.</footer>
        </div>
    )
}

// About.js
export default About() {
    return (
        <div>이곳은 About 페이지입니다.</div>
    )
}

About.Layout = SubLayout;

// _app.js
export default App({ Component, pageProps }) {
    const EmptyLayout = ({ children }) => <>{children}</>;
    const SubLayout = Component.Layout || EmptyLayout;

    return (
        <Layout>
            <SubLayout>
                <Component {...pageProps} />
            </SubLayout>
        </Layout>
    )
}

만약, 특정 페이지만 다른 레이아웃을 적용하고 싶다면 어떻게 해야 할까? 우선 특정 페이지(예시 코드에서는 About.js)에 Layout 속성을 설정해 준다. 함수도 객체이기 때문에 About.Layout = SubLayout 형태로 About 컴포넌트에 Layout 속성을 설정해 줄 수 있다.

 

_app.js에는 SubLayout 변수를 만들고 About 컴포넌트가 Component 파라미터로 들어올 경우에만 Component.Layout의 값으로 미리 설정한 SubLayout을 받아오고 About 페이지가 아닐 경우에는 EmptyLayout이 <SubLayout>으로 대체하도록 해주었다.

 

1. _app.js는 모든 컴포넌트의 root 역할
2. _document.js는 메타 태그와 같은 html 문서 역할
3. 모든 페이지에 들어있는 요소들은 Layout 컴포넌트로 따로 빼서 관리하기
4. 부모 컴포넌트에서 children 파라미터는 자식 컴포넌트를 의미한다.
5. 컴포넌트 이름으로 속성-값(객체)을 설정해 주면, 컴포넌트가 렌더링 될 때 그 프로퍼티를 불러올 수 있다.