이미지 포맷 이해하기

래스터와 벡터 이미지, 손실과 무손실 압축 방법을 알아보고, PNG, JPG, WebP, AVIF 포맷을 언제 사용할지 생각해봅시다

    Table Of Contents

    들어가기

    이미지를 사용하는 상황에 따라, 파일을 작게 만들어서 로딩을 빠르게 할지, 화질을 우선해서 조금 더 기다리게 할지 같은 선택을 신경 써야 할 때가 있어요. 각 이미지 포맷은 압축률, 로딩 시간, 화질을 다루는 방법이 다르기 때문에, 상황에 맞게 이미지를 쓸 때, 포맷별로 어떤 특성이 있는지 알면 도움이 돼요.

    이 글에서는 래스터와 벡터의 차이부터 시작해서, 래스터 포맷(PNG, JPG, WebP, AVIF)이 각각 어떤 방식으로 이미지를 압축하는지 설명해요. 이 글을 읽고 나면 이런 내용을 알 수 있어요.

    래스터와 벡터

    디지털 이미지는 래스터(Raster)와 벡터(Vector)라는 방식으로 표현할 수 있어요.

    래스터 이미지는 아주 작은 색상 점(픽셀, pixel)을 가로·세로로 빽빽하게 나열해서 만든 이미지예요. 각 픽셀은 "이 위치의 색은 빨강 120, 초록 200, 파랑 80"처럼 하나의 색상 값을 갖고 있어요. 이 픽셀이 수백만 개 모여서 하나의 사진이나 그래픽을 만들어요. 디지털 카메라로 찍은 사진, 스크린샷, 게임 텍스처가 모두 래스터 이미지예요.

    래스터 이미지의 원리 (출처: https://guides.lib.umich.edu/c.php?g=282942&p=1885352)

    래스터 이미지의 크기는 픽셀 수에 비례해요. 1920×1080 해상도라면 픽셀이 약 207만 개예요. 각 픽셀을 RGBA(빨강, 초록, 파랑, 투명도) 4Byte로 저장하면 1920 × 1080 × 4Byte ≈ 8.3MB가 돼요. 화면 하나에 이미지가 여러 장이면 수십 MB가 돼요. 그리고 확대하면 픽셀 하나하나가 네모 점으로 드러나면서 깨져요.

    래스터 이미지를 확대한 경우 (출처: https://guides.lib.umich.edu/c.php?g=282942&p=1885352)

    벡터 이미지는 픽셀을 저장하지 않아요. 대신 "좌표 (10, 20)에서 (100, 80)까지 빨간 선을 그려라"처럼, 점·선·곡선·도형을 그리는 수학적 명령을 저장해요.

    벡터 이미지의 원리 (출처: https://guides.lib.umich.edu/c.php?g=282942&p=1885352)

    화면에 표시할 때 해상도에 맞게 매번 다시 계산해서 그리므로, 아무리 확대해도 깨지지 않아요.

    벡터 이미지를 확대한 경우 (출처: https://guides.lib.umich.edu/c.php?g=282942&p=1885352)

    래스터·벡터에서 쓰는 이미지 포맷

    앞에서는 이미지를 래스터·벡터라는 두 가지 방식으로 표현한다고 했어요. 이번에는 그런 이미지를 파일로 저장할 때 쓰는 방식, 즉 이미지 포맷을 나눠 볼게요.

    이미지를 파일로 저장할 때 쓰는 방식을 이미지 포맷이라고 해요. 확장자(PNG, JPG 등)마다 픽셀을 어떻게 압축·저장하는지가 달라요.

    래스터에서는 용량을 줄일지, 품질을 지킬지 같은 목적별로 쓰는 포맷이 나뉘어요. PNG, JPG, WebP, AVIF가 대표적이에요. 벡터에서는 주로 확대해도 깨지지 않게, 화면 크기에 맞게 쓰기 위해서 한 가지 포맷(SVG)을 널리 써요.

    정리하면 아래와 같아요.

    구분포맷핵심 특징
    래스터PNG무손실 압축, 알파 채널 지원
    래스터JPG손실 압축, 사진에 최적화
    래스터WebP손실/무손실 모두 지원, 웹 최적화
    래스터AVIF최신 고효율 손실/무손실
    벡터SVGXML 기반, 해상도 무관, CSS/JS 제어 가능

    SVG

    SVG(Scalable Vector Graphics)는 XML 기반 벡터 포맷이에요. 픽셀 대신 "원 그리기", "선 그리기", "이 경로를 따라 채우기" 같은 그리기 명령이 텍스트로 들어 있어요. 아이콘, 로고, 단순 일러스트처럼 도형으로 그릴 수 있는 이미지에 적합해요.

    반면 단점도 있어요.


    래스터와 벡터의 선택 기준

    이미지를 기하학적 도형으로 표현할 수 있으면(아이콘, 로고, 일러스트) SVG가 적합해요. 그렇지 않은 이미지(사진, 스크린샷, 복잡한 그래픽)는 래스터 포맷을 써야 해요. 래스터 포맷 중 어떤 포맷을 골라야 할지는, 각 포맷이 이미지를 어떻게 압축하는지 이해하면 판단할 수 있어요.

    래스터 이미지의 압축

    래스터 이미지를 압축 없이 그대로 저장하면, 한 장만 해도 수 MB에서 수십 MB가 나와요. 그만큼 용량을 줄일 필요가 있어서, 각 이미지 포맷은 용량을 줄이기 위해 서로 다른 방법을 사용해요. 한쪽은 어떤 정보를 얼마나 버릴지를 정하고, 다른 한쪽은 버리지 않고 어떤 패턴을 얼마나 잘 압축할지를 정해요.

    손실 압축(Lossy Compression)은 정보를 일부 버리는 방법이에요. 사진처럼 색상 변화가 부드러운 이미지는, 사람 눈이 구분하지 못하는 정보를 버리면 큰 이득을 얻어요. 이런 방식을 손실 압축이라고 해요.

    무손실 압축(Lossless Compression)은 정보를 버리지 않고 반복 패턴만 잘 압축하는 방법이에요. 로고, 아이콘, UI처럼 경계가 또렷한 이미지는 정보를 버리면 깨짐이 바로 눈에 띄어요. 그래서 원본을 정확히 복원할 수 있는 무손실 압축이 적합해요.

    포맷마다 세부 알고리즘은 다르지만, 래스터 이미지를 파일로 만드는 큰 흐름은 비슷해요. 3번 단계를 거치면 손실 압축이고, 거치지 않으면 무손실 압축이에요.

    1. 픽셀 데이터를 색상 채널 단위로 분리해요.
    2. 사람 눈에 덜 민감한 정보를 줄이거나, 반복 패턴을 찾기 쉬운 형태로 변환해요.
    3. (손실 압축에서만) 필요하면 정보 일부를 버려서 데이터양을 줄여요.
    4. 남은 데이터를 엔트로피 코딩(Entropy Coding)으로 더 압축해요.
      • 엔트로피 코딩(Entropy Coding)은 "자주 나오는 값은 짧은 비트로, 드문 값은 긴 비트로 적는다"는 방식으로 전체 크기를 줄이는 기법이에요.
      • 예를 들어 0이 100번 연속이면 "0이 100번"처럼 한 덩어리로 적고, 드문 숫자는 그대로 적는 식이에요. ZIP 파일 압축과 원리가 같아요.
    5. 메타데이터와 함께 파일 컨테이너에 저장해요.

    이제 각 래스터 포맷이 위의 다섯 단계 흐름을 어떻게 구현하는지 살펴볼게요.

    PNG

    PNG(Portable Network Graphics)는 대표적인 무손실 포맷이에요. 핵심은 원본 픽셀을 정확히 복원할 수 있다는 점이에요.

    PNG는 **알파 채널(투명도)**도 지원해요. 각 픽셀에 "이 위치가 얼마나 투명하게 보일지"를 0~255 값으로 저장할 수 있어요. 로고나 UI 요소를 어떤 배경 위에든 겹쳐 쓸 때, 배경을 가리지 않고 자연스럽게 붙일 수 있어요. JPG는 알파 채널을 지원하지 않아서, 투명을 표현하려면 PNG나 WebP를 써야 해요.


    PNG에서 이미지를 압축하기 위해서는 두 단계를 거쳐요. 먼저 행 단위 필터링으로 픽셀 데이터를 압축하기 쉬운 형태로 바꾸고, 이어서 DEFLATE 압축으로 파일 크기를 줄여요.

    1단계: 행 단위 필터링(Row Filtering)

    PNG는 이미지를 행(row) 단위로 처리해요. 각 행의 픽셀 값을 그대로 저장하는 대신, 이웃 픽셀을 이용해 예측하고 예측 오차만 저장해요. 이 예측을 할 때 쓸 수 있는 행 단위 필터는 PNG 규격에 정해진 다섯 가지뿐이에요.

    필터예측 방식계산
    None예측 없음원본 값 그대로
    Sub왼쪽 픽셀 기준현재 - 왼쪽
    Up위쪽 픽셀 기준현재 - 위
    Average왼쪽과 위의 평균현재 - floor((왼쪽 + 위) / 2)
    Paeth왼쪽, 위, 왼쪽위 중 가장 가까운 값현재 - PaethPredictor(왼쪽, 위, 왼쪽위)

    예를 들어, 원본 행의 픽셀 값이 [120, 122, 124, 126]이고 Sub 필터를 적용하면 아래처럼 돼요.

    원본은 네 개의 서로 다른 값이었지만, 필터를 적용하면 같은 값(2)이 반복돼요. 반복이 많을수록 다음 단계의 압축 효율이 올라가요.

    필터링이 효과적인 이유는 이웃 픽셀끼리 값이 비슷한 경우가 많기 때문이에요. 단색 배경에서는 차이가 전부 0이 되고, 부드러운 그라데이션에서는 아주 작은 값만 남아요.

    인코더는 행마다 항상 다섯 가지 필터를 모두 시험한 뒤, 다음 단계(DEFLATE)에서 압축 결과가 가장 작은 필터를 선택해요.

    2단계: DEFLATE 압축

    필터링된 데이터를 DEFLATE 알고리즘으로 압축해요. DEFLATE는 두 기법을 순서대로 적용해요.

    1. LZ77: 이미 지나간 데이터(최대 32KB) 안에서 "지금 이 바이트들이 앞에서 한 번 나왔구나"를 찾아요. 겹치는 구간을 "앞에서부터 거리 N, 길이 M" 한 쌍으로 바꿔요. 예를 들어 [2, 2, 2, 2, 2, 2]라면, 첫 번째 2만 그대로 두고, 나머지 다섯 개는 "바로 왼쪽 1칸에서 5개 복사"라는 뜻의 (거리=1, 길이=5) 한 번으로 적어요.
    2. Huffman 코딩: LZ77이 만든 "그대로 둔 값"과 "거리-길이 쌍"을, 나오는 횟수에 따라 비트 길이를 다르게 부여해요. 자주 나오는 조합은 2~3비트, 드문 조합은 10비트처럼 길게 적어서 전체 비트 수를 줄여요.

    단색 영역이 많으면 필터링 결과가 0이 길게 이어져요. LZ77이 "0이 N개" 한 덩어리로 줄이기 때문에 파일이 매우 작아져요. 반대로 사진처럼 픽셀마다 값이 제각각이면 반복이 거의 없어서 LZ77이 줄일 부분이 적고, 파일이 잘 안 줄어요. 같은 사진을 JPG 품질 85로 저장하면 PNG보다 5~10배 작은 경우가 많아요.

    PNG 정리하기

    • 무손실이라 원본 픽셀을 정확히 복원할 수 있어요.
    • 알파 채널(투명도)을 지원해요.
    • 단색·선명한 경계 이미지(로고, 아이콘, UI, 스크린샷)에서 압축 효율이 좋아요.
    • 사진처럼 복잡한 질감은 PNG로 저장하면 같은 해상도라도 수 MB가 나오기 쉽고, JPG 품질 85로 저장한 것보다 5~10배 클 수 있어요.

    JPG

    JPG(JPEG, Joint Photographic Experts Group)는 대표적인 손실 포맷이에요. 핵심은 사람 눈이 덜 민감한 정보부터 버리는 것이에요. JPG는 여섯 단계를 거쳐서 이미지를 압축해요.

    1단계: 색 공간 변환 (RGB → YCbCr)

    사람 눈은 밝기 변화에는 민감한데, 색은 조금 덜 정확해도 눈치채기 어려워요. 그래서 밝기를 그대로 두고, 색만 골라서 해상도를 낮추기 위해서 RGB 이미지를 YCbCr 색 공간으로 바꿔요.

    색 공간은 같은 색을 어떤 숫자 조합으로 나타낼지를 정하는 방식이에요.

    2단계: 색차 서브샘플링 (Chroma Subsampling)

    Y(밝기)는 그대로 두고, Cb/Cr(색차)만 해상도를 낮춰서 저장해요.

    JPG는 가로·세로 2×2 픽셀 블록당 색차를 하나만 두는 4:2:0 방식을 써요. 이 단계에서 색차 데이터가 원본의 25%로 줄어들어요. 자연 사진에서는 눈에 잘 안 띄어서 용량 대비 품질이 좋지만, 텍스트나 얇은 UI 선처럼 색 경계가 날카로운 이미지에서는 색 번짐이 드러날 수 있어요.

    아래 이미지는 RGB 이미지를 YCbCr 색공간으로 변환했을 때, Y, Cb, Cr 채널의 데이터가 어떻게 보이는지를 나타낸 예시예요.

    RGB에서 YCbCr 색공간으로 변환 예시 (출처: https://www.freecodecamp.org/news/how-jpg-works-a4dbd2316f35)

    3단계: 8×8 블록 분할과 DCT(이산 코사인 변환)

    이미지를 8×8 픽셀 블록으로 나누고, 각 블록에 **DCT(이산 코사인 변환)**를 적용해요. DCT는 "이 블록 안에 어떤 패턴이 얼마나 들어 있는지"를 수치로 바꾸는 단계예요.

    결과는 8×8 계수 행렬이에요.

    예를 들어서, 단색 블록이면 DC만 값이 있고 63개 AC는 전부 0이에요. 체크무늬처럼 픽셀이 갑자기 바뀌는 영역은 우하단 쪽 AC 계수에 값이 많이 몰려요.

    4단계: 양자화(Quantization)

    DCT 계수를 양자화 테이블에 있는 숫자로 나누고 반올림해요. 테이블은 좌상단(저주파)에는 2, 4처럼 작은 수, 우하단(고주파)에는 16, 100처럼 큰 수를 넣어요. 나누는 수가 크면 몫이 0에 가깝게 떨어져서, 고주파 계수는 대부분 0이 돼요. 예를 들어 계수 7을 16으로 나누면 0.43이고, 반올림해서 0이에요.

    이 단계에서 정보가 영구적으로 버려져요. JPG 품질(quality) 설정은 이 테이블의 "나누는 수"를 전반적으로 키우거나 줄이는 값이에요. 품질을 낮추면 나누는 수가 커져서 0이 되는 계수가 많아지고 파일이 작아지지만, 경계선 주변에 블록처럼 뭉개진 번짐(blocking artifact)이 보여요.

    5단계: 지그재그 스캔과 런렝스 부호화

    양자화된 8×8 계수를 한 줄로 펼칠 때 지그재그 순서를 써요. 지그재그 순서는 좌상단(평균 밝기)에서 시작해서 우하단(미세한 디테일)까지 번갈아 가며 읽는 경로예요.

    고주파 계수는 대부분 0이 되었기 때문에, 배열 뒤쪽에 0이 길게 이어져요. 이걸 **런렝스 부호화(RLE)**로 줄여요. **런렝스 부호화(RLE)**는 "0이 12개 나왔고, 그다음에 3이 나온다"를 (12, 3) 한 쌍으로 적는 식이에요.

    6단계: Huffman 코딩

    RLE 출력을 Huffman 코딩으로 최종 압축해요. 자주 나오는 (0의 개수, 다음 값) 조합에 짧은 코드를 부여해요.

    JPG 정리하기

    • 사람 시각 특성을 활용한 손실 압축이라, 자연 사진에서 압축 효율이 매우 좋아요.
    • 품질 80~85면 눈으로 원본과 구분하기 어려운 수준에서 파일을 크게 줄일 수 있어요.
    • 알파 채널을 지원하지 않아요.
    • 텍스트나 선이 선명한 이미지에서는 블록 번짐이 눈에 띄어요.
    • 저장할 때마다 양자화를 다시 거치므로, 여러 번 편집·저장을 반복하면 품질이 계속 떨어져요.

    WebP

    WebP는 Google이 웹 전송 최적화를 목표로 만든 포맷이에요. 손실과 무손실을 모두 지원하고, 알파 채널과 애니메이션도 지원해요. 손실 모드와 무손실 모드의 압축 방식이 완전히 달라요.


    WebP 손실 모드 (VP8 기반)

    VP8 비디오 코덱의 키프레임(I-frame) 압축을 이미지에 적용해요. JPG와 전체 흐름은 비슷하지만, **블록 예측(intra prediction)**이 핵심 차이예요.

    1. 매크로블록 분할: 이미지를 16×16 픽셀 덩어리(매크로블록)로 나눠요. 복잡한 부분은 4×4 픽셀 단위로 더 잘게 나누기도 해요.
    2. 블록 내 예측: 이미 복원된 "위쪽·왼쪽" 블록의 픽셀을 보고, "이번 블록은 아마 이렇게 생겼을 것이다"를 먼저 만든 다음, 실제 픽셀과의 차이만 저장해요. 16×16 블록에는 4가지 예측 모드(수직, 수평, DC 평균, TrueMotion)가 있어요. 4×4 블록에는 10가지 방향 예측 모드가 있어서 더 정밀한 예측이 가능해요. 인코더가 각 블록마다 가장 정확한 예측 모드를 선택해요.
    3. 잔차 변환과 양자화: 예측 값과 실제 값의 차이(잔차, residual)에 DCT 또는 WHT(Walsh-Hadamard Transform)를 적용하고 양자화해요. 예측이 정확할수록 잔차가 작아지고, 같은 품질에서 파일이 더 작아져요.
    4. 부울 산술 코딩(Boolean Arithmetic Coding): JPG의 Huffman 대신 산술 코딩을 사용해요. 산술 코딩은 Huffman보다 이론적 한계에 더 가까운 압축률을 달성할 수 있어요.

    JPG와의 결정적 차이는 2번(블록 예측) 단계예요. JPG는 8×8 블록의 픽셀 값을 그대로 DCT에 넣지만, WebP는 먼저 주변에서 예측한 뒤 차이만 DCT에 넣어요. 예측이 맞을수록 DCT에 들어가는 값 자체가 작아져서, 같은 양자화 강도에서 더 적은 정보 손실로 더 작은 파일을 만들 수 있어요.

    Google의 비교 자료에 따르면, 동일 SSIM(Structural Similarity Index, 구조적 유사도) 기준으로 WebP 손실 모드가 JPG보다 25~34% 작다고 해요.


    WebP 무손실 모드 (VP8L)

    PNG와 Webp의 무손실 압축은 완전히 다른 접근을 써요. Webp는 이렇게 네 가지 변환을 순서대로 적용한 뒤 엔트로피 코딩으로 압축해요.

    1. 예측 변환: PNG의 5가지보다 많은 13가지 예측 모드를 제공해요. 이미지를 타일로 나누고, 타일마다 최적의 예측 모드를 선택해요.
    2. 색 공간 변환: 초록(G) 채널은 그대로 두고, 빨강(R)·파랑(B)은 "초록과의 차이"만 저장해요. 픽셀끼리 R, G, B가 비슷한 값이면 차이 값은 0에 가깝게 몰려서, 다음 압축 단계에서 더 효율적으로 줄어요.
    3. 컬러 캐시: 방금 쓴 색 32개를 기억해 두는 캐시가 있어요. 같은 색이 다시 나오면 "캐시 7번"처럼 인덱스 하나만 적어서, RGBA 네 숫자 대신 한 숫자로 표현해요.
    4. LZ77 + Huffman 코딩: 변환된 데이터에서 반복 패턴을 찾고, Huffman 코딩으로 최종 압축해요.

    Google의 비교 자료에 따르면, WebP 무손실은 PNG보다 평균 26% 작다고 해요.


    하지만 WebP가 항상 더 작은 건 아니에요. 이미지 종류, 인코딩 옵션, 품질 설정에 따라 PNG나 JPG가 더 나은 결과를 내는 경우도 있어요. 그래서 포맷을 정하기 전에 실제 이미지로 여러 포맷을 시험해 보는 게 좋아요.

    AVIF

    AVIF(AV1 Image File Format)는 AV1 비디오 코덱의 정지 프레임 압축을 이미지에 적용한 포맷이에요. WebP(VP8)의 다음 세대 기술이라고 볼 수 있어요.

    WebP와 같은 흐름(예측 → 잔차 변환 → 양자화 → 엔트로피 코딩)을 쓰되, 개선된 점이 3가지 있어요.

    1. 더 큰 블록과 더 많은 예측 모드 WebP는 최대 16×16 픽셀 블록인데, AVIF는 최대 128×128 픽셀까지 한 블록으로 잡을 수 있어요. 예측 모드도 50가지 이상이라 "이 방향으로 그라데이션", "이 방향으로 경계"를 더 정확히 맞춰요. 하늘처럼 넓은 단색은 큰 블록 하나로 처리해서 메타데이터가 줄고, 복잡한 부분만 작은 블록으로 나눠요.
    2. 블록마다 다른 변환 선택 DCT 말고도 경계선에 맞는 변환(ADST 등)을 골라 쓸 수 있어요. 경계선이 있는 블록에서는 에너지가 덜 흩어져서 같은 비트로 더 선명하게 복원돼요.
    3. 복원 후 경계 보정 필터 디코딩이 끝난 뒤, 블록과 블록 사이에 생긴 경계선을 부드럽게 다듬는 필터(CDEF)를 적용해요. 경계 방향은 유지하고 블록 노이즈만 줄여서, 낮은 비트레이트에서도 JPG보다 번짐이 덜 눈에 띄어요.

    이런 개선 덕분에 같은 품질에서 WebP보다 약 20%, JPG보다 약 50% 작은 결과를 낼 수 있어요.


    하지만 압축 품질이 좋은 반면에, 인코딩 및 디코딩에서 트레이드오프가 있어요.

    포맷 선택 기준

    상황에 맞는 포맷을 고르는 가장 실용적인 기준은 이미지의 성격이에요.

    이미지 특성추천 포맷
    사진, 실사 이미지JPG 또는 WebP(손실)
    로고, 아이콘, UI, 스크린샷PNG 또는 WebP(무손실)
    투명 배경 필요PNG 또는 WebP
    애니메이션 필요WebP
    아이콘, 로고(확대 대응)SVG
    대형 히어로 이미지, 최대 압축 필요AVIF 를 고려할 수 있어요

    어느 상황에서든 정답인 포맷은 없어요. 품질 목표와 용량 목표를 동시에 놓고, 상황에 맞는 이미지 포맷을 찾아 나가는 과정이 중요해요.

    웹에서 여러 포맷 제공하기

    웹에서 여러 포맷을 동시에 지원하려면 HTML의 <picture> 요소를 사용해요. 브라우저가 지원하는 포맷 중 가장 먼저 매칭되는 것을 선택해요.

    <picture> <source srcset="hero.avif" type="image/avif" /> <source srcset="hero.webp" type="image/webp" /> <img src="hero.jpg" alt="히어로 이미지" /> </picture>

    이 코드에서 브라우저는 AVIF를 지원하면 hero.avif를, AVIF는 안 되지만 WebP를 지원하면 hero.webp를, 둘 다 안 되면 hero.jpg를 불러와요. <picture><source>는 브라우저가 자동으로 판단하므로, JavaScript 없이도 최적의 포맷을 제공할 수 있어요.

    같은 원본을 여러 포맷으로 변환해 비교하기

    Node.js에서 sharp 라이브러리를 사용하면 같은 원본을 여러 포맷으로 변환하고 크기를 비교할 수 있어요.

    import sharp from "sharp"; const input = "photo.png"; await sharp(input).jpeg({ quality: 85 }).toFile("photo.jpg"); await sharp(input).webp({ quality: 85 }).toFile("photo.webp"); // AVIF는 낮은 quality 수치에서도 품질이 좋은 편이에요 await sharp(input).avif({ quality: 50 }).toFile("photo.avif");

    포맷이 상황과 맞지 않을 때의 문제점

    포맷이 이미지 특성이나 사용 상황과 맞지 않으면 사용자 경험이 바로 나빠져요.

    전송량이 불필요하게 커져요

    사진을 PNG로만 저장하면 같은 이미지를 JPG 품질 85로 저장할 때보다 5~10배 큰 파일이 전송돼요. 히어로 이미지 하나가 5MB라면, 느린 네트워크에서는 로딩에 수 초가 걸려요. 초기 로딩이 느리면 사용자 이탈률이 올라가요.

    시각 품질이 떨어져요

    텍스트가 포함된 UI 캡처나 스크린샷을 JPG로 저장하면, 글자 주변에 블록 번짐이 생겨요. 품질을 높이면 번짐은 줄지만 파일 크기 이점이 사라지고, 품질을 낮추면 가독성이 떨어져요. 이런 이미지는 PNG나 WebP(무손실)가 적합해요.

    투명도 정보가 사라져요

    투명 배경이 필요한 UI 아이콘이나 로고를 JPG로 저장하면 알파 채널이 없어서 배경이 흰색이나 검정으로 채워져요. 다른 배경 위에 합성하면 시각적 오류가 바로 드러나요.

    디코딩 비용이 과도해져요

    파일 크기만 보고 포맷을 고르면 디코딩 비용을 놓칠 수 있어요. AVIF는 파일은 작지만 디코딩에 CPU를 많이 써요. 저사양 모바일 기기에서 대형 AVIF 이미지를 여러 장 디코딩하면 스크롤 끊김이나 프레임 드롭이 생길 수 있어요.

    이런 문제는 대부분 "파일 크기"만 보고 포맷을 정했을 때 발생해요. 이미지가 사용자 화면에 도달하려면 네트워크 전송 → CPU 디코딩 → GPU 렌더링 세 단계를 거치므로, 압축률·로딩 시간·화질을 한 세트로 보고 포맷을 결정해야 해요.

    참고 자료