본문 바로가기
project/withMe

CDN으로 NEXT.JS 성능 개선

by qjatjs123123 2025. 2. 27.

안녕하세요!

 

withMe 서비스의 프론트엔드는 NEXT.JS 프레임워크를 사용하여 웹 페이지를 개발하고 있습니다.

 

대규모 트래픽을 처리하거나 성능 개선에 도움이 될 수 있는 주제를 공유하려고 합니다.

많은 관심과 피드백 부탁드립니다. 🙏

 

 


 

 

서론

NEXT.JS의 단점

 

NEXT.JS는 강력한 웹 프레임 워크 중 하나일 만큼 많은 장점들이 있습니다. 크게는 SSR,  이미지, 폰트 최적화, 캐싱 등 다양한 기능을 제공합니다.

 

하지만, 이러한 모든 일을 NEXT 서버가 혼자 처리한다면 어떨까요?

 

서버의 부담이 커지면서 성능 저하나 서버 장애로 이어질 수 있습니다. 특히 많은 사용자가 동시에 접속하는 환경에서는 높은 트래픽을 처리할 때 서버 자원이 과도하게 소모될 수 있습니다.

 

저는 이러한 문제를 해결하기 위해 NEXT.JS 의 작업을 CDN을 통해 분산시켰습니다.

 

 


 

 

CDN이란?

CDN (Content Delivery Network)는 지리적 제약 없이 전 세계 사용자에게 빠르고 안전하게 콘텐츠를 제공할 수 있는 콘텐츠 전송 기술입니다.

 

쉽게 말해, 서울에 있는 사용자가 미국에 호스팅된 넷플릭스를 보려고 한다고 가정해 봅시다. 이 사용자가 서울에서 미국까지 대서양을 가로질러 요청을 보내고 응답을 받아야 한다면, 로딩 시간이 길어질 것입니다. CDN은 이러한 문제를 해결하기 위해 여러 나라에 캐싱 서버를 구축하여, 사용자가 가장 가까운 서버에서 요청과 응답을 빠르게 받을 수 있도록 합니다.

 

동작 과정에 대해서 알아봅시다.

  1. 사용자가 HTML, 이미지, CSS과 같은 컨텐츠를 서버로부터 요청
  2. DNS는 사용자와 가장 가까운 위치에 배치된 CDN 서버에 매핑
  3. CDN 서버에 컨텐츠가 있다면 응답
  4. CDN 서버에 컨텐츠가 없다면 ORIGIN 서버에 직접 요청 후 캐싱 저장, 그리고 응답

 

 

 


 

 

S3와 CloudFront 그리고 Imgix

CloudFront는 HTML, CSS, JS 등 정적 파일을 더 빠르게 배포하도록 지원하는 AWS의 CDN 서비스입니다.

 

Imgix는 이미지 최적화 및, 이미지 프로세싱을 제공하는 CDN 서비스입니다.

 

 

저는 JS, CSS를 CloudFront로,

이미지 최적화 및 이미지 프로세싱은 Imgix로 분산하였고,

NEXT 서버는 오로지 SSR만 담당하도록 하였습니다.

 

 


 

 

 

CDN 연동 전/후 비교

CDN 연동 전 

 

CDN 연동 전에는 NEXT.JS 서버에서 하는 일은 다음과 같습니다.

  1. SSR 렌더링
  2. JS, CSS와 같은 정적파일 제공
  3. 이미지 프로세싱

 

 

CDN 연동 후 

 

CDN 연동 후에는 NEXT.JS 서버에서 하는 일은 다음과 같습니다.

  1. SSR 렌더링

 

 

이미지를 통해 봐도, NEXT 서버가 맡고 있던 일이 많이 줄어든 것 같죠?

 

 

 


 

 

 

구현

S3, CloudFront 연동

 

연동하는 것은 관련 링크를 남깁니다.

https://www.youtube.com/watch?v=eCae0OQSiCA

 

 

 

연동을 완료하셨다면, next.config.js에 아래와 같이 CDN URL을 추가하면 됩니다.

/** @type {import('next').NextConfig} */
const config = {
  reactStrictMode: false,
  assetPrefix: 'YOUR_CDN_DOMAIN'
};

