원티드랩 기술 블로그

원티트랩 기술 블로그

Follow publication

CloudFront + CloudFront functions 이용하여, Next.js 번들파일 효율적으로 서빙하기! 🧞

안녕하세요.
원티드랩 프론트엔드팀 김성광 입니다.

배경 🧪

원티드를 WebPageTest에서 체크를 해보았습니다.
아래와 같이 Next.js 서버에서 js, css 서빙 시간이 오래 걸리는 것을 발견하였습니다.

webpagetest 결과

느린 원인은 2가지로 판단됩니다.

  1. 지리적인 Latency 발생 🌏
    WebPageTest: Virginia USA 🇺🇸
    Next.js 서버: 한국 🇰🇷
  2. 서버 부하 🔥
    일반 Request 처리
    번들파일 (js, css) Request 처리

CDN Support with Asset Prefix 🌐

CDN Support with Asset Prefix 를 적용하게 되면, 번들파일 (js, css)을 CDN에서 서빙할 수 있게 되고, CDN을 이용하게 되면, 사용자와 가까운 곳에서 콘텐츠를 전송함으로써 더 빠르고 안정적인 온라인 경험을 제공합니다.

CDN은 사용자와 콘텐츠 간의 지리적 거리를 줄여 로드 시간을 줄입니다.

출처: https://imagekit.io/blog/what-is-content-delivery-network-cdn-guide/

CDN에 파일만 올리면 어느 정도 성능이 올라가지만,
더 영리하고, 효율적으로 이용하기 위해서 셋팅이 필요합니다.

이번 글에서
CloudFront + CloudFront functions을 이용하여, Next.js 번들 파일을 효율적으로 이용하는 방법에 대해 소개합니다.

목표 ✨

(번들 파일을 CDN 서빙시)
아래 Response Header 셋팅이 목표 입니다.

access-control-allow-origin: *                   // CORS
cache-control: public,max-age=31536000,immutable // 캐싱 정책
content-encoding: br // 최신압축 알고리즘 적용
x-cache: hit from cloudfront // cache hit

흐름(flow): Browser ↔ CloudFront ↔ S3

본격적인 작업에 들어가기전에
흐름에 대해서 알아보겠습니다.
아래 그림은 Browser ↔ CloudFront ↔ S3 기본 흐름입니다.

여기서 주목해야 할 포인트는 아래와 같습니다.

  1. CloudFront의 캐싱 만료 시간은 TTL 값을 사용한다.
  2. S3(origin) 응답 해더에 Cache-Control설정이 없으면 CloudFront “기본 TTL” 값으로 캐싱 만료가 세팅됩니다. (Clinet1 호출 시)
flow: wbrowser → CloudFront → S3

S3에 Response Header에Cache-Control 을 붙여보겠습니다.

S3 Response Header 추가 방법

  1. 파일, 디렉토리를 체크
  2. 작업 → 메타데이터 편집
  3. 메타데이터 추가

Client 1 호출 시, CloudFront → S3 순서로 호출되고,
S3에서 “메타데이타" 세팅한 값이 내려옵니다.
CloudFront는 S3 Response HeaderCache-Control 값으로, 캐시 만료 타임을 세팅됩니다.

flow: CloudFront → S3(Cache-Control)

참고:
더 자세한 캐시 만료 관리에 대한 글은 아래 링크를 확인해 주세요.

관심사 분리 ➗

S3에 “메타데이터” 및 CORS 설정을 추가하게 되면, CloudFront, S3 양쪽 모두 추가될 수 있어, 아래와 같이 역할을 나누겠습니다.

S3

파일 저장만 담당. (다른 역할은 없음)

CloudFront

  • CloudFront 캐시만료
  • Response Header 조작 (CORS, Cache-Control)

이제 본격적으로 원하는 Response Header를 만드는 방법에 대해 알아보겠습니다.

access-control-allow-origin: *                   // CORS
cache-control: public,max-age=31536000,immutable // 캐싱 정책
content-encoding: br // 최신압축 알고리즘 적용
x-cache: hit from cloudfront // cache hit

x-cache: hit from cloudfront

