Code Splitting, Image Optimization, SEO, SSR, SSG, ISR 등 여러가지 이유가 있겠지만
가장 큰 이유는 대표님이 원하셨다.
대표님께서 react 프로젝트를 최신스펙으로 migration 하시기를 원하셨다.
그리고 그전 프로젝트가 여러 개발자의 손을 거치면서 레거시 코드가 상당히 많고 겨우 화면만 돌아가는 수준이여서 나 역시 이 프로젝트를 앞으로 추가 개발하고 유지보수 하기 위해서 원했다.
그래서 대표님과 일주일 정도 이야기를 가진 후 바로 Next.js 로 전환을 시도했다.
Next.js migration 관련 문서를 보면 기존 프로젝트에 next를 설치 후에 사용하는 경우도 많던데 우리 같은 경우에는 새로운 프로젝트를 생성해서 처음부터 개발하였다.
그렇게 하기 위해서 Next.js 초기세팅을 하고 document에 "hello world" 부터 띄우고 시작했다.
같은 웹 사이트라도 어떤 페이지에서는 csr을, 어떤 페이지에는 ssr을, 어떤 페이지는 ssg를 상황에 맞게 사용할 수 있도록 해준다는 것이 Next.js의 가장 큰 장점입니다.
그래서 Next.js를 이용하면 우리는 적재적소에 렌더링 패턴을 알맞게 활용하여, 서버비용을 줄이거나, 빌드 타임을 줄이거나, 콘텐츠를 캐싱하는 등 optimized된 환경을 유저에게 제공할 수 있습니다.
getInitialProps
Next는 기본적으로 데이터 요구 사항이 없는 경우 페이지가 정적인지 자동으로 확인하고, getInitialProps나 getServerSideProps를 사용하지 않는다면 페이지를 정적 HTML로 사전에 렌더링하여 자동으로 페이지를 최적화합니다.
그러나 전역적으로 getInitialProps를 사용하게 되면, 이러한 최적화과정이 일어나지 않습니다. 때문에 Next.js 9.3버전 이후엔 이런 것을 방지하고자 SSR과 SSG를 분리해 getStaticProps / getServerSideProps로 나눠졌으며, 전역적인 데이터 패치 기능을 지원하지 않습니다. 따라서 전역적으로 SSR의 데이터 패칭을 해야만 하는 경우라면 getInitialProps를 써야만 전역적인 패치가 가능합니다.
getStaticPaths
동적라우팅 + getStaticProps를 원할 때 사용합니다.
페이지가 동적 라우팅을 쓰고 있고, getStaticProps를 쓰는 경우, getStaticPaths을 통해 빌드 타임 때 정적으로 렌더링할 경로를 설정해야합니다. 여기서 정의하지 않은 하위 경로는 접근해도 화면이 뜨지 않습니다. 동적라우팅 할 때, 라우팅 되는 경우의 수를 하나하나 집어넣어야 합니다.
getStaticProps
data를 빌드시에 미리 땡겨와서 static하게 제공하기 때문에 굉장히 빠른 속도로 페이지가 렌더됩니다. 따라서 매 유저의 요청마다 fetch할 필요가 없는 데이터를 가진 페이지를 렌더링 할때 매우 유리합니다.
getServerSideProps
getServerSideProps는 페이지를 렌더링하기전에 반드시 fetch해야할 데이터가 있을 때 사용합니다. 매 페이지 요청시마다 호출되므로 getStaticProps보다 느리지만, 빌드 이후에도 페이지 요청마다 실행된다는 특징이 있습니다.
import Document, { DocumentContext } from 'next/document';
import { ServerStyleSheet } from 'styled-components';
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
// sheet을 사용해 정의된 모든 스타일을 수집
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
});
// Documents의 initial props
const initialProps = await Document.getInitialProps(ctx);
// props와 styles를 반환
return {
...initialProps,
styles: (
<>
{' '}
{initialProps.styles} {sheet.getStyleElement()}{' '}
</>
),
};
} finally {
sheet.seal();
}
}
}
페이지 접속 시 렌더링 속도가 눈에 띄게 빨라졌고 레이아웃이 순간적으로 움직이는 현상도 없어졌습니다.
마이그레이션을 한 후 LightHouse 성능 지표 점수에 큰 상승이 있었습니다.
Performance 점수가 대폭 향상되었고 Accessibility 점수도 향상되었습니다.