안녕하세요. 올리브영에서 프론트엔드 개발 업무를 담당하는 코난입니다.
올리브영 프론트엔드는 NEXT.JS 프레임워크를 사용하여 웹 페이지를 개발하고 있습니다.
NEXT.JS 프레임워크를, Vercel이나, AWS Amplify같은 관리형 서비스가 아닌, AWS ECS나 EKS를 사용하여 직접 운영할 때 적용하면 좋은 노하우 2가지를 공유하려고 합니다. 🙇♂️
NEXT.JS와 CDN 연동하기
NEXT.JS와 CDN(e.g. AWS Cloudfront)을 연동하는 방법은 NEXT.JS에서 제공하는 옵션인 assetPrefix
를 사용하면 됩니다.
next.config.js
에 아래와 같이 CDN URL
을 추가하면 됩니다.
그리고 NEXT.JS를 next build
명령어를 사용하여 빌드를 했을 때 생성되는 .next
폴더 내부의 static
폴더를 CDN의 Origin(e.g. AWS S3)에 업로드 하면 됩니다.
Origin에 업로드할 때, .next/static
이 아닌, _next/static
으로 파일 경로를 변경해서 올려야 정상적으로 동작합니다.
NEXT.JS 프로젝트와 CDN이 정상적으로 연동이 됐다면 아래와 같은 그림의 모습을 확인하실 수 있습니다.
고객이 페이지 진입 시 요청한 첫번째 요청을 노란색으로 표시한 것처럼 NEXT.JS 서버에 의해서 SSR로 렌더링해서 내려주고
, 그 외의 페이지를 렌더링하기 위해 필요한 JS와 CSS
파일은 CDN을 통해서 제공
하는 모습을 확인하실 수 있습니다.
CDN 연동 전/후 비교
CDN 연동 전
CDN 연동 전에는 NEXT.JS 서버에서 하는 일은 다음과 같습니다.
- HTML요청 시, SSR 렌더링
- JS, CSS와 같은 정적파일 제공
- 이미지 최적화
CND 연동 후
CDN 연동 후에는 NEXT.JS 서버에서 하는 일은 다음과 같습니다.
- HTML요청 시, SSR 렌더링
- 이미지 최적화
기존 NEXT.JS 서버에서 제공하던 정적파일은 CDN을 통해서 제공하기 때문에 NEXT.JS 서버는 SSR과 이미지 최적화에 관련된 부분만 집중
할 수 있습니다.
CDN 연동으로 얻는 장점
1. 더 가까운 엣지 포인트
CDN을 사용함으로써 더 가까운 엣지 포인트
에서 정적파일을 고객에게 더 빠르게 제공할 수 있습니다.
2. 압축 성능 개선
정적파일 압축
(e.g. gzip, brotli)을 NEXT.JS 서버가 아닌, CDN에서 압축을 함으로써 컴퓨팅 파워를 아낄 수 있을 뿐만 아니라, CDN에서 제공하는 압축 알고리즘에 따라 더 적은 용량
으로 고객에게 제공할 수 있습니다.
3. HTTP 프로토콜 버전
CDN에서 제공하는 HTTP 프로토콜 버전
(e.g. HTTP/2, HTTP/3)을 통해서 최신의 HTTP 프로토콜 버전을 사용하여 고객에게 더 빠르게 정적파일을 제공할 수 있습니다.
NEXT.JS와 도커 이미지 경량화하기
NEXT.JS를 컨테이너로 배포할 때 이미지를 경량화하는 방법은 NEXT.JS에서 제공하는 옵션인 output
을 사용하면 됩니다.
next.config.js
에 아래와 같이 output: standalone
옵션을 추가하면 됩니다.
위 옵션을 설정하고 next build
명령어를 사용하여 빌드를 하면, .next 폴더 하위에 standalone
폴더가 생성되고, 이 폴더만을 사용하여 NEXT.JS 서버를 운영할 수 있습니다.
컨테이너를 위한 이미지를 생성할 때에는 standalone
폴더와, public, 환경 변수(e.g. .env.production, .env.local)등 구동에 필요한 파일만을 포함하여 이미지를 생성하면 됩니다.
FROM node:18.17.0-alpine3.18
ENV PORT 80
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Copy build output files
COPY ./public ./public
COPY ./.next/standalone ./
COPY ./.env.production ./
EXPOSE $PORT
# Running the app
ENTRYPOINT [ "node", "server.js" ]
output 옵션 적용 전/후 비교
output: standalone
을 적용하기 전에는 NEXT.JS 서버를 배포하기 위한 컨테이너 이미지가 약 180MB
정도 였지만, 적용 후에는 약 70MB
정도로 줄어든 것을 확인할 수 있습니다.
이미지 경량화로 얻는 이점
컨테이너 기반으로 서버를 배포하기 위해서는 도커 호스트에서 컨테이너 이미지를 다운
(docker pull)받아야 합니다. 이미지 크기가 클수록 다운받는 시간이 걸리기에, 그만큼 배포하는 시간도 지연
됩니다.
컨테이너 이미지의 크기를 작게 유지할 수록 이미지를 다운받는 시간이 짧기 때문에, 배포속도에 있어서 이점을 얻을 수 있습니다.
NOTE
내용을 기반으로 한 발표 영상과 자료가 있어 함께 전달드립니다.
아래 발표는 AWS ECS 설정부분도 같이 있기에 블로그 내용은 4장
과 5장
을 참고하시면 됩니다.