Next.js로 정적 웹 사이트 개발하고 빌드하기

시소·2023년 10월 11일
4

Next.js Static Exports

목록 보기
1/3
post-thumbnail

💪 목표
Next.js의 Static Exports를 활용해 정적으로 웹 페이지를 개발&빌드 하는 방법에 대해 알아 본다.

👀 참고 사항
본 포스트에서는 Next.js의 Pages Router 방식과 관련된 내용을 담고 있다. (App Router 방식 X)

개요

React의 프레임워크 Next.js는 웹 애플리케이션 개발 시 필요한 다양한 기능과 최적화를 제공하여, 개발자가 애플리케이션 구축에 집중할 수 있도록 많은 부분에 있어서 도움을 준다.

Next.js의 사전 렌더링(Pre-rendering) 기능

해당 프레임워크가 제공하는 주요 기능 중 하나로는 모든 페이지를 사전 렌더링(Pre-rendering)한다는 특징이 있는데, 이로 인해 성능 및 SEO 향상이라는 이점을 얻을 수 있게 된다.
웹 페이지를 그리기 위해 JavaScript로 모든 작업을 수행하는 대신, 각 페이지에 대해 미리 HTML 파일을 생성해 놓은 뒤 페이지가 브라우저에서 로드될 때 최소한의 JS 코드만 실행시킨다는 방식이다.

이 사전 렌더링 방식은 HTML이 생성되는 시점에 따라 2가지 형태로 분류된다.

  1. 정적 생성 (Static Generation): 빌드 타임(build-time)에 HTML이 생성되며, 각 요청에서 재사용된다.
  2. 서버사이드 렌더링 (Server-side Rendering): 각 요청마다 HTML이 생성된다.

참고로 프로젝트에 한 가지 방식만 사용해야 할 필요는 없다. 각각의 페이지마다 사용할 렌더링 방식을 선택하여 하이브리드 형태로 개발하는 것도 가능하다.

정적 사이트 생성(SSG, Static Site Generation) 방식을 선택한 이유

애플리케이션 구축이 완료되면 그 다음 단계로 배포를 진행해야 한다. Next.js 에서는 다음과 같이 배포를 위한 다양한 옵션을 제공하고 있다. 지원되는 전체 옵션은 이곳에서 확인 가능하다.

이 중에서도 별도의 웹 서버 구성 없이 자체 호스팅형으로 웹 사이트를 배포해야 하는 상황이었기에 Static HTML Export 방식을 채택하게 되었다.
이로 인해 사전 생성된 페이지를 CDN을 통해 제공하여 페이지의 로드 시간을 단축시키는 효과를 얻고자 하였다.

추후 이 포스트의 시리즈로 SSG 방식으로 개발된 웹 사이트를 AWS의 S3 + CloudFront + Route53에 배포하는 내용에 대해서도 다룰 예정이다.

⚠️ 주의: Static HTML Export 에서 지원되지 않는 기능들

공식 문서에 따르면, 아래와 같은 일부 Next.js 기능이 제공되지 않는다. Node.js 서버가 필요한 기능 혹은 빌드 프로세스 도중 계산이 가능한 동적 논리가 필요한 기능이 이에 해당한다. 따라서 해당 기능이 필요한 경우라면 정적 HTML 내보내기가 아닌 다른 방식으로의 개발이 필요하다.

  • Internationalized Routing
  • API Routes
  • Rewrites, Redirects
  • Headers
  • Middleware
  • Incremental Static Regeneration
  • Image Optimization with the default loader
  • Draft Mode
  • getStaticPaths 일부 기능
  • getServerSideProps

정적 웹 사이트 구축

이제 SSG 방식에 대해서 대략적으로 알아 보았으니, 실제 웹 페이지를 구현해야 한다. dummyJSON API를 활용하여 간단한 쇼핑몰 페이지를 구축해 보았다.

프로젝트 전체 코드

전체 코드는 https://github.com/mnngfl/next-js-static-export 위치에서 확인할 수 있다.

Next.js 프로젝트 생성

다음과 같은 구성으로 Next.js 프로젝트를 신규 생성하였다.

