리엑트의 핵심 기능은 UI를 컴포넌트 단위로 관리하는 것이다. 이 핵심 기능이 라우터와 어우러져 우리는 SPA의 사용환경을 사용자에게 제공하게 된다. 그렇다면 만약 라우팅을 위해 제작한 Router 컴포넌트내의 요소를 원하는대로 사용자의 화면상에 배치하고 싶다면 어떻게 해야할까?
위의 두 이미지는 모두 무인양품의 온라인 스토어 이미지 이다. 브라우저창의 가로 넓이와 상관없이 NAV바 이하의 콘텐츠는 모두 1060픽셀내 그리고 브라우저의 한 가운데에 위치한다다
무인양품 사이트를 클론하면서 위와 같은 배치를 목표로하며 변하지 않은 UI인 사이드바는 전체 페이지가 렌더링 될때 단 한번만 렌더링이 되고 불필요하게 메인 콘텐츠 컴포넌트가 렌더링 될 때에는 재 렌더링이 발생하지 않도록 하는것을 목표로 하였다.
따라서 처음엔 다음과 같이 라우터 컴포넌트를 구현했다.
<BrowserRouter>
<Nav />
<div className="mainContainer">
<Aside />
<Routes>
<Route path="/cart" element={<Cart />} />
<Route path="/detail/:id" element={<Detail />} />
<Route path="products/categories" element={<List />} />
<Route path="products/categories/1/types" element={<Mens />} />
<Route path="products/categories/2/types" element={<Womens />} />
<Route path="products/categories/3/types" element={<Labo />} />
<Route path="/" element={<Landing />} />
</Routes>
</div>
</BrowserRouter>
사이드 바에 해당하는 Aside 컴포넌트를 무작성 Routes 컴포넌트의 외부에 위치시켜 각 콘텐츠 페이지에 해당하는 컴포넌트에 포함시키지 않아 url 변경에따라 렌더링되는것을 막고자 하였다. 그리고 레이아웃을 위해 해당 스타일 값을 모든 컴포넌트에 공통으로 적용될 파일인 common.css 내에 mainContainer를 선택자로지정해 스타일을 적용시켰다. 하지만 이런 구조는 다음과 같은 이유로 비적절 하다고 느껴졌다.
따라서 레이아웃을 위한 적절한 방법을 모색하던중 React의 children개념을 적용하기로 하였다.
React 공식문서
props.children
모든 컴포넌트에서 props.children를 사용할 수 있습니다. props.children은 컴포넌트의 여는 태그와 닫는 태그 사이의 내용을 포함합니다.<Welcome>Hello world!</Welcome>
Hello world! 문자열은 Welcome 컴포넌트의 props.children으로 사용할 수 있습니다.
우선 1060픽셀의 모든 콘텐츠요소를 브라우저의 한가운데에 위치시킬 MainContainer 컴포넌트, url에 따라 전환될 페이지를 위치시킬 ContentsWrapper를 구현해 해당 컴포넌트 내에 라우터 컴포넌트의 요소들을 목적에 따라 Aside와 페이지 콘텐츠를 MainContainer의 자식요소로 배치했다.
//Router.js
<BrowserRouter>
<Nav />
<MainContainer>
<Aside />
<ContentsWrapper>
<Routes>
<Route path="/cart" element={<Cart />} />
<Route path="/detail/:id" element={<Detail />} />
<Route path="products/categories" element={<List />} />
<Route path="products/categories/1/types" element={<Mens />} />
<Route path="products/categories/2/types" element={<Womens />} />
<Route path="products/categories/3/types" element={<Labo />} />
<Route path="/" element={<Landing />} />
</Routes>
</ContentsWrapper>
</MainContainer>
</BrowserRouter>
//MainContainer.js
const MainContainer = ({ children }) => {
return <div className="mainContainer">{children}</div>;
};
const ContentsWrapper = ({ children }) => {
return <div className="contentsWrapper">{children}</div>;
};
이러한 방법을 통해 실제 사이트와 같은 페이지 레이아웃이 가능해 졌다.
props.children 개념을 처음 접했을때에는 단순히 컴포넌트를 여닫는 태그로 사용해 태그내에 작성한 jsx 요소를 children 이라는 이름의 객체로 받을수 있구나, 그런데 이런건 어떤 용도로 사용하는걸까 하는 생각이 들었지만 이번에 사용한 용도와 같이 내부에 존재하는 컴포넌트의 레이아웃에도 사용할 수 있구나 라는 점을 깨닫는 계기가 되었다.