module.exports = config;

 

 

 

그리고 NEXT.JS를 next build 명령어를 사용하여 빌드를 했을 때 생성되는 .next 폴더 내부의 static폴더를 S3 업로드 하면 됩니다.

 

.next/static 폴더

Origin에 업로드할 때, .next/static이 아닌, _next/static으로 파일 경로를 변경해서 올려야 정상적으로 동작합니다.

 

 

 

 

Imgix 연동

 

마찬가지로 Imgix도 연동을 해줍니다.

 

https://docs.imgix.com/en-US/getting-started/setup/quick-start-guide

 

Quick Start Guide | Setup | Getting Started

Start serving assets with Imgix in minutes.

docs.imgix.com

 

 

연동을 완료하셨다면, next.config.js 에 아래와 같이 설정을 해야 합니다.

 

/** @type {import('next').NextConfig} */
const config = {
  images: {
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    deviceSizes: [640, 750, 828, 1080, 1200, 1300, 1400, 1500, 1600, 1700, 1920, 2048, 3840],
    loader: 'custom', 
    loaderFile: './customImgLoader.js',
  },
};

module.exports = config;

 

 

즉 Image 컴포넌트를 사용할 때 해당 설정을 참고하게 됩니다.

먼저 imageSizes, deviceSize를 지정합니다.

 

Next/Image 컴포넌트를 사용할 때, 최적화된 이미지 크기를 선택하는 것이 중요합니다. 예를 들어, 렌더링에 필요한 이미지 크기가 500 x 500px인데, 1920 x 1920px 크기의 이미지를 불러오면 불필요하게 많은 데이터가 다운로드되어 네트워크 속도나 로딩 시간에 부담을 줄 수 있습니다. 이를 해결하기 위해 deviceSizesimageSizes 설정을 잘 활용해야 합니다.

 

  • deviceSizes는 화면 크기에 맞춰 선택할 디바이스별 이미지 크기 중단점을 설정합니다. 
  • imageSizes는 sizes 속성이 사용된 이미지에 대해, deviceSizes보다 작은 이미지를 선택할 때 사용됩니다.

 

즉 이렇게 지정해 높으면 srcSet 속성에 여러 사이즈의 이미지를 지정하게 됩니다.

 

Next/Image 컴포넌트에서 sizes에 지정한 사이즈별로 가장 적합한 이미지를 srcSet에서 선택하여 로딩하게 됩니다.

예를 들면 현재 뷰포트가 2000이고 sizes = "50vw"라고 했을 때 srcSet은 deviceSizes 목록에 따라 가장 적합한 1200vw가 선택됩니다.

 

 

 

로더

로더는 Next/Image 컴포넌트가 이미지를 어떻게 불러올지를 정의하는 설정입니다.

저는 Next에서 이미지 처리를 하는 것이 아닌 Imgix를 사용하여 이미지를 처리했기에 설정을 해주어야 합니다.

 

const customImgLoader = ({ src, width, quality }) => {
  return `${imgix_domain}${src}?w=${width}&q=${quality || 75}&fm=webp`;
};

export default customImgLoader;

 

다음과 같이 설정합니다.

 


 

 

결과

(CDN 연동 전 JS,CSS 파일)

 

 

(CDN 연동 후 JS,CSS 파일)

해당 CDN 서버로 요청, 응답을 잘 받고 있습니다. 그리고 캐시 HIT가 된 것을 볼 수 있네요
확실히 응답속도가 빠른 것을 볼 수 있습니다.

 

 

 

 

(CDN 연동 전 이미지)

 

 

(CDN 연동 전 이미지)

확실히 이미지도 캐시 처리가 되서 빨리진 것을 확인 하실 수 있습니다.

 

 


 

 

마무리

이렇게 CDN을 사용하면 Next.js 서버의 부하를 줄이고, 정적 파일의 응답 속도와 성능을 개선할 수 있습니다.

더불어, 로드 밸런싱 같은 기술을 활용하면 트래픽이 많은 환경에서도 더욱 효율적으로 대응할 수 있을 것입니다.

 

 

피드백 환영입니다.

감사합니다.