서버에 업로드하기 전에 해상도나 저장 크기를 줄여
jpeg
,png
,webp
,bmp
이미지를 압축할 수 있는 라이브러리입니다.
프로젝트에서 게시글 작성 시 이미지를 업로드하는 기능을 개발했습니다.
초기에 구현한 방식은 이미지를 압축 없이 원본 그대로 업로드하는 방식이었습니다.
하지만 테스트 과정에서 다음과 같은 문제를 발견했습니다.
이를 해결하기 위해 클라이언트 측에서 먼저 이미지를 압축한 후 업로드하는 방식으로 개선했습니다.
사용 방법
압축을 원하는 파일과 옵션을 지정한 뒤,
imageCompression
비동기 함수를 사용해 압축 시켜주면 됩니다!
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files ? e.target.files[0] : null;
if (file) {
// 선택된 파일을 상태로 저장
setSelctedImageFIle(file);
const reader = new FileReader();
reader.onload = () => {
setPreviewImage(reader.result as string);
};
reader.readAsDataURL(file);
// 파일 입력 필드 초기화
e.target.value = '';
}
};
문제점
const handleImageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const maxFileSizeMB = 5;
if (file.size > maxFileSizeMB * 1024 * 1024) {
alert(`파일 크기가 ${maxFileSizeMB}MB를 초과했습니다.`);
return;
}
// 이미지 옵션
const options = {
maxSizeMB: 0.2,
maxWidthOrHeight: 1226,
useWebWorker: true,
};
try {
// 이미지 압축
const compressedBlob = await imageCompression(file, options);
const compressedFile = new File([compressedBlob], file.name, {
type: file.type,
lastModified: Date.now(),
});
setSelectedImageFile(compressedFile);
// 미리보기 이미지 생성
const reader = new FileReader();
reader.onload = () => setPreviewImage(reader.result as string);
reader.readAsDataURL(compressedFile);
// 파일 입력 필드 초기화
e.target.value = '';
} catch (error) {
alert('이미지를 처리하는 도중 오류가 발생했습니다. 다시 시도해 주세요.');
}
};
개선된 점
1224px 결정 이유
업로드된 이미지가 다양한 페이지에서 사용되는데,
가장 작은 사이즈에 맞추면 다른 뷰에서 이미지가 깨질 위험이 있었습니다.
그래서 여러 화면에서 가장 무난하고 균형 잡힌 크기로 보이도록 1224px로 지정했습니다.
같은 이미지를 개선 전·후 적용해본 결과, 파일 크기는 4.3MB → 145KB, 로딩 시간은 1.01초 → 820ms로 개선되었습니다. 이로 인해 페이지 로딩 속도 향상, 사용자 경험 개선을 향상 시켰습니다.
라이브러리
https://www.npmjs.com/package/browser-image-compression
더 자세한 코드는 깃허브 참고
https://github.com/Co-Drive/Driver-Client/pull/369