본문 바로가기
Front-End

[학습정리] Next.js를 프로젝트에서 사용한 이유

by Cafe Mocha 2022. 12. 3.

학습정리 : Next.js

이 문서는 Next를 처음 공부하면서 작성한 글로 잘못된 정보가 있을 수 있습니다.

 

Next.js란?


Next.js는 React로 만드는 서버사이드 렌더링 프레임 워크이다.

 

 

 

서버사이드 렌더링을 하면 뭐가 좋은데?


  1. 클라이언트 렌더링의 경우 모든 js 파일을 로드하고 사용자는 웹을 보게 된다. 이때까지 사용자는 많은 시간을 대기해야한다.(첫 로딩 시간이 오래 걸린다.)
  2. seo 클라이언트 사이드의 경우 자바스크립트가 로드 되지 않은 경우 아무런 정보를 볼 수 없다. 검색엔진의 봇에 아무 페이지도 걸리지 않아, seo에 불리하다.

이런 두가지 문제점을 해결하는 것이 서버 사이드 렌더링이다.

해결

  1. 서버에서 자바스크립트를 로딩함으로 클라이언트 측에서는 자바스크립트를 로딩하는 시간이 줄어든다.(pre-rendering)
  2. 검색엔진이 자바스크립트를 읽은 것이 아닌, 서버측에서 자바스크립트, html, css를 만들어 컨텐츠를 직접 업로드해 검색엔진에 글이 걸리게 된다. 또한 meta 태그를 자유롭게 추가함으로 seo를 용이하게 할수 있습니다.

💡 초기 로딩, SEO 에서 SSR의 장점이 있다. Next는 CSR,SSR을 함께 사용할 수 있다.

 

next.js가 제공하는 주요 기능


페이지 기반 라우팅 (automatic routing)

pages 폴더에 있는 파일은 해당 파일 이름으로 라우팅됩니다. (pages/page1.tsx -> localhost:3000/page1)

다이나믹 라우팅

대괄호를 활용해서 동적으로 경로를 사용할 수 있다.

  • pages/users/[username].tsx → pages/users/mocha → router.qeury.username = “macha”
  • pages/users/[…data].tsx → pages/users/mocha/1 → router.query.data = [”mocha”,1]

 

 

Pre-rendering

(프론트) 서버에서 HTML 파일을 미리 구성한다.

주소창에 url 입력시 브라우저는 pre-rendering 된 HTML 파일을 받게된다.

  • SSG (default) : 빌드 시 HTML 파일을 구성한다.
  • SSR : 해당 page에서 getServerSideProps()를 사용할 시, 요청을 받을 때마다 서버에서 HTML을 새로 구성해 반환한다.

page 파일에서 getInitialProps() 나 getServerSideProps() 를 사용하지 않으면 기본적으로 SSG를 사용하게 된다. 따라서 url 입력을 통해 접근하는 페이지는 모두 pre-rendering 된 페이지이다.

 

💡 단, useEffect 등으로 데이터를 받아서 csr로 적용하는 부분은 pre-rendering이 적용되지 않는다.

Link next/Link

페이지간 빠르고 매끄러운 전환을 위한 clinet-side navigation을 제공한다.

HTML의 a 태그와 달리 페이지를 리로딩하지 않고도 페이지간 이동이 가능하고, link 컴포넌트가 뷰포트에 보였을 때 관련 페이지를 백그라운드에서 미리 가져다 놓기 때문에 사용자가 링크를 클릭했을 때 매우 빠르게 해당 페이지로 이동할 수 있게 해준다.

server landing

서버렌더링을 합니다. 클라이언트 렌더링과 다르게 서버렌더링을 한 페이지의 페이지 소스보기를 클릭하면 내부에 소스가 있습니다.

<aside> 💡 발표때는 실제 저희 프로젝트 소스코드로 확인해서 보여줬습니다.

</aside>

 

 

 

 

 

 

code splitting

코드 스플리팅은 내가 원하는 페이지에서 원하는 자바스크립트와 라이브러리를 렌더링 하는 것입니다. 모든 번들(chunk.js)이 하나로 묶이지 않고, 각각 나뉘어 좀 더 효율적으로 자바스크립트 로딩 시간을 개선할 수 있습니다.

코드 분할은 webpack, parcel, rollup 등의 모듈 번들러도 지원하고 있는 기능이지만, next.js를 사용하면 별도의 설정없이 자동으로 프로젝트에 적용된다.

💡 dynamic import? • ES2020에서 제공하는 dynamic import은, 해당 모듈을 애플리케이션의 빌드 타임에 불러오는 것이 아니라 런타임때 불러오는 것이다. 즉 처음 받아오는 모듈 (혹은 소스코드)의 용량을 줄임으로써 페이지의 초기 로딩 속도를 줄일 수 있다.(초기 페이지 로딩시 불필요한 모듈 fetch을 줄임으로써 성능 최적화를 할 수 있다.) https://blog.rhostem.com/posts/2020-05-10-nextjs-and-dynamic-import

 

next/Image

