TIL99. Next.JS 13 환경설정

조연정·2022년 12월 9일
1

Next.js

목록 보기
1/1

업데이트된 next.js 13를 사용해보자. (환경설정편)

Next.js란

next.js는 react에서 SSR을 쉽게 구현할 수 있도록 Vercel에서 만든 프레임워크이다.

Next.js를 사용하는 이유

초기 웹사이트는 사용자가 다른 페이지로 이동할 때마다 서버에 요청을 해서 새로운 html을 불러와 매번 새로고침되는 방식이었다. 이를 보완하고자 나온 것이 단일 페이지로 최초 한 번 페이지 전체를 로드하는 SPA의 CSR방식이고, 대표적인 SPA 라이브러리가 react 이다.
하지만, 검색엔진 최적화(seo)문제나 초기 페이지 로딩이 오래 걸린다는 문제점이 존재한다. 검색엔진봇은 js를 해석하기 힘들기 때문에 html에서 크롤링을 하는데, CSR방식은 client에서 페이지를 구성하기 전에 빈 html을 보여주기 때문에 검색엔진이 어떠한 정보도 얻기 힘들다.
*구글은 브라우저 내에 Js엔진이 있기 때문에 CSR방식을 사용해도 SEO문제는 없다고 한다.
이때 next.js를 사용하면 앞에 말한 두가지 문제점을 해결할 수 있다.

Next.js의 작동방식

  1. 사용자가 초기 페이지 접속 요청 시, SSR방식으로 렌더링 될 html을 보낸다.
  2. 브라우저에서 js를 다운받고, react를 실행한다.
  3. 사용자가 페이지 이동할 경우, CSR방식으로 브라우저에서 처리한다.

Next.js 시작하기

  • 초기설정

experimental

// next.config.js
/** @type {import('next').NextConfig} */
module.exports = {
  reactStrictMode: true,
  experimental: {
    appDir:true,
  }
}

: /app 경로는 아직 시험용이기 때문에 next.config.js파일에 experimental 설정이 필요

Next.js & CSS-in-JS

css-in-js형식으로 스타일링을 하면 js코드가 적용되기 전의 페이지가 렌더링되어서 스타일이 적용되는 않은 html 코드가 먼저 렌더링되기 때문에 초기설정이 필요하다.

기존설정

// _document.tsx
export default 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()
    }
  }
}

-> 13버전부터는 app디렉토리에 _app.tsx , _documents.tsx 는 사용하지 않기 때문에 다른 방식을 사용해야 한다.

  1. styled-components API를 사용하여 렌더링 중에
    생성된 모든 CSS 스타일 규칙과 해당 규칙을 반환하는
    함수를 수집하는 전역 레지스트리 구성 요소를 만든다.
// lib/styled-components.tsx
import React from 'react';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';

export function useStyledComponentsRegistry() {
  const [styledComponentsStyleSheet] = React.useState(
    () => new ServerStyleSheet(),
  );

  const styledComponentsFlushEffect = () => {
    const styles = styledComponentsStyleSheet.getStyleElement();
    styledComponentsStyleSheet.instance.clearTag();
    return <>{styles}</>;
  };

  const StyledComponentsRegistry = ({
    children,
  }: {
    children: React.ReactNode;
  }) => (
    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
      {children as React.ReactElement}
    </StyleSheetManager>
  );

  return [StyledComponentsRegistry, styledComponentsFlushEffect] as const;
}
  1. 레지스트리에 수집된 스타일을 루트 레이아웃의 < head >태그에 삽입하는 useServerInsertedHTML hook을 사용하여 클라이언트 컴포넌트를 생성한다.
'use client';

import { useStyledComponentsRegistry } from '../lib/styled-components';
import { useServerInsertedHTML } from 'next/navigation';

export default function RootStyleRegistry({
  children,
}: {
  children: React.ReactNode;
}) {
  const [StyledComponentsRegistry, styledComponentsFlushEffect] =
    useStyledComponentsRegistry();

  useServerInsertedHTML(() => {
    return <>{styledComponentsFlushEffect()}</>;
  });

  return <StyledComponentsRegistry>{children}</StyledComponentsRegistry>;
}

3.root layout의 자식들을 style registry component로 감싼다.

import RootStyleRegistry from './RootStyleRegistry';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <RootStyleRegistry>{children}</RootStyleRegistry>
      </body>
    </html>
  );
}
  1. styled-components를 사용하는 자식 컴포넌트
    use client: 타사 npm 패키지의 구성요소에는 자체적으로 "클라이언트 사용"지침이 있기 때문에 서버 구성요소 내에서는 올바르게 작동하지 않는다.그렇기 때문에 css-in-js나 외부라이브러리 등을 사용 시에는 client components사용해 알려줘야한다.
// app/page.tsx

"use client"; 

import styled from "styled-components";

function Home() {
  return <Container>I'm homepage</Container>;
}
export default Home;
const Container = styled.div`
  background: red;
`;

*실습에서는 Tailwind CSS와 같은 CSS 파일을 출력하는 다른 방식을 사용하고 있다.

profile
Lv.1🌷

0개의 댓글