Next.JS는 React의 단점인 느린 FCP(First contentful paint) 보완해주는 렌더링 방식을 제공한다.
const Page = () => {
return (
...
)
}
export default Page
Page.getLayout = (page:ReactNode) => {
return <MainLayout>{page}</MainLayout>;
}
페이지별로 서로다른 레이아웃을 적용하고 싶다면 각 페이지별로 레이아웃 코드를 작성하고 App 컴포넌트에 props로 레이아웃을 적용시키는 코드를 작성해야 된다.
getServerSideProps
, getStaticProps
함수를 페이지 컴포넌트에 작성하여 백엔드 서버로부터 데이터를 불러와 페이지 컴포넌트에게 Props로 데이터를 전달해줘야 한다.
전체 렌더링 과정에서 JS는 총 두 번 실행된다.
첫 번째는 서버에서 JS 코드들을 HTML로 렌더링 할 때 실행되고 두 번째는 하이드레이션을 진행 할 때 실행된다.
하이드레이션은 페이지에 아직 JS 코드들이 없어 JS 코드를 입히는 과정이다.
즉, 상호작용에 필요한 코드들만 JS Bundle 작업이 이루어지고 해당 코드가 입혀지면 되는 것이다. 나머지 UI에 필요한 코드들은 이미 1번 서버에서 HTML로 렌더링 할 때 이용이되었으니 말이다.
그런데, 실제로는 JS Bundle시 UI에 사용된 코드들을 포함한 컴포넌트들이 Bundle된다.
이렇게되면 JS Bundle 용량이 불필요하게 커지게 된다. 용량이 커지면서 당연하게 하이드레이션 과정의 소요시간이 길어지게 되고 TTI에 이르기까지 오래걸리는 것이다.
/search 경로로 시작하는 모든 페이지의 레이아웃이 적용되기 때문에 /search/setting 경로 또한 layout이 적용된다.
/search/setting 경로에 layout을 생성하게 되면 layout이 중첩되어 적용이 된다.
페이지 경로와 상관 없이 공통적으로 Layout을 적용하고 싶다면, 위 사진처럼 폴더명을 소괄호로 묶어 라우트 그룹 설정하여 공통적인 Layout 적용이 가능하다.
React v18 이상에서 사용 가능한 서버에서만 작동되는 컴포넌트이다.
서버 컴포넌트가 필요한 이유는 기존 Page router 단점 중에 불필요한 컴포넌트까지 JS Bundle 되는 문제를 해결하기 위해 등장했다.
클라언트 컴포넌트와 서버 컴포넌트로 분리하여 1번 과정에서는 전체 컴포넌트가 실행이 되고, 2번 과정에서는 하이드레이션을 위해 브라우저에서 클라이언트 컴포넌트만 실행된다.
Bundle 용량이 줄어든다는 장점 때문에 페이지 대부분을 서버 컴포넌트로 구성하는 것이 권장되고 클라이언트 컴포넌트는 꼭 필요한 경우에만 사용하는 것이 좋다.
컴포넌트 구성 기준은 상호작용이 필요한 컴포넌트들은 클라이언트 컴포넌트로 만들고 나머지 컴포넌트들을 전부 서버 컴포넌트로 구성하면 된다.
서버 컴포넌트 주의사항
서버 컴포넌트에는 브라우저에서 실행될 코드가 포함되면 안 된다.
예를들어,React hook이나 브라우저에서 실행되는 기능을 담고 있는 라이브러리 등이 있다.
클라이언트 컴포넌트는 클라이언트에서만 실행되지 않는다.
이름이 클라이언트 컴포넌트이기 때문에 클라이언트에서만 실행되는 것으로 착각할 수 있는데 위에도 작성되어 있듯이 클라이언트 컴포넌트는 사전 렌더링을 위해 서버에서 1번 실행되고 하이드레이션을 위해 브라우저에서 1번 실행된다.
클라이언트 컴포넌트에서 서버 컴포넌트를 import 할 수 있다.
원래 서버 컴포넌트는 JS Bundle에서 제외되기 때문에 브라우저에서 실행되지 않는다.
하지만, Next.JS는 수월한 개발환경을 위해 클라이언트 컴포넌트에서 서버 컴포넌트를 import 하면 서버 컴포넌트를 클라이언트 컴포넌트로 자동으로 변환시켜준다.
어쩔 수 없이 클라이언트 컴포넌트에서 서버 컴포넌트를 import 해야할 상황이라면 import 문을 사용하기 보다 위 사진처럼 props로 children을 받아 구현하는 것이 좋다.
이렇게 구현하면 서버 컴포넌트의 결과물만 클라이언트 컴포넌트에 children이라는 props 로 전달되기 때문에 직접 실행시키지 않아 서버 컴포넌트가 클라이언트 컴포넌트로 자동 변환되지 않는다.