메뉴바 구현을 완료하고 보니 어떤 페이지에는 메뉴바가 있고 어떤 페이지에는 메뉴바가 없어서 메뉴바가 있는 페이지에 메뉴바 컴포넌트를 각각 넣는 것은 비효율적이라고 판단했다.
따라서 홈, 설정, 마이페이지에는 메뉴바가 있는 기본 레이아웃을, 회원가입, 로그인 화면에는 메뉴바가 없는 레이아웃을 사용하고자 한다. 페이지 별로 다른 레이아웃을 구성할 때는 Per-Page Layouts을 사용하면 된다.


우리 페이지에서는 유저인증(로그인, 회원가입, 비밀번호 변경) 페이지는 메뉴바가 없는 기본 레이아웃을 가진다. 따라서 기본 레이아웃을 page component만 받는 컴포넌트로 작성했다.
// src/components/layout/Layout.tsx
import { ReactNode } from 'react';
// 메뉴바 없는 버전 레이아웃
export function Layout(props: { children: ReactNode }) {
return (
<>
{props.children}
</>
);
}
또한 나머지 페이지에는 모두 메뉴바가 있으므로 메뉴바 레이아웃을 개별 레이아웃으로 만들었다.
// src/components/layout/MenuBarLayout.tsx
import { MenuBar } from '@/components';
import { ReactNode } from 'react';
import styled from 'styled-components';
// 메뉴바 있는 버전 레이아웃
export function MenuBarLayout(props: { children: ReactNode }) {
return (
<Wrapper>
<MenuBar />
{props.children}
</Wrapper>
);
}
const Wrapper = styled.div`
display: flex;
justify-content: space-between;
`;
// src/pages/_app.tsx
import { Provider } from 'react-redux';
import { AppProps } from 'next/app';
import store from '../redux/store';
import type { ReactElement, ReactNode } from 'react';
import type { NextPage } from 'next';
// 각 페이지에서 불러와서 쓸 '레이아웃이 적용된 페이지'의 type
type NextPageWithLayout = NextPage & {
getLayout?: (page: ReactElement) => ReactNode;
};
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};
export default function App({ Component, pageProps }: AppPropsWithLayout) {
// 컴포넌트의 getLayout이 존재하면 해당 레이아웃 렌더링, 존재하지 않으면 기존 페이지 렌더링
const getLayout = Component.getLayout ?? ((page) => page);
return (
<Provider store={store}>
<GlobalStyles />
{getLayout(<Component {...pageProps} />)}
</Provider>
);
}
// src/pages/main.tsx
import { RecommendFollow, InfiniteScroll, MenuBarLayout } from '@/components';
import styled from 'styled-components';
import type { ReactElement } from 'react';
export default function Main() {
// 생략..
return (
<HomeDiv>
<PostSection>
<h2 className='a11y-hidden'>게시물</h2>
<InfiniteScroll />
</PostSection>
<RecommendFollow />
</HomeDiv>
);
}
// getLayout으로 해당 페이지에 필요한 레이아웃 적용 - 메뉴바 있는 레이아웃
Main.getLayout = function getLayout(page: ReactElement) {
return <MenuBarLayout>{page}</MenuBarLayout>;
};
const HomeDiv = styled.div`
display: flex;
margin: 0 auto;
`;
const PostSection = styled.section`
display: flex;
flex-flow: column nowrap;
margin-right: 130px;
@media (max-width: 1300px) {
margin-right: 0;
}
`;
메뉴바가 없는 로그인, 회원가입 페이지의 경우 main.tsx의 Main.getLayout 이부분 코드에서 MenuBarLayout 대신에 Layout 컴포넌트를 불러와서 사용해주면 된다.
우리 프로젝트에서는 메뉴바가 없는 레이아웃의 경우에는 따로 설정해줄 것이 없기 때문에 Layout 컴포넌트를 삭제하고 메뉴바가 있는 페이지에만 getLayout으로 메뉴바 레이아웃을 적용해주도록 하였다.