React 프로젝트 Next.js 로 마이그레이션 후기

이형준·2023년 11월 21일
0

Migration 한 이유

Code Splitting, Image Optimization, SEO, SSR, SSG, ISR 등 여러가지 이유가 있겠지만

가장 큰 이유는 대표님이 원하셨다.
대표님께서 react 프로젝트를 최신스펙으로 migration 하시기를 원하셨다.
그리고 그전 프로젝트가 여러 개발자의 손을 거치면서 레거시 코드가 상당히 많고 겨우 화면만 돌아가는 수준이여서 나 역시 이 프로젝트를 앞으로 추가 개발하고 유지보수 하기 위해서 원했다.
그래서 대표님과 일주일 정도 이야기를 가진 후 바로 Next.js 로 전환을 시도했다.

그래서 무엇을 했나요 ?

Next.js migration 관련 문서를 보면 기존 프로젝트에 next를 설치 후에 사용하는 경우도 많던데 우리 같은 경우에는 새로운 프로젝트를 생성해서 처음부터 개발하였다.
그렇게 하기 위해서 Next.js 초기세팅을 하고 document에 "hello world" 부터 띄우고 시작했다.

그래서 React 랑 뭐가 다른가요 ?

provide every rendering pattern you need

같은 웹 사이트라도 어떤 페이지에서는 csr을, 어떤 페이지에는 ssr을, 어떤 페이지는 ssg를 상황에 맞게 사용할 수 있도록 해준다는 것이 Next.js의 가장 큰 장점입니다.
그래서 Next.js를 이용하면 우리는 적재적소에 렌더링 패턴을 알맞게 활용하여, 서버비용을 줄이거나, 빌드 타임을 줄이거나, 콘텐츠를 캐싱하는 등 optimized된 환경을 유저에게 제공할 수 있습니다.

  • 페이지는 파일 이름을 기반으로 경로와 연결된다.
  • "a 태그" -> "next/link" 를 사용하면 앱 내부의 두 페이지 간 클라이언트 측 탐색이 가능해집니다, 또한 코드분할을 자동으로 수행하므로 각 페이지는 해당 페이지에 필요한 것만 로드합니다.

Dynamic Routes

  • 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보다 느리지만, 빌드 이후에도 페이지 요청마다 실행된다는 특징이 있습니다.

Assets, Metadata, and CSS

  • "next/image" 를 사용해서 이미지 구성 요소 및 이미지 최적화를 제공한다, 뷰포트가 더 작은 장치에 큰 이미지를 전달하는 것을 방지 가능합니다.
  • Next.js 공식문서를 보면 css,scss 에 관한 설명이 자세히 나와있다, 하지만 우리는 style-components 를 사용했다, 그 이유는 전 프로젝트에 수백개의 tsx 파일에 한개의 scss 가 스타일된 부분이 있었고, 그 부분을 반응형 적용하는데 있어서 꽤나 오랜시간을 들여서 분리한 경험이 있기에 style-components를 적용해서 그러한 일을 방지하기 위함이였다, 하지만 style-components가 최초 렌더링 될 때 스타일이 그려지지 않고 페이지가 그려진 후 스타일이 그려지는 이슈가 있었다, 아래의 코드를 활용해서
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

마이그레이션을 한 후 LightHouse 성능 지표 점수에 큰 상승이 있었습니다.
Performance 점수가 대폭 향상되었고 Accessibility 점수도 향상되었습니다.

profile
프론트엔드 개발자 이형준입니다.

0개의 댓글