이 글은 ImageCompressor 컴포넌트의 동적 import와 useWebWorker 옵션을 기준으로 작성했습니다. 성능 개선을 숫자로 과장하지 않고, 어떤 문제를 줄이기 위한 선택인지 기록합니다.
문제: 이미지 압축은 화면 조작과 같은 스레드를 쉽게 막는다
브라우저에서 큰 이미지를 읽고 압축하면 사용자는 화면이 잠깐 멈춘 것처럼 느낄 수 있습니다. 파일 크기가 크고 여러 장을 처리할수록 이 문제가 커집니다. 특히 압축 도구는 사용자가 품질값을 바꾸거나 결과를 확인하며 계속 화면을 조작하는 UI이기 때문에, 처리 중 반응성을 완전히 잃지 않는 것이 중요합니다.
img-compressor는 browser-image-compression을 사용할 때 useWebWorker: true를 전달합니다. 이 옵션은 가능한 환경에서 무거운 처리 일부를 Worker 쪽으로 넘겨 메인 스레드 부담을 줄이기 위한 선택입니다. 단, 모든 브라우저와 모든 파일에서 같은 체감 결과를 보장한다고 쓰지는 않습니다.
라이브러리는 필요한 순간에만 불러온다
초기 화면에서는 파일 입력, 옵션, 안내 문구만 필요합니다. 압축 라이브러리는 사용자가 파일을 선택하고, 리사이즈 후에도 추가 압축이 필요할 때만 필요합니다. 그래서 정적 import 대신 처리 함수 안에서 동적으로 불러오는 구조를 사용합니다.
const { default: imageCompression } = await import('browser-image-compression');
await imageCompression(resizedFile, {
maxSizeMB: 1,
maxWidthOrHeight: Math.max(maxWidth, maxHeight),
useWebWorker: true,
initialQuality: quality,
});
이 구조는 초기 번들을 작게 유지할 가능성을 만들지만, 실제 번들 크기와 로딩 효과는 빌드 결과에서 확인해야 합니다. 중요한 것은 “성능이 좋아진다”는 문장보다, 필요하지 않은 시점에 무거운 코드를 먼저 가져오지 않는 경계입니다.
Worker 옵션만으로 UX가 완성되지는 않는다
Web Worker를 사용해도 사용자는 현재 작업이 진행 중인지 알아야 합니다. 그래서 진행 상태, 현재 파일 번호, 전체 파일 개수, 처리 중 버튼 잠금이 함께 필요합니다. Worker는 내부 처리 부담을 줄이는 도구이고, 진행률 표시는 사용자 불안을 줄이는 UI입니다. 둘 중 하나만으로는 충분하지 않습니다.
또한 Worker 사용 가능 여부와 라이브러리 내부 구현은 브라우저 환경에 따라 달라질 수 있습니다. 실패했을 때 사용자에게 안내하고, 성공한 파일은 결과 목록에 남기는 예외 흐름이 같이 있어야 합니다.
검증 순서
- 큰 사진 한 장을 선택해 처리 중 화면 조작이 가능한지 확인합니다.
- 여러 장을 넣었을 때 현재 파일 번호가 갱신되는지 확인합니다.
- 작은 파일에서는 추가 압축을 건너뛰는 조건이 동작하는지 확인합니다.
- 압축 라이브러리 로드 실패 시 결과 목록에 잘못된 파일이 들어가지 않는지 확인합니다.
- 빌드 결과에서 압축 라이브러리가 초기 청크에 과하게 포함되지 않았는지 확인합니다.
운영 시 남겨야 할 기록
성능 관련 글은 수치가 없으면 쉽게 주장처럼 보입니다. 그래서 이 사이트에서는 체감 개선을 단정하지 않고, 구현 코드와 확인할 항목을 함께 적습니다. 다음 단계로는 동일 자산을 기준으로 Worker 옵션을 켰을 때와 껐을 때의 처리 시간, UI 입력 지연, 브라우저별 차이를 따로 기록하는 것이 좋습니다.