Skip to main content

레이아웃 컴포넌트

레이아웃(layout) 컴포넌트는 페이지 라우터에서 자주 쓰이는 컴포넌트이자 페이지 구성 패턴입니다. 넥스트에서 레이아웃 컴포넌트는 /layouts 폴더 밑에 위치한 컴포넌트를 가리킵니다.

레이아웃 컴포넌트 목적

여러 페이지에 페이지 헤더가 존재하는 웹 애플리케이션이 있다고 해보겠습니다. 이 애플리케이션은 메인 페이지와 로그인 페이지로 구성되어 있습니다. 이때 두 페이지 모두 상단에 페이지 헤더를 다음과 같이 나타낸다고 해봅시다.

<!-- 로그인 페이지 -->
<h1>나의 앱</h1>
<main>
<form>
<label>로그인 아이디</label>
<input/>
</form>
</main>
<!-- 메인 페이지 -->
<h1>나의 앱</h1>
<main>
<section>메인</section>
</main>

이 두 페이지는 모두 헤더 역할을 하는 <h1>나의 앱</h1> 코드를 공통으로 정의하고 있습니다. 넥스트에서는 이렇게 페이지마다 공통으로 들어가는 요소를 레이아웃 컴포넌트에 정의하여 코드의 중복을 방지합니다.

layouts/Layout.jsx
export default function Layout({ children }) {
return (
<>
<h1>나의 앱</h1>
<div>{children}</div>
</>
)
}
tip

위 코드에서 <> </> 문법은 프라그먼트(Fragment) 문법을 의미합니다. 리액트 컴포넌트는 화면에 표시할 UI가 최상위 엘리먼트(HTML 요소)를 1개만 갖고 있어야 합니다. 이런 제약사항 때문에 여러 개의 엘리먼트를 최상위 엘리먼트에 배치하고 싶을 때 프라그먼트를 사용합니다. 프라그먼트는 실제로 화면에 그려지는 엘리먼트는 아니고 논리적으로만 최상위 태그가 있는 것처럼 보이게 만드는 효과를 갖습니다.

레이아웃 컴포넌트 기본

이렇게 생성한 레이아웃 파일은 _app.jsx 파일에서 다음과 같이 사용합니다.

pages/_app.jsx
import Layout from '../layouts/Layout'

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

레이아웃 컴포넌트를 구성하게 되면 페이지를 이동해도 <Component> 영역만 변하게 되기 때문에 레이아웃 컴포넌트 내부의 상태는 보존됩니다.

레이아웃 컴포넌트 응용

만약 구현하려는 웹 애플리케이션에서 UI 레이아웃이 다 달라 여러 개의 레이아웃 컴포넌트를 사용해야 한다면 어떻게 해야 할까요? 그럴땐 아래와 같이 Per-Page 레이아웃 방식을 이용합니다.

pages/login.jsx
import SimpleLayout from '../layouts/SimpleLayout'

export default function LoginPage() {
return <div>로그인</div>
}

LoginPage.getLayout = function getLayout(page) {
return (
<SimpleLayout>{page}</SimpleLayout>
)
}
pages/main.js
import AdminLayout from '../layouts/AdminLayout'

export default function MainPage() {
return <div>메인</div>
}

MainPage.getLayout = function getLayout(page) {
return (
<AdminLayout>{page}</AdminLayout>
)
}
pages/_app.js
export default function MyApp({ Component, pageProps }) {
// Use the layout defined at the page level, if available
const getLayout = Component.getLayout ?? ((page) => page)

return getLayout(<Component {...pageProps} />)
}

레이아웃 컴포넌트에서 데이터 호출하기

만약 레이아웃 컴포넌트에서 서버 데이터를 호출하고 싶다면 useEffectSWR과 같은 클라이언트의 데이터 호출 방식을 사용해야 합니다. 왜냐하면 레이아웃 컴포넌트는 페이지 컴포넌트가 아니기 때문에 getStaticProps, getServerSideProps과 같은 서버 사이드 데이터 호출 속성이 지원되지 않기 때문입니다.