이미지를 저장할 때 자주 사용하는 포맷으로 JPG, PNG, GIF가 있다.
세 포맷은 모두 이미지를 저장하기 위한 형식이지만, 압축 방식과 지원하는 기능, 적합한 사용처가 서로 다르다.
| 포맷 | 압축 방식 | 손실 여부 | 투명 배경 | 애니메이션 | 주 용도 |
|---|---|---|---|---|---|
| JPG | DCT, 양자화 등을 이용한 압축 | 손실 | X | X | 사진 |
| PNG | 필터링 + DEFLATE | 무손실 | O | 일반적으로 X | 스크린샷, 로고, UI |
| GIF | LZW | 무손실 | 제한적 | O | 간단한 애니메이션 |
JPG와 JPEG는 사실상 같은 이미지 포맷이다.
JPG의 가장 큰 특징은 손실 압축(Lossy Compression) 을 사용한다는 것이다.
손실 압축은 원본 데이터의 일부를 제거하면서 파일의 크기를 줄이는 방식이다.
원본 이미지
↓
사람이 알아차리기 어려운 정보 일부 제거
↓
파일 크기 감소
예를 들어 원본 사진이 10MB라고 해도 JPG로 적절히 압축하면 1~2MB 정도로 줄어들 수 있다.
대신 제거된 정보는 다시 복구할 수 없다.
따라서 JPG를 반복해서 수정하고 저장하면 압축이 반복되면서 화질이 점점 떨어질 수도 있다.
사진에는 색상의 변화가 매우 많다.
예를 들어 하늘만 봐도 하나의 파란색으로 이루어진 것이 아니라,
파랑 → 연한 파랑 → 더 연한 파랑 → 흰색
처럼 수많은 미세한 색 변화가 존재한다.
JPG는 이런 자연스러운 색상 변화가 많은 이미지를 효율적으로 압축하는 데 강하다.
그래서 다음과 같은 이미지에는 JPG가 적합하다.
즉,
사진처럼 색상이 복잡한 이미지의 용량을 줄이고 싶다면 JPG가 적합하다.
단, JPG는 투명 배경을 지원하지 않는다.
PNG의 가장 큰 특징은 무손실 압축(Lossless Compression) 을 사용한다는 것이다.
무손실 압축은 원본 데이터를 버리지 않고 파일 크기를 줄이는 방식이다.
원본 이미지
↓
압축
↓
PNG 파일
↓
압축 해제
↓
원본 이미지와 동일
즉, 압축했다가 다시 풀어도 원래 픽셀 데이터를 그대로 복원할 수 있다.
PNG는 정보를 제거하는 대신 반복되는 데이터와 패턴을 효율적으로 표현한다.
개념적으로 다음과 같은 데이터가 있다고 생각해보자.
AAAAAAAA
BBBBBBBB
이 데이터를 그대로 저장하는 대신,
A 8개
B 8개
와 같이 반복되는 패턴을 더 짧게 표현할 수 있다.
실제 PNG는 이보다 복잡한 방식으로 동작하며, 크게
이미지 데이터
↓
필터링
↓
DEFLATE 압축
과정을 사용한다.
DEFLATE는 ZIP 파일에서도 사용되는 압축 방식이다.
PNG는 다음과 같이 경계가 선명한 이미지에 적합하다.
예를 들어 프로그램 화면을 캡처했다고 해보자.
┌─────────────────────┐
│ Login │
│ │
│ [ Username ] │
│ [ Password ] │
│ LOGIN │
└─────────────────────┘
이런 이미지에는 글자나 버튼의 경계가 중요하다.
JPG로 압축하면 경계 주변에 미세한 노이즈가 생길 수 있지만 PNG는 원본 픽셀을 그대로 보존하기 때문에 더 선명하게 표현할 수 있다.
PNG는 알파 채널(Alpha Channel)을 지원한다.
따라서 이미지의 배경을 투명하게 만들 수 있다.
웹사이트의 로고나 아이콘에서 PNG를 많이 사용하는 이유 중 하나다.
즉,
스크린샷, 로고, UI, 투명 배경 등이 필요하다면 PNG가 적합하다.
그렇지는 않다.
PNG가 원본을 보존한다는 점만 보면 JPG보다 좋아 보일 수 있지만, 그만큼 파일 크기가 커질 수 있다.
예를 들어 같은 사진을 저장했을 때 다음과 같은 차이가 발생할 수 있다.
PNG : 10MB
JPG : 2MB
육안으로 봤을 때 두 이미지의 차이가 거의 없다면 웹에서는 JPG를 사용하는 것이 훨씬 효율적일 수 있다.
파일 크기가 작아지면 다음과 같은 장점이 있기 때문이다.
즉 PNG는 JPG의 상위 호환이 아니다.
두 포맷의 목표 자체가 다르다.
PNG
→ 원본 데이터 보존
JPG
→ 약간의 정보를 포기하고 파일 크기를 크게 감소
대부분의 상황에서는 다음 기준으로 판단하면 된다.
사진
특히 다음과 같이 색상이 복잡한 이미지에 적합하다.
스크린샷
로고
아이콘
UI
그래프
다이어그램
투명 배경 이미지
즉 가장 간단하게 외우면,
사진 → JPG
스크린샷 → PNG
로고 → PNG
아이콘 → PNG
투명 배경 → PNG
라고 생각할 수 있다.
GIF의 가장 유명한 특징은 애니메이션을 지원한다는 것이다.
여러 장의 이미지를 하나의 파일 안에 저장한 뒤 순서대로 보여줄 수 있다.
예를 들어,
프레임 1
😐
프레임 2
🙂
프레임 3
😀
을 빠르게 반복하면,
😐 → 🙂 → 😀 → 😐 → ...
처럼 움직이는 이미지가 된다.
인터넷에서 흔히 말하는 움짤이 대표적인 GIF 사용 사례다.
GIF는 LZW(Lempel-Ziv-Welch) 라는 무손실 압축 알고리즘을 사용한다.
LZW는 데이터에서 반복되는 패턴을 찾아 사전에 등록한 뒤, 이후부터는 해당 패턴을 짧은 코드로 표현하는 방식이다.
예를 들어 다음 데이터가 있다고 해보자.
ABCABCABCABC
ABC라는 패턴이 계속 반복된다.
이때 매번
A B C
를 저장하는 대신 ABC라는 패턴에 번호를 부여하고 이후에는 해당 번호를 사용하는 방식으로 데이터를 줄일 수 있다.
개념적으로는,
원본
↓
반복되는 패턴 탐색
↓
패턴을 코드로 변환
↓
압축
과 같이 동작한다.
LZW 자체는 무손실 압축이기 때문에 압축 과정에서 데이터가 사라지는 것은 아니다.
GIF에는 큰 제약이 하나 있다.
한 프레임에서 사용할 수 있는 색상이 최대 256색이다.
현대의 일반적인 사진은 수십만~수백만 가지의 색 조합을 사용할 수 있다.
따라서 사진을 GIF로 변환한다면,
원본 사진
수백만 가지 색
↓
256색으로 감소
↓
LZW 압축
과 같은 과정이 필요하다.
LZW 압축 자체에서는 데이터가 사라지지 않지만, 원본 이미지를 256색으로 줄이는 과정에서 색 정보가 손실될 수 있다.
따라서 사진을 GIF로 저장하면 색상이 부자연스럽게 표현되는 경우가 많다.
GIF는 다음과 같은 이미지에 더 적합하다.
정리하면 다음과 같다.
원본 이미지
↓
이미지를 작은 블록으로 나눔
↓
DCT 등의 변환
↓
덜 중요한 정보 제거
↓
압축
일부 데이터를 실제로 제거한다.
따라서 손실 압축이다.
원본 이미지
↓
픽셀 간 패턴 분석
↓
필터링
↓
DEFLATE 압축
↓
저장
원본 정보를 제거하지 않는다.
따라서 무손실 압축이다.
이미지
↓
최대 256색으로 표현
↓
LZW로 반복 패턴 압축
↓
저장
LZW 자체는 무손실 압축이지만 GIF의 256색 제한 때문에 원본 사진을 GIF로 변환하는 과정에서 품질이 떨어질 수 있다.
일반적인 개발자라면 JPG, PNG, GIF 압축 알고리즘의 세부적인 구현까지 알 필요는 없다.
예를 들어 다음과 같은 내용을 직접 구현하거나 수학적으로 설명할 필요까지는 없는 경우가 많다.
이런 내용은 이미지 처리나 압축 알고리즘을 전문적으로 공부할 때 더 깊게 살펴볼 수 있다.
일반적인 CS 기초 수준에서는 다음 정도를 이해하는 것이 중요하다.
JPG
→ 손실 압축
→ 사진에 적합
→ 작은 용량
PNG
→ 무손실 압축
→ 스크린샷, UI, 로고에 적합
→ 투명도 지원
GIF
→ LZW 무손실 압축
→ 256색 제한
→ 애니메이션 지원
그리고 다음 질문에 답할 수 있으면 충분하다.
왜 사진에는 JPG를 많이 사용하고 스크린샷에는 PNG를 많이 사용할까?
사진은 수많은 색 변화가 있기 때문에 JPG의 손실 압축을 사용하면 육안으로 큰 차이를 느끼지 않으면서 파일 크기를 크게 줄일 수 있다.
반면 스크린샷이나 UI는 글자와 선의 경계가 중요하기 때문에 원본 픽셀을 보존하는 PNG가 더 적합하다.
JPG
= 사진
= 손실 압축
= 작은 용량
= 투명 배경 지원 X
PNG
= 스크린샷 / 로고 / UI
= 무손실 압축
= 원본 픽셀 보존
= 투명 배경 지원 O
GIF
= 움직이는 이미지
= LZW 압축
= 256색 제한
= 애니메이션 지원 O
가장 간단하게 기억한다면,
JPG = 사진 / PNG = 선명함과 투명도 / GIF = 움직임
으로 정리할 수 있다.