캐시 hit가 일어나야 성능이 좋아지게 됩니다.
CloudFront를 사용하는데, hit가 일어나지 않는다면 사용 의미가 크게 없어집니다.

CloudFront TTL 조정

빌드 될 때마다 번들 파일명이 변경되기 때문에, CloudFront에서 캐시를 오래가지고 있을수록 이득입니다.

CloudFront에 기본 제공하는Managed-CachingOptimized 정책을 살펴보겠습니다.

CloudFront Managed-CachingOptimized 설정

위에 말한 “관심사 분리”를 통해 S3에 max-age 설정하지 않습니다.
(S3 max-age 응답이 없을 시 기본 TTL 값 캐시 만료)

기본 TTL을 최대 TTL 값으로 세팅 하겠습니다. (기본TTL == 최대 TTL)

신규 CloudFront 캐싱 정책 생성

신규로 캐시 정책 생성 하고, CloudFront에 적용을 합니다.
신규로 만든 캐시정책은 아래와 같습니다.

CloudFront 캐시 정책 변경

content-encoding: br

Brotli 압축을 CloudFront 정책에서 쉽게 적용이 가능합니다.
Brotli가 지원 안되는 브라우저도 있기 때문에, Gzip도 활성화 합니다.

CloudFront Brotli

access-control-allow-origin: *
cache-control: public,max-age=31536000,immutable

이 헤더는 CloudFront 순수 세팅만으로 header를 내릴 수 있는 방법이 쉽지 않습니다.

CloudFront Functions

2021년 5월경에 도입 되었으며 4가지 사용 사례를 제공합니다.

캐시 키 정규화

URL 리디렉션 또는 다시 쓰기

요청 권한 부여

해더 조작 👈👈👈👈

“해더 조작” 원하는 기능을 제공하고 있습니다!
친절하게 예재코드까지 제공합니다.

CloudFront Functions

예재코드를 참고하여, 우리가 추가하고 싶은 코드를 추가합니다

function handler(event) {
var response = event.response;
var headers = response.headers;

// CORS header
if (!headers['access-control-allow-origin']) {
headers['access-control-allow-origin'] = {value: "*"};
console.log("Access-Control-Allow-Origin was missing, adding it now.");
}
// cache-control
headers['cache-control'] = {value: 'public,max-age=31536000,immutable;'};
return response;
}

CloudFront에서 아래와 같이 연결 합니다.

적용 결과

Respose Header에 셋팅된 것을 확인하였습니다.

실제 성능은 얼마나 좋아졌을까?

Lighthouse 점수 향상 🚀

테스트 환경 (5번씩 측정, 중간값을 표기)

  • URL: https://www.wanted.co.kr/newintro
  • 브라우저 : 크롬 (시크릿탭)
  • lighthouse 설정:
Lighthouse 설정

AS-IS: 47점

TO-BE: 57점 (+10) 👍👍

번들파일 용량 감소 💫

AS-IS

  • js: 631 kb
  • css: 130 kb

TO-BE (기존대비: 12.8% 용량감소 👍👍)

  • js: 547 kb (13% 용량감소 👍👍)
  • css: 116 kb (11% 용량감소 👍👍)

2021–10–13: 서버 모니터링 결과 내용추가

프론트 서버의 Request 처리량 약 77% 감소 하였습니다. (서버 가용성 Up)

원티드 프론트서버 request 처리량

마무리

CDN Support with Asset Prefix을 적용하다가, 입사 후 첫 장애도 냈습니다.
장애를 발판 삶아 CloudFront에 대해 많이 배우고, 성장하게 된 것 같습니다.
현재에 안주하지 않고, 더 높은 목표를 세우고, 실패하고, 배우고, 성장하는 개발자가 되도록 하겠습니다.

참고

원티드에서는 다양한 직군에서 적극적으로 채용중입니다! 서버, 웹, 앱, 디자인 등 제품을 만들어가는 각자의 분야에서 전문적인 분들과 함께 일하기를 기대하고 있습니다. 회사 채용 정보 페이지를 확인해 주세요!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Responses (1)

Write a response