> npx create-next-app
✔ What is your project named? … next-js-static-export
✔ Would you like to use TypeScript? … Yes
✔ Would you like to use ESLint? … Yes
✔ Would you like to use Tailwind CSS? … No
✔ Would you like to use `src/` directory? … No
✔ Would you like to use App Router? (recommended) … No
✔ Would you like to customize the default import alias (@/*)? … No

의존성 패키지 설치

필요한 몇 가지의 의존성 패키지를 설치해준다.

npm i swr
npm i --save-dev sass eslint-config-prettier
  • swr: 클라이언트 측에서 외부 데이터를 가져오기 위해 사용
  • sass: 스타일링을 위해 사용
  • eslint-config-prettier: 편집기에서 code formatting 도움을 받기 위해 사용

pages/ 디렉토리

페이지 라우터 기능을 사용해 간단하게 홈 화면, 상품 목록 화면, 상품 상세 화면 으로 3가지 경로가 있는 각각의 페이지를 생성해 보았다.

pages/index.tsx - 홈 화면

pages/products/index.tsx - 상품 목록 화면

pages/products/detail.tsx - 상품 상세 화면

이 포스트에서 React 및 Next.js로 다양한 기능을 구현하는 방법에 대해 다루고자 하는 것은 아니므로, 상세 코드에 대해서는 설명을 생략하겠다.

next.config.js

공식 문서에 따라, 정적 내보내기를 수행하기 위해 설정해야 하는 몇 가지 옵션이 있다.

const nextConfig = {
  // ...
  output: 'export',
  trailingSlash: true,
  images: {
    unoptimized: true
  }
}

module.exports = nextConfig

output: 'export'

터미널에서 next build 명령 수행 시, 프로젝트의 out/ 디렉토리에 애플리케이션의 실행에 필요한 HTML/CSS/JS 파일을 생성한다.

참고로, 과거 사용되었던 next export 명령은 Next.js v13.3.0 에서 deprecated 되었다.

trailingSlash: true

Next.js는 기본 설정으로 후행 슬래시가 있는 URL을 후행 슬래시가 없는 URL로 리디렉션한다. (Ex. /products/ -> /product)
이 프로젝트에서는 정적으로 생성된 각 페이지의 index.html 경로로 접근해야 하기 때문에, 후행 슬래시가 존재해야 한다.

현재 프로젝트에 /, /products, /products/detail 라는 3개의 라우트가 있는데 해당 옵션을 활성화해야 next build 수행 시 Next.js가 아래와 같은 HTML을 만들어진다.

  • /out/index.html
  • /out/products/index.html
  • /out/products/detail/index.html

images.unoptimized: true

default 이미지 로더를 사용 중에 프로젝트를 빌드하면 경고와 함께 빌드가 정상적으로 수행되지 않는다. 이미지 최적화를 위해 로더 설정을 완료하거나 혹은 images.unoptimized: true 설정으로 이미지 최적화를 비활성화 하여 빌드가 제대로 수행될 수 있도록 한다.


정적 웹 사이트 빌드

개발이 완료되었으면 빌드 과정을 수행하여 웹 사이트를 배포할 수 있는 형태로 만들어 주어야 한다.
터미널에서 npm run build 명령을 실행하면 위에서 구성한 내용에 따라 프로젝트의 out/ 디렉토리에 다음과 같은 빌드 결과물이 생성된다.

/out
├── 404
│   └── index.html
├── 404.html
├── _next
│   ├── AfhOQvS5dDqozwuj8YkgR
│   └── static
├── index.html
└── products
    ├── detail
    └── index.html

이렇게 생성된 정적 파일을 로컬 서버 상에서 구동시켜 보고자 한다면, Serve 라는 NPM 패키지를 활용하면 된다.

# 설치(필요한 경우 수행)
> npm install --global serve

# 로컬 포트 4000에서 out 디렉토리를 사용
> serve -l 4000 out

이후 브라우저에서 localhost:4000 경로로 이동해 보면 빌드했던 정적 웹 사이트가 노출되는 것을 확인할 수 있다.


마치며

지금까지 Next.js 프레임워크를 이용하여 정적 웹 사이트를 개발하고 빌드하는 방법에 대해 정리해보았다. 이 이후로는 빌드된 사이트를 실제 외부 사용자들이 볼 수 있도록 배포하는 과정이 필요하다.
다음 시리즈에서 AWS 환경에 프로젝트를 배포하는 방법 및 그 과정에서 경험했던 몇 가지 어려움과 해결방안에 대해 알아보고자 한다.
더 나아가 CI/CD 파이프라인을 구축하여 빌드 및 배포 과정을 자동화하는 내용까지 시리즈에 담아 볼 예정이다.


출처 및 참고

profile
배우고 익힌 것을 나만의 언어로 정리하는 공간 ..🛝

0개의 댓글