-
프론트엔드 고화질 이미지 다루는 방법Front-end 2025. 6. 24. 14:56반응형
고화질 이미지를 업로드 하고, 웹에서 보여줄 수 있어야 하며, 이미지 여러 장을 한 번에 다운로드 받을 수 있어야 하는 미션이 생겼다.
사실 내부 툴이다보니 어드민만 업로드 할 수 있고 최대 5장만 올릴 수 있으며, 마케팅 팀만 다운로드 할 수 있으면 되어서 그리 복잡한 로직이나 고민을 필요로 하진 않는다.
하지만 공부도 중요하고, 다른 고화질을 이미지를 다루는 회사에서는 어떤 식으로 작업하는지 궁금해졌기에 우리도 별거 아니지만 적용을 해보면 좋겠다는 생각을 했다.
다른 회사에서는 무엇을 사용하고 있을까?
그냥 직관적으로 생각했을 때는 "유저가 고화질 이미지를 업로드" -> "업로드한 이미지 압축" -> "클라우드에 업로드" -> "웹에서 보여질 때는 WebP 등 가벼운 이미지 사용" -> "다운로드 시에만 고화질 원본 이미지 사용" 정도로 생각이 들었다.
그리고 리서치를 시작했다.
주로 많은 사용량을 보이는 몇 가지 사이트를 찾아보았다. ( pixabay, freepik, adobe, shutterstock )
"직접 다운로드"와 "이미지를 다른 이름으로 저장" 두 가지를 실시해보았다.
pixabay
직접 다운로드와 이미지를 다른 이름으로 저장 할 때 각각 다른 확장자명이 나왔다.
개발자 모드로 이미지를 열어보면 cdn을 통해서 이미지를 가져오고 있고 jpg를 파일을 사용하고 있다.
직접 다운로드 시에는 jpg 이미지가 나오고, 이미지를 다른 이름으로 저장하면 webp가 그대로 나왔다.
freepik & adobe
freepik, adobe는 같은 스타일을 사용하고 있는 것으로 보인다.
pixabay와 마찬가지로 jpg를 이용해서 img 태그의 src 속성을 사용해 웹에서 렌더링 시켜서 보여주고 있다.
직접 다운로드, 이미지를 다른 이름으로 저장 둘 다 jpg 파일로 추출이 되는데 한 가지 다른 점은 파일 크기이다.
직접 다운로드 시 3MB 정도로 추출되고, 다른 이름으로 저장을 하면 176KB 로 추출이 된다는 차이가 있다.
shutterstock
똑같이 jpg 확장자를 사용해서 화면에 렌더링 시키고 있다.
다만 다른 회사와 다른 점은 picture 태그를 사용해서 source를 사용하고 있고, img 태그도 fetchpriority="high"를 사용하고 있다. 그리고 확대 했을 때 img 태그에 lazy loading을 사용하고 있다.
이미지 포맷별 특성 이해하기
PNG : 무손실 압축
우리가 많이 사용하는 이미지 확장자명은 주로 png, jpeg인데 사실 무슨 의미인지 생각도 해보진 못했고 그냥 그러려니 사용했다가 이번에야 의미를 알게되었어.
PNG의 뜻은 "Portable Network Graphics" 라고 하는데, 무손실 압축을 제공하는 이미지 포맷이다.
프론트엔드 개발자라면 이미지를 많이 받아봤을텐데 투명도르 지원하며 텍스트, 로고처럼 선명한 경계선이 중요한 이미지에 적합하다.
PNG는 화질 보존도도 높고, 투명도를 지원하며, 이름에서 알 수 있듯이 웹 브라우저 호환성도 우수하다. 그런데 문제는 파일 크기가 상대적으로 크다는데 있다.
나도 그것 때문에 PNG 파일을 상대적으로 고화질 사진에는 사용하지 않게 된다.JPEG : 사진 압축의 표준
JPEG의 뜻은 "Joint Photographic Experts Group" 이라고 하는데 손실 압축 방식으로 사진과 같은 복잡한 이미지에 최적화 되어있다.
작은 파일 크기, 사진에 최적화된 압축, 광범위한 호환성을 따졌을 때 개발 외적으로도 많이 사용되는 확장자이다.
그러나 손실 압축으로 인한 화질 저하, PNG와 달리 투명도 미지원, 반복 저장 시 화질 열화 등의 단점을 가진다.
TIP : jpg라는 확장자도 있고, jpeg라는 확장자도 있는데 어떻게 다른걸까?
결국은 같다!
초기의 Windows(MS-DOS) 시스템은 파일 확장자를 세 글자로 제한했기에 jpeg 대신 jpg를 사용했을 뿐 결국 내부 구조나 이미지 품질, 압축 방식 등은 완전히 동일하다.
WebP : 구글의 차세대 포맷
깨끗한 무손실 압축, 웹 브라우저 호환성 등에도 불구하고 상대적으로 파일 크기가 큰 문제 때문에 개발자들이 주로 사용하게 되는 것이 WebP 파일이다.
WebP파일은 Google이 개발한 JPEG, PNG의 장점을 결합한 현대적인 이미지 포맷이라고 한다.
JPEG에 대비해 약 25~35% 작은 파일 크기를 가지고, PNG 대비 약 26% 작은 파일 크기를 가진다.
또한, 무손실/손실 압축 모두를 지원하며 투명도 및 애니메이션 지원까지 해주고 있으니 안 쓸 이유가 없다.
다만, 단점으로는 상대적으로 새로운 포맷이고 그에 따라 일부 구현 브라우저의 경우 지원되지 않는다는 점이 있다.
AVIF : 미래의 이미지 포맷
나는 이미지가 필요할 때 unsplash 라는 사이트를 주로 사용하는데, unsplash 에서 "이미지를 다른 이름으로 저장"을 클릭하면 avif 파일이 나온다.
AVIF는 AV1 Image File Format의 약자이며, AV1 비디오 코덱을 기반으로 한 이미지 포맷이다.
장점은 WebP에 대비해 약 50% 정도 작은 파일 크기를 자랑할 정도로 압축률과 화질이 뛰어나며, HDR 및 넓은 색 영역을 지원한다.
그러나 단점으로는 브라우저 지원이 제한적이며 Encoding/Decoding 속도가 상대적으로 느린 편이라고 한다.
의문점
여기까지 다른 회사의 제품들을 보고, 각각의 확장자에 대해 살펴봤다면 의문점이 든다.
PNG가 더 고화질이고, 무손실인데도 불구하고 왜 기업들은 고화질 이미지 다운로드에 손실 압축인 JPG를 선택하는걸까?
그 이유는 고화질을 최대한 유지하면서도 파일 크기를 줄여야하기 때문이다.
JPG는 파일용량 대비 화질 효율이 가장 좋은 포맷 중 하나이다.
PNG는 항상 동일한 원본 품질을 유지하지만 상대적으로 용량이 크다는 단점이 있다.
그런데 JPG는 손실 압축을 사용한다고 했는데 그럼 안 좋은 것 아닌가? 라는 생각이 든다.
JPG(JPEG)의 경우 손실 압축 방식이지만 이미지 품질을 "거의 유지"하면서도 용량을 크게 줄일 수 있다.
(다만, 압축률(=품질설정)에 따라 다르다)
JPG는 왜 품질을 "거의 유지" 할 수 있을까?
JPG는 사람의 눈으로 구분하기 힘든 정보만 버리는 방식으로 압축한다고 한다.
예를 들어, 인간은 밝기에는 민감하지만 색상 변화에는 둔감하기에 색상 정보를 줄이고, 미세한 디테일, 반복되는 패턴 등을 줄여서 파일 용량을 10~20배 가까이 줄여서 사용할 수 있다.
그렇기에 적절한 품질 설정을 갖고 있다면 사람, 사진, 풍경 등을 사용하기에는 JPG로 사용하는 것이 효율적이다.
손실 압축인 JPG로 다운로드 하는데, 서버는 어떻게 원본 화질을 유지할 수 있을까?
대부분의 회사는 원본 이미지를 고품질(무손실) 포맷으로 저장하고, 사용자의 요구(다운로드 혹은 썸네일 보기 등)에 맞춰서 JPG로 동적으로 변환 또는 캐싱해서 제공한다고 한다. 그래서 다음과 같은 처리 방식을 가진다.
[ 고화질 이미지 업로드 ]
1. 사용자가 고해상도 이미지를 업로드 ( DSLR JPG, PNG, TIFF 등 )
2. 서버에는 원본 이미지(무손실 또는 최대화질의 JPG)를 변형 없이 그대로 저장
3. 필요에 따라 썸네일용, 미리보기용 등을 나눠서 가벼운 JPG, WebP, AVIF 등을 추가로 생성하고 캐싱한다.
[ 고화질 이미지 다운로드 ]
사용자 다운로드 요청 시, 원본 그대로를 다운로드 시키거나, 서버에서 사용자가 원하는 크기의 JPG로 변환 후 제공한다.
만약 S3에 저장한다고 했을 때 사용자가 이미지를 업로드 하게 되면 무손실 원본 이미지, 웹 미리보기용 이미지, 고품질 JPG 다운로드용 이런 식으로 저장을 해놓을 수 있을 것이다.
그리고 다운로드를 하게 되면 일반 사용자는 압축 된 고화질 JPG를 다운로드 받고, 프리미엄 유저는 무손실 원본을 다운 받을 수 있는 등의 방법을 취할 수 있을 것이다.
반응형'Front-end' 카테고리의 다른 글
강력새로고침 하면 불러오는데 일반새로고침은 불러오지 못한다? _ service worker (0) 2025.06.04 Shadcn Dialog에서 Textarea 내부 Enter 키가 동작하지 않는다면? (0) 2025.01.10 React 프론트엔드 개발자의 상태관리 기법과 이유 (3) 2024.05.23