최근에 진행한 같이가요 서비스는 호스트가 원하는 이벤트를 주최하고 여러 참가자들의 신청 받으며 관리 할 수 있는 서비스이다.
그 중 내 티켓 페이지는 사용자가 이벤트 참여를 위해 구매한 티켓들을 카드 형태로 보여주는 페이지이다. 한 티켓 당 호스트가 주최한 이벤트 배너 이미지를 보여주고 있다.
아래 페이지 접근 시, 티켓 목록 이미지가 늦게 로딩되며 첫 화면이 완전히 보이기까지 지연이 발생한다. 한 유저가 여러 티켓을 구매할 수록 구입한 티켓 정보가 많아지게 되는데, 이때 각 이미지 용량이 크면 이미지 로딩 속도가 느려지는 문제가 발생한다.
이로 인해 사용자 체감 성능 저하로 성능 개선이 필요하다고 생각했다.

성능 측정을 통해 어떤 부분을 최적화해야 하는지 판단할 수 있다.
크롬 브라우저에서 제공하는 웹 개발에 도움되는 다양한 툴이 있다.
→ 이 중에서 Lighthouse를 통해 성능 측정을 한 뒤 개선해보려고 한다.
Lighthouse는 측정한 웹 페이지에서 다섯 가지 지표에 가중치를 적용해 평균값을 계산한 종합 성능 점수이다.

이러한 지표를 웹 바이탈(Web Vitals)이라고 부른다.
![]() | ![]() |
|---|
Lighthouse의 진단 결과를 보면 가장 큰 문제는 “이미지”에 있었다.

브라우저가 가장 먼저 보여주려는 주요 콘텐츠(이미지)가 너무 크고, 너무 늦게, 너무 많은 자원과 함께 로딩되고 있었다는 결과를 볼 수 있다.
이벤트 배너 이미지가 성능에 얼마나 영향을 미치는지 알아보기 위해서는 LCP 수치를 확인하면 알 수 있다. 하나의 이미지를 불러오는데 무려 6110ms 시간이 소요되고 있었다.
하지만 Lighthouse가 절대적인 성능 측정의 지표는 아니기 때문에 좀 더 확실하게 성능 개선을 확인하기 위해 네트워크 탭도 확인해봤다.
네트워크 탭을 확인해보니 이미지 용량이 787kB이고, 해당 이미지를 불러오는데 드는 시간은 662ms로, 다른 요소들에 비해 너무 많은 시간이 소요되는 것을 확인할 수 있었다.
[최적화 전 LCP(6110ms)]

[최적화 전 .jpeg 이미지 용량(787kB)]

그래서 어떤 방법으로 성능을 개선할 수 있을지 고민해보았다.
이미지 최적화와 관련된 내용들을 찾아보던 중 구글에서 만든 WebP라는 이미지 포맷이 최적화에 많이 사용된다는 것을 알았다.
구글에서 만든 웹에 최적화된 이미지 포맷이다.
WebP는 이미지 손상을 최소화하면서 png 또는 jpg와 비교했을 때 평균 40% 감소한 크기로 이미지를 압축할 수 있다. 현재 유저가 이미지를 업로드할때 png, jpg, jpeg 파일만 업로드 하도록 설정했는데 이를 webP로 바꾼다면 이미지를 불러올 때 시간이 훨씬 줄어들 수 있겠다고 생각했다.
유저가 이벤트 배너 이미지를 업로드하는 과정에서 이미지 형식을 webP로 바꿔서 업로드 되도록 하는 convertImageToWebP을 구현했다.
const convertImageToWebP = (file: File): Promise<File> => {
return new Promise((resolve, reject) => {
const img = new Image();
const reader = new FileReader();
reader.onload = () => {
if (typeof reader.result === 'string') {
img.src = reader.result;
}
};
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
if (!ctx) return reject(new Error('Canvas context error'));
ctx.drawImage(img, 0, 0);
canvas.toBlob(blob => {
if (!blob) return reject(new Error('WebP 변환 실패'));
const webpFile = new File([blob], file.name.replace(/\.\w+$/, '.webp'), { type: 'image/webp' });
resolve(webpFile);
}, 'image/webp');
};
img.onerror = reject;
reader.onerror = reject;
reader.readAsDataURL(file);
});
};
유저가 올린 이미지를 FileReader를 이용해 브라우저가 이해할 수 있는 형태인 데이터 URL로 변환한다. 이 URL은 Image 객체에 넣어 브라우저에서 표시할 수 있도록 준비하는 과정이다.
이미지가 로드되면 브라우저의 <canvas>요소를 생성하고, 그 안에 이미지를 그대로 그린다. 이 과정은 이미지를 가공하거나 포맷을 바꾸기 위해 그림판처럼 복사해놓는 역할을 한다,
캔버스에 그려진 이미지를 toBlob() 메서드를 사용해 WebP 포맷이 변환된다.
사진을 직접 첨부한 후 콘솔에서 업로드할 URL을 확인해보면 .webp 포맷이 변환된 것을 확인 할 수 있다!
업로드할 URL: https://gotogetherbucket.s3.~~~.webp
성능 개선 후, LCP와 네트워크 탭을 확인해보니 확실히 성능 개선된 것을 확인할 수 있었다.



다음 포스팅에서는 WebP 최적화가 실제로 어떻게 성능에 영향을 주는지, 기술적인 지표와 개념을 중심으로 더 깊이 있게 살펴볼 예정이다.