안녕하세요 프론트엔드 개발자 Garden, 오소현입니다:)
저는 요즘 항해 플러스 프론트엔드 3기 코스 과정에 참여하면서 공부하고 있는데요!
오늘은 그 9주차의 회고를 진행해보려고 합니다 !
이번주차는 성능 최적화 챕터가 새로 시작되었습니다.
평소 회사에서도 이미지 최적화 , cdn 등등 회사에서 성능 최적화를 위해 많은 부분을 고려하면서 개발하고 있는데 그 개념을 확실하게 이해하고 있지는 못했어서 매우 좋은 기회로 다가왔습니다 ^0^
이번주 과제에서는 s3, cloudfront에 배포해보며 직접 실습하고 cdn을 사용했을 때의 성능을 직접 비교하여 보고서를 작성하는 과제였습니다:)
주차 초반에는 s3와 cloudfront의 개념을 학습했었습니다. 그리고 제 사이드 프로젝트 백곰의 공식 홈페이지 일부 페이지를 가져와 이 프로젝트를 가지고 최적화 작업을 진행해보았습니다.
이번 과제는 AWS S3와 CloudFront를 활용하여 Next.js 애플리케이션의 정적 파일을 효율적으로 호스팅하고, GitHub Actions를 통해 자동화된 배포 파이프라인을 구축하였습니다.
웹 애플리케이션의 성능 최적화와 배포 자동화에 대한 실질적인 경험을 제공하며, AWS와 GitHub Actions의 활용 능력을 향상시키는 것을 목표로 이번 주차 과제를 진행하였습니다.
자동화된 배포는 다음과 같이 진행됩니다:)
GitHub repository의 코드를 Actions runner로 가져옵니다.
- name: Checkout repository
uses: actions/checkout@v4
Node.js 20 버전을 설정하여 최신 환경에서 빌드를 진행합니다.
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: "20"
actions/cache
를 사용하여 node_modules
를 캐싱합니다.npm ci
명령어로 프로젝트 의존성을 설치합니다. - name: Cache node_modules
id: cache-node-modules
uses: actions/cache@v4
with:
path: "**/node_modules"
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies if cache is missing
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci
npm run lint
명령어로 코드 스타일을 검사합니다. - name: Lint
run: npm run lint
npm run build
명령어로 프로덕션 최적화된 빌드를 생성합니다. - name: Build
run: npm run build
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws s3 sync
명령어로 변경된 파일만 효율적으로 업로드합니다. - name: Deploy to S3
run: aws s3 sync build/ s3://${{ secrets.AWS_BUCKET_NAME }} --delete
aws cloudfront create-invalidation
명령어로 CloudFront 캐시를 무효화합니다. - name: Invalidate CloudFront cache
run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"
측정 지표 | S3 단독 | CDN | 개선율 |
---|---|---|---|
총 완료 시간 | 8.6s | 7.28s | 15.3% ⬇️ |
DOMContentLoaded | 1.96s | 884ms | 54.9% ⬇️ |
로드 | 4.29s | 1.85s | 56.9% ⬇️ |
전송 크기 | 11.0MB | 10.8MB | 1.8% ⬇️ |
리소스 크기 | 11.0MB | 11.0MB | 0% |
✅ 총 완료 시간
CloudFront를 사용하여 총 완료 시간이 15.3% 감소하는 결과가 나왔습니다! 이는 CDN이 콘텐츠를 더 빠르게 전달하여 전체 로딩 시간을 줄였기 때문에 성능이 개선되었습니다 :)
✅ DOMContentLoaded
DOMContentLoaded 시간이 54.9% 감소하여, 초기 페이지 렌더링이 훨씬 빨라졌습니다. 이는 CDN의 캐싱 효과 덕분입니다 :)
✅ 로드
전체 로드 시간이 56.9% 감소했습니다. CloudFront는 콘텐츠를 엣지 서버에 캐싱하여, 사용자에게 더 빠르게 제공할 수 있습니다 :)
✅ 전송 크기
전송 크기가 1.8% 감소했습니다. CloudFront는 Gzip 또는 Brotli 압축을 사용하여 파일 크기를 줄이고, 전송 속도를 향상시킵니다.
✅ 리소스 크기
리소스 크기는 동일하지만, CDN의 효율적인 전송 방식 덕분에 전반적인 성능이 개선되었습니다.
몇 달 전, 급하게 사이드 프로젝트 Vacgom의 공식 홈페이지를 개발하게 되었다가 전혀 성능을 고려하지 않고 급하게 배포해 출시했던 경험이 있었습니다.
이미지 용량 큰 것도 그냥 막 넣고... 하하 🥹 화질 나빠지니까 이미지 몇 배율로 넣고 등등의.. 앞선 경험을 반성하며 이번 주차 과제의 대상이 되는 프로젝트를 해당 홈페이지 일부 코드를 가져와 추가로 성능 개선을 함께 진행해보았습니다.
제가 이번 성능 개선 미션에서 사용한 도구는 CloudFront
, Chrome DevTools > Network
, WebPageTest
입니다.
왜 성능 개선을 해야할지? 그리고 언제 성능 개선을 해야할지 평소에 궁금했습니다.
원래 처음에 배포하고 나서는 딱히 제가 만든 웹사이트에 불편함을 느낄 수 없을 수 있었지만 하지만 회사에서는 개선이 반드시 필요한 서비스를 만나서 내가 스스로 개선해야하기 때문입니다!
이러한 상황을 만났을 때 문제를 스스로 정의하고 잘 해쳐나가기 위해 성능을 어떻게 개선시킬 수 있고 어떠한 방식으로 성능을 개선해나가는지 배울 수 있을 것이라고 생각했고 이 성능 개선 작업을 진행하게 되었습니다.
원본 홈페이지의 성능을 WebPageTest를 통해 측정해보았습니다.
CDN을 통해 배포한 사이트의 성능이 S3로 배포한 사이트의 성능보다 더 빠르게 측정되었지만 아직 개선이 필요한 부분이 있습니다.
webpack과 AWS CloudFront 도구를 통해 요청 크기를 줄여보고자 노력했습니다.
먼저, 압축에 관한 내용인데요! S3는 기본적으로 지정해주지 않아도 Accept-Encoding 헤더를 통해 gzip
압축을 지원합니다.
우리가 cloudFront를 세팅할 때 자동으로 객체를 압축하는 옵션을 추가해주었기 때문에 따로 설정해주지 않아도 압축이 지원되었습니다. cloudFront는 자동으로 br(Bortli)
압축을 지원해주기 때문에 cdn을 사용하여 자동 압축되는 것 말고 추가 작업은 진행하지 않았습니다.
minify 설정은 웹 페이지의 크기를 줄이는 작업으로, 코드를 최적화하여 파일 크기를 줄이고 로딩 속도를 높이는 데 도움을 주고 있습니다. 주로 공백, 개행과 같은 불필요한 소스코드를 줄여 텍스트 컨텐츠의 크기를 줄여 요청의 크기를 줄이는 작업니다.
요청의 크기가 줄어든다면 서비스의 이용자가 더 빨리 콘텐츠를 받아볼 수 있습니다.
Next.js에서는 기본적으로 압축과 minify 설정이 되어있습니다. 하지만 이번 과제에서는 추가적으로 설정을 해주었습니다.
아래는 minify 설정이 되지 않았을 때의 성능입니다.
모든 코드가 띄어쓰기, 개행 등의 불필요한 소스코드로 인해 요청 크기가 증가하였습니다.
따라서 minify 설정을 추가하여 요청 크기를 줄여보았습니다.
위의 사진과 같이 동일한 파일의 불필요한 소스 코드를 줄여주어 텍스트 파일의 크기를 줄일 수 있었습니다.
서비스에서는 Pretendard 폰트를 사용하고 있었는데요! 이 폰트는 Pretendard의 모든 옵션을 제공하고 있는 폰트여서 전체 폰트 파일이 다 로드되어야했고, 또한 ttf 파일로 구현이 되어있었습니다.
폰트 최적화를 위해서 ttf파일에서 woff 파일로 변환하여 폰트 크기를 줄여보았습니다.
기존 서비스의 이미지들은 다음과 같은 문제점이 있었습니다.
따라서 저는 이미지 최적화를 위해 다음과 같은 작업을 진행하였습니다.
기존의 PNG 이미지를 WebP 형식으로 파일을 변환하였습니다. WebP는 이미지 품질을 유지하면서도 파일 크기를 줄일 수 있는 최신 이미지 형식으로 웹 최적화에 많이 사용되고 있습니다!
이미지 파일들을 S3에 저장하였습니다. 이를 통해 파일 자체로 배포하는 일을 방지하였습니다.
이미지에 loading="lazy"
옵션을 추가하여 웹 성능을 개선하고자 했습니다. 사용자가 이미지를 볼 때까지 로딩을 지연시켜 초기 페이지 로딩 속도를 향상시키는 옵션입니다!
<img
src="https://vacgom-for-hanghae.s3.ap-southeast-2.amazonaws.com/img-intro-services-new.webp"
alt="서비스 소개 이미지"
className="w-full h-full object-cover rounded-2xl"
loading="lazy"
/>
위와 같은 작업을 진행한 후 성능을 측정해보았습니다.
전체적으로 개선 전보다 성능이 좋아졌다는 것을 알 수 있습니다. 개선 전과 후를 한번에 표로 비교해보면 다음과 같이 개선되었습니다.
개선 전과 후의 홈페이지 성능을 WebPageTest를 통해 측정한 결과는 다음과 같습니다:
Metric | 개선 전 | 개선 후 | Description |
---|---|---|---|
Time to First Byte | 2.365s | 0.985s | 콘텐츠 다운로드 시작 시간 |
Start Render | 4.600s | 4.100s | 첫 번째 픽셀이 화면에 나타나는 시간 |
First Contentful Paint | 4.550s | 4.010s | 텍스트와 이미지가 처음으로 나타나는 시간 |
Speed Index | 5.527s | 5.780s | 페이지가 사용 가능해 보이는 데 걸리는 시간 |
Largest Contentful Paint | 5.752s | 5.927s | 가장 큰 콘텐츠가 로드되는 데 걸리는 시간 |
Cumulative Layout Shift | 0.034 | 0 | 로딩 중 디자인 이동 정도 |
Total Blocking Time | 0.513s | 0.070s | 메인 스레드가 차단된 시간 |
위의 결과에서 눈에 띄게 향상된 결과를 한번 더 정리해보았습니다.
성능 최적화 작업을 통해 다음과 같은 긍정적인 변화를 확인할 수 있었습니다.
✅ Time to First Byte (TTFB):
✅ Cumulative Layout Shift (CLS):
✅ Total Blocking Time (TBT):
전체적으로 웹 성능 최적화와 이미지 최적화, 그리고 효율적인 리소스 로딩 전략을 통해 이루어졌습니다. 결과적으로 페이지 로딩 속도와 사용자 경험이 크게 향상되었습니다.
개선 전과 후를 Lighthouse를 통해 측정한 결과는 다음과 같고, 눈에 띄게 개선된 결과를 확인할 수 있습니다!
측정 지표 | 개선 전 | 개선 후 S3 | 개선 후 CDN (개선율) | Description |
---|---|---|---|---|
성능 | 86 | 90 | 98 (14% ↑) | 웹 페이지의 전반적인 성능 점수 |
접근성 | 100 | 100 | 100 | 웹 페이지의 접근성 점수 |
권장사항 | 79 | 79 | 100 (26.6% ↑) | 웹 페이지의 권장사항 준수 점수 |
검색엔진 최적화 | 100 | 100 | 92 | 웹 페이지의 SEO 점수 |
이 결과는 CDN을 활용한 최적화가 웹 성능을 크게 향상시킬 수 있음을 라이트 하우스로도 확인했습니다!
기본, 심화 과제 둘다 best를 받을 수 있엇습니다 ㅠㅠ
이번주에도 오프코치님의 스윗한 멘토링과 함께..!
이번주에는 과제가 수월한 편이었어서 뭘 더 해 볼 수 있었을까한 한주였습니다 ㅎㅎ
다음주에는 성능최적화로 다시 해보는걸로!
저는 현재 항해 프로그램을 마쳤지만 10주간 아주 불태웠는데요!
바로 다음 기수인 항해 플러스 프론트엔드 코스 4기를 모집하고 있다고 하여 공유드립니다!
저도 3기 입과할때 슈퍼 얼리버드 기간에 합류해 추천인 할인까지해서 제일 최대 할인된 가격에 합류할 수 있었습니다 ㅎㅎ
또한 추천인 제도로 [추천인] 코드에 “fWHY9o”를 입력하시면 20만 원 추가 할인 혜택이 있으니 결제하실때 꼭 추천인 할인 코드도 함께 입력해주세요!
제 항해 플러스 프론트엔드 후기 글을 보고 궁금한 사항이 있으시다면 댓글이나, 벨로그 프로필 이메일, 링크드인으로 문의주세요 :)