next/Image 적용 전, 후 (https://fe-developers.kakaoent.com/2022/220714-next-image/)

next/Image의 3가지 기능

  • lazy loading
    • 이미지 로드하는 시점을 필요할 때까지 지연시키는 기술
    • 예를 들면 스크린 밖에 있는 이미지는 로딩을 지연시키고, 스크린 안에 있는 이미지만을 로드해서 필요한 이미지만 빠르게 로드할 수 있도록 하는 것
    • 크롬 76버전 이상부터는 img 태그에 loading=“lazy” 속성을 추가하면 간단하게 적용 가능
    • Next/Image는 자동으로 적용
  • 이미지 사이즈 최적화
    • 사이즈 최적화를 통해 총 용량을 많이 줄일 수 있고 페이지 로드 속도를 높일 수 있다.
  • placeholder 제공
    • CLS(Cumulative Layout Shift) 이미지가 로드되기 전까지 영역의 높이가 0이었다가, 로드된 후 레이아웃이 변경되는 현상
    • Next/Image는 placeholder를 제공해 CLS현상이 일어나지 않도록 한다.

 

 

 

 

Redirect

redirect는 사용자가 변경된 path로 유입되면 새로운 경로고 안내하는데 아래와 같이 next.config.js 파일을 수정해주면 된다. 여기서 "/contact"라는 경로를 입력하면 "/form"이라는 새로운 경로로 리다이렉트 되는 것을 알 수 있다.

const nextConfig = {
  reactStrictMode: true,
  async redirects() {
    return [
      {
        source: "/contact",
        destination: "/form",
        permanent: false,
      }
    ]
  },
}

module.exports = nextConfig

Rewrite

rewrite는 redirect처럼 리다이렉트 기능을 하지만 여기서 한가지 다른 점은 URL이 바뀌지 않은 상태로 이동한다는 점이다. 그렇기 때문에 API 키나 특정한 경로를 감추고 싶을 때 사용하면 된다.

const API_KEY = process.env.API_KEY;

const nextConfig = {
  reactStrictMode: true,
  async rewrites() {
    return [
      {
// source 주소를 입력하면 destination의 주소로 이동 but, 주소 url은 바뀌지 않음
        source: "/api/movies",
        destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`
      }
    ]
  }
}

module.exports = nextConfig

hot reloading

개발 중 저장되는 코드는 자동으로 새로고침됩니다.

single file components

style jsx를 사용함으로 컴포넌트 내부에 해당 컴포넌트만 스코프를 가지는 css를 만들수 있습니다.

  • <style jsx global>를 사용하면 글로벌로 스타일 정의 가능합니다.
// styled-jsx

function Heading(props) {
  const variable = "red";
  return (
    <div className="title">
      <h1>{props.heading}</h1>
      <style jsx>
        {`
          h1 {
            color: ${variable};
          }
        `}
      </style>
    </div>);
}

_app.tsx

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default MyApp;
  • 이곳에서 렌더링 하는 값은 모든 페이지에 영향을 줍니다.
  • 최초로 실행되는 것은 _app.tsx
  • _app.tsx은 클라이언트에서 띄우길 바라는 전체 컴포넌트 → 공통 레이아웃임으로 최초 실행되며 내부에 컴포넌트들을 실행함
  • 내부에 컴포넌트가 있다면 전부 실행하고 html의 body로 구성
  • Component, pageProps를 받습니다.
    • 여기서 props로 받은 Component는 요청한 페이지입니다. GET / 요청을 보냈다면, Component 에는 /pages/index.js 파일이 props로 내려오게 됩니다.
    • pageProps는 페이지 getInitialProps를 통해 내려 받은 props들을 말합니다.
  • 그 다음 _document.tsx가 실행됨
  • 페이지를 업데이트 하기 전에 원하는 방식으로 페이지를 업데이트 하는 통로
  • _app.tsx에서 console.log 실행시 client, server 둘다 콘솔 찍힙니다. (localhost:3000 웹과 터미널에서 둘다 콘솔 보임)
  • Recoil,globalStyle 모두 _app.tsx에서 설정한다.

_document.tsx


meta 태그를 정의하거나, 전체 페이지에 관려하는 컴포넌트입니다.

// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from "next/document";
export default class CustomDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          // 모든페이지에 아래 메타테크가 head에 들어감 // 루트파일이기에 가능한
          적은 코드만 넣어야함 전역 파일을 엉망으로 만들면 안된다 // 웹 타이틀,
          ga 같은것 넣음
          <meta property="custom" content="123123" />
        </Head>
        <body>
          <Main />
        </body>
        <NextScript />
      </Html>);
  }
}
  • 이곳에서 console은 서버에서만 보이고 클라이언트에서는 안보입니다.
  • render 요소는 반영하지만 페이지 구성 요소만 반영되고 js는 반영 하지 않기 때문에 console은 보이지 않습니다. 즉, componentDidMount 같은 훅도 실행 되지 않습니다. 정말 static한 상황에만 사용합니다.

 

 

 

정리


  1. Next.js로 만들어진 웹 페이지는 url로 접근시 pre-rendering(SSG, SSR) 된 페이지를 반환한다.
  2. pre-rendering 은 프론트엔드 서버(Next.js)에서 일어난다.
  3. Next.js 는 SSG가 기본이다. getServerSideProps() 을 사용하지 않은 페이지는 모두 SSG로, 빌드 타임에 미리 렌더링 된다.(CSR이 필요한 부분은 제외)→ 소스코드에서 확인 가능
  4. SSR을 하려면 getServerSideProps()를 사용해야한다.
  5. Link를 클릭하거나 router.push()를 통해 이동하면 CSR 방식으로 페이지를 전환한다.

Next.js를 프로젝트에 적용한 이유

  • SEO에 신경쓰면서 개발할 수 있다.
  • CSR, SSR 모두 사용할 수 있다.
    • 리액트 기반 프레임워크로 코드 스타일을 맞추기 쉽다.
  • Next의 여러가지 기능을 통한 성능 향상이 크다.

 

레퍼런스


'Front-End' 카테고리의 다른 글

[학습정리] Webpack,Babel  (0) 2023.02.17
[학습정리] Storybook  (0) 2022.12.16