Next.js 사용하기

백우진·2023년 2월 28일
1

Next.js?

React 에서 서버 사이드 랜더링을 간편하게 해주는 프레임 워크


기본 작동 방식

  1. 사용자가 홈페이지를 접속하고 클라이언트는 서버로 요청(server-side)
  2. 서버는 미리 구성된 HTML, CSS를 클라이언트에게 전달
    (pre-rendering, init Load = Js동작이 없는 HTML 화면을 먼저 보여주는것)
  3. 클라이언트가 스크립트 파일을 수행(Hydration)

왜 써야할까?

Next.js는 초기 페이지를 서버에서 로딩한다
: Pre-rendering을 이용하면 사용자에게 초기 페이지를 빠르게 보여 줄 수 있는 장점이 있다.

SEO 문제 해결

직관적인 페이지 기반 라우팅 시스템(Auto Routing)
: /pages 폴더에서 컴포넌트를 export하면 폴더명이 페이지 route가 된다.

SPA 장점 유지
: 첫 페이지는 SSR 방식, 이후에는 CSR 방식을 이용


설치

npx create-next-app 프로젝트명 --typescript

✨Styled-components Pre-rendering 문제

자바스크립트 코드가 적용이 되지 않은 페이지가 미리 랜더링되기에 CSS in JS로 스타일링을 할 경우 스타일이 적용되지 않게 보이는 문제가 있다.

html 파일에 스타일 요소를 주입시켜 문제를 해결 할 수 있다.
_document.tsx 파일에 다음과 같이 등록하면 된다.


// _document.tsx

import Document, {
 Html,
 Head,
 Main,
 NextScript,
 DocumentContext,
} from "next/document";
import { ServerStyleSheet } from "styled-components";

class MyDocument extends Document {
 static async getInitialProps(ctx: DocumentContext) {
   const sheet = new ServerStyleSheet();
   const originalRenderPage = ctx.renderPage;
   try {
     ctx.renderPage = () =>
       originalRenderPage({
         enhanceApp: (App) => (props) =>
           sheet.collectStyles(<App {...props} />),
       });

     const initialProps = await Document.getInitialProps(ctx);
     return {
       ...initialProps,
       styles: (
         <>
           {initialProps.styles}
           {sheet.getStyleElement()}
         </>
       ),
     };
   } finally {
     sheet.seal();
   }
 }

 render() {
   return (
     <Html>
       <Head></Head>
       <body>
         <Main />
         <NextScript />
       </body>
     </Html>
   );
 }
}

export default MyDocument;


Styled-components Classname 문제

Next.js를 이용하면 처음에 SSR, 페이지 이동할때 CSR 을 이용하는데 이때 serverclient에서 생성하는 class 해시값이 달라 충돌로 문제가 발생한다.

styled-component로 만들어진 컴포넌트는 내부적으로 태그의 className 을 해시하여 만들어지게 된다.

  1. npm i -D babel-plugin-styled-components 설치
  2. 루트 경로에 .babelrc 파일 생성
  3. 바벨 설정
    {
     "presets": [
       "next/babel"
     ],
     "plugins": [
       [
         "styled-components",
    			"babel-plugin-styled-components",
         {
           "ssr": true,
           "displayName": true,
           "preprocess": false
         }
       ]
     ]
    }
    
profile
안녕하세요.

0개의 댓글