PicScrub logoPicScrub
형식 목록으로 돌아가기

JPEG

제일 많이 새는 놈

JPEG 파일은 파일 헤더와 이미지 데이터 사이의 APPn 세그먼트에 메타데이터를 담습니다. 어디에 무엇이 들어 있고, PicScrub이 각 부분을 어떻게 다루는지 살펴보세요.

색상 프로필, 원하면 남겨 줌
SOI시작
APP0JFIF
APP1EXIF
APP1XMP
APP2ICC
APP13IPTC
COM주석
SOS …진짜 사진 데이터, 그대로 둠
EOI끝
GPS랑 카메라 정보가 여기 숨어 있음, 삭제
바이트 단위로 똑같음

지워지는 것

  • EXIF GPS 좌표, 카메라 제조사와 모델, 촬영 시각, 노출 설정
  • XMP 편집 이력, 사용한 소프트웨어, 별점
  • IPTC / Photoshop 캡션, 크레딧, 키워드
  • 주석과 내장 썸네일 자르고 편집해도 살아남을 수 있는 원본의 작은 사본

남길 수 있는 것

  • 이미지 데이터 언제나 그대로, 다시 인코딩하지 않아요
  • ICC 색상 프로필 선택 사항, 색이 정확하게 보이도록
  • 회전 정보 선택 사항, 세로 사진이 바로 서도록
  • 저작권 표기 선택 사항, 좌표 없이 크레딧만 남기고 싶은 사진가를 위해

파일 구조 훑어보기

헥스 에디터로 JPEG을 열어 본 적이 있다면, 파일이 마커로 구분된 세그먼트들로 이루어져 있다는 걸 봤을 거예요. 모든 마커는 0xFF로 시작하고, 그 뒤의 바이트가 어떤 종류의 세그먼트인지 알려 줍니다. 이런 설계 덕분에 JPEG은 비교적 파싱하기 쉬워요. FF 바이트를 찾아 그 뒤에 뭐가 오는지 확인하면 됩니다.

프라이버시 측면에서 중요한 건, 모든 메타데이터(EXIF, GPS, 촬영 시각)가 실제 이미지 데이터와 완전히 분리된 이 세그먼트 안에 있다는 점이에요. 그래서 픽셀을 건드리거나 다시 압축하지 않고도 메타데이터만 지울 수 있습니다.

JPEG 파일 구조

SOI
APP0-15
DQT
SOF
DHT
SOS + Data
EOI
SOI
2바이트
이미지 시작 (FF D8)
APP0-15
100바이트
애플리케이션 마커 (메타데이터)
DQT
130바이트
양자화 테이블
SOF
20바이트
프레임 시작
DHT
420바이트
허프만 테이블
SOS + Data
가변 길이
스캔 데이터 (실제 이미지)
EOI
2바이트
이미지 끝 (FF D9)

JPEG 헤더 예시

SOI (이미지 시작)
APP0 마커
APP0 길이
JFIF 식별자
JFIF 데이터
APP1 마커
APP1 길이
Exif 식별자
OffsetHexASCII
0000
FFD8FFE000104A464946000101000048
......JFIF.....H
0010
00480000FFE112344578696600000000
.H.....4Exif..

마커의 구조

  • FF xx:마커 (xx가 종류를 나타냄)
  • LL LL:길이 (2바이트, 빅엔디언, 자기 자신 포함)
  • Data...:세그먼트 데이터 (길이 - 2바이트)

JPEG 마커 전체 목록

마커이름설명
FF D8SOI이미지 시작
FF D9EOI이미지 끝
FF C0SOF0프레임 시작 (베이스라인 DCT)
FF C2SOF2프레임 시작 (프로그레시브 DCT)
FF C4DHT허프만 테이블 정의
FF DBDQT양자화 테이블 정의
FF DDDRI재시작 간격 정의
FF DASOS스캔 시작 (이 뒤로 이미지 데이터)
FF FECOM주석 (메타데이터)
FF E0APP0JFIF 마커
FF E1APP1EXIF / XMP 마커
FF E2APP2ICC 프로필 / MPF
FF EDAPP13IPTC / Photoshop
FF EEAPP14Adobe 색 변환 정보

금색 = 메타데이터(지워짐), 그냥 = 남는 구조

JFIF와 EXIF

많은 사람이 헷갈려 하는 부분이 있어요. JPEG 파일에는 서로 다른 메타데이터 표준이 두 가지 동시에 들어 있는 경우가 많습니다. JFIF가 먼저 나와서 해상도 같은 기본 정보를 담당했고, 그다음에 카메라들이 촬영 정보를 자세히 담은 EXIF를 넣기 시작했어요. 요즘 JPEG은 대부분 둘 다 가지고 있고, 그래서 파일 앞부분에 APP0과 APP1 마커가 나란히 보이는 겁니다.

APP0:JFIF

JPEG File Interchange Format. 기본적인 이미지 정보를 담습니다.

  • • 버전 번호
  • • 픽셀 밀도 (DPI)
  • • 화면 비율
  • • 선택적 썸네일

APP1:EXIF

Exchangeable Image File Format. 카메라 메타데이터를 담습니다.

  • • 카메라 제조사/모델
  • • GPS 좌표
  • • 촬영 시각
  • • 노출 설정

APP 마커 깊이 보기

JPEG 규격은 각 업체가 원하는 대로 쓰라고 "애플리케이션" 마커 16개 (APP0부터 APP15까지)를 비워 뒀습니다. 세월이 흐르면서 여러 단체가 자기 메타데이터 형식으로 서로 다른 마커를 차지했어요. 결과는 좀 뒤죽박죽이지만, 그래도 문서는 잘 되어 있는 뒤죽박죽입니다.

까다로운 점은 같은 마커라도 내용에 따라 의미가 달라진다는 거예요. 예를 들어 APP1은 EXIF일 수도 XMP일 수도 있어서, 안에 들어 있는 식별자 문자열을 봐야 어느 쪽인지 알 수 있습니다.

APP0 (0xFFE0):JFIF

식별자: JFIF\0. 버전, 밀도 단위, X/Y 밀도, 선택적인 내장 썸네일이 들어 있습니다. 대체로 남겨도 안전해요.

APP1 (0xFFE1):EXIF

식별자: Exif\0\0. 카메라 정보, GPS 데이터, 촬영 시각, 썸네일, 메이커 노트를 담는 IFD 항목들이 들어간 완전한 TIFF 구조가 통째로 들어 있습니다. 프라이버시 측면에서 가장 문제가 되는 부분이에요.

APP1 (0xFFE1):XMP

식별자: http://ns.adobe.com/xap/1.0/\0. Adobe가 만든 XML 기반 메타데이터 표준입니다. 편집 이력, 소프트웨어 정보, 확장된 EXIF 데이터가 들어갈 수 있어요.

XMP 네임스페이스
xmp: http://ns.adobe.com/xap/1.0/
xmpMM: http://ns.adobe.com/xap/1.0/mm/
dc: http://purl.org/dc/elements/1.1/
photoshop: http://ns.adobe.com/photoshop/1.0/
tiff: http://ns.adobe.com/tiff/1.0/
exif: http://ns.adobe.com/exif/1.0/

APP1 (0xFFE1):확장 XMP

식별자: http://ns.adobe.com/xmp/extension/\0. 65KB를 넘는 XMP 데이터를 여러 APP1 세그먼트에 나눠 담을 때 씁니다.

APP2 (0xFFE2):MPF

식별자: MPF\0. 입체 이미지와 파노라마를 위한 Multi-Picture Format입니다.

APP2 (0xFFE2):ICC 프로필

식별자: ICC_PROFILE\0. 색 관리 데이터입니다. 여러 APP2 마커에 나뉘어 들어갈 수 있어요. 보통은 남겨도 괜찮습니다.

APP13 (0xFFED):IPTC/Photoshop

식별자: Photoshop 3.0\0. 캡션, 키워드, 저작권, 작성자 정보가 담긴 IPTC-IIM 데이터가 들어 있습니다. 작성자 정보가 포함될 수 있어요.

APP14 (0xFFEE):Adobe

식별자: Adobe\0. 색 변환 플래그(RGB/CMYK)가 들어 있습니다. 색을 제대로 표현하는 데 중요해요.

EXIF의 구조

여기서부터가 재미있고 조금 이상한 부분이에요. EXIF 데이터는 사실 JPEG 안에 들어 있는 아주 작은 TIFF 파일입니다. 정말이에요. 자기만의 헤더와 바이트 순서를 가지고 있고, 태그를 저장하는 데 TIFF의 IFD(Image File Directory) 구조를 씁니다.

"Exif" 식별자 다음에 처음 보이는 건 TIFF 헤더인데, 데이터가 리틀엔디언(Intel, "II")인지 빅엔디언(Motorola, "MM")인지 알려 줍니다. 이걸 잘못 읽으면 모든 숫자가 엉망이 되기 때문에, 어떤 파서든 가장 먼저 확인하는 부분이에요.

TIFF 헤더 (8바이트)

바이트 순서 (II = 리틀엔디언)
매직 넘버 (42)
IFD0 오프셋
OffsetHexASCII
0000
49492A0008000000
II*.....

II = Intel(리틀엔디언), MM = Motorola(빅엔디언)

IFD 항목의 구조 (12바이트)

Tag IDTypeCountValue/Offset
2바이트2바이트4바이트4바이트

주요 IFD 항목

0x010F:Make
0x0110:Model
0x0132:DateTime
0x8769:ExifIFDPointer
0x8825:GPSInfoIFDPointer
0x927C:MakerNote

PicScrub이 JPEG을 처리하는 방법

방식은 아주 단순합니다. 파일을 마커 단위로 읽어 나가면서, 이미지를 표시하는 데 꼭 필요한 것은 남기고 메타데이터가 담긴 것은 건너뜁니다. 압축된 이미지 데이터는 아예 건드리지 않으니 화질 손실이 전혀 없어요.

핵심은 JPEG의 마커 기반 구조 덕분에 이 작업이 쉽다는 점입니다. DCT 계수나 허프만 테이블을 이해할 필요가 없어요. 어떤 세그먼트가 메타데이터이고 어떤 게 아닌지만 가려내면 됩니다.

1

헤더 확인

파일 맨 앞에 SOI 마커(FF D8)가 있는지 검사합니다

2

마커 파싱

마커를 순서대로 읽으며 종류와 길이를 뽑아냅니다

3

메타데이터 판별

APP 세그먼트의 식별자를 확인합니다 (EXIF, XMP, IPTC 등)

4

선별 복사

메타데이터가 아닌 세그먼트만 결과 파일에 옮기고, 메타데이터 세그먼트는 건너뜁니다

남는 것

  • • SOI/EOI 마커 (필수)
  • • DQT (양자화 테이블)
  • • SOF (프레임 헤더)
  • • DHT (허프만 테이블)
  • • SOS와 스캔 데이터 (실제 이미지)
  • • 선택 사항: ICC 색상 프로필 (설정 가능)

지워지는 것

  • • APP1 EXIF (카메라, GPS, 촬영 시각)
  • • APP1 XMP (편집 메타데이터)
  • • APP13 IPTC (캡션, 작성자)
  • • COM 마커 (주석)
  • • EXIF 썸네일 이미지

EXIF 태그 목록

프라이버시 관점에서 모든 EXIF 태그가 똑같이 위험한 건 아니에요. 노출 설정 같은 건 거의 무해합니다. 반면 일련번호나 소유자 이름은 사용자나 장비를 특정할 수 있어요. 저희가 위험도가 높다고 보는 태그는 다음과 같습니다:

태그 ID이름프라이버시 위험도
0x9003DateTimeOriginal높음
0x9004DateTimeDigitized높음
0x9010OffsetTime보통
0x9286UserComment높음
0x927CMakerNote높음
0xA420ImageUniqueID높음
0xA430CameraOwnerName높음
0xA431BodySerialNumber높음
0xA434LensModel보통
0xA435LensSerialNumber높음
0xFDE8OwnerName높음
0xFDE9SerialNumber높음
카메라 설정 태그 전체 보기 (신원과 무관)
0x829A ExposureTime
0x829D FNumber
0x8822 ExposureProgram
0x8827 ISOSpeedRatings
0x9201 ShutterSpeedValue
0x9202 ApertureValue
0x9203 BrightnessValue
0x9204 ExposureBiasValue
0x9207 MeteringMode
0x9208 LightSource
0x9209 Flash
0x920A FocalLength
0xA001 ColorSpace
0xA002 PixelXDimension
0xA003 PixelYDimension
0xA402 ExposureMode
0xA403 WhiteBalance
0xA405 FocalLengthIn35mmFilm
0xA406 SceneCaptureType

GPS 태그 목록

GPS 데이터는 메인 IFD의 0x8825 태그가 가리키는 별도의 하위 IFD에 들어 있습니다. 이 포인터가 있다면 이미지에 위치 정보가 들어 있다는 뜻이에요. 요즘 스마트폰은 특히 적극적으로 이 정보를 넣는데, 어디에 서 있었는지까지 짚어낼 만큼 정밀한 경우도 많습니다.

태그 ID이름설명
0x0000GPSVersionIDGPS 태그 버전
0x0001GPSLatitudeRefN 또는 S
0x0002GPSLatitude도, 분, 초
0x0003GPSLongitudeRefE 또는 W
0x0004GPSLongitude도, 분, 초
0x0005GPSAltitudeRef해수면 위/아래
0x0006GPSAltitude미터
0x0007GPSTimeStampUTC 시각
0x001DGPSDateStampUTC 날짜
0x0012GPSMapDatum측지 기준계 정보
0x001BGPSProcessingMethodGPS/CELLID/WLAN/MANUAL
0x001CGPSAreaInformation장소 이름

IPTC 태그 목록

IPTC는 통신사들이 캡션, 크레딧, 저작권 정보를 사진에 심으려고 만든 표준이에요. "Photoshop 3.0" 식별자와 함께 APP13 안에 저장됩니다 (네, Adobe가 가져다 썼어요). Lightroom이나 Photoshop에서 저작권 정보나 키워드를 넣은 적이 있다면, 그게 바로 여기에 들어갑니다.

0x0250 By-line (작성자)
0x0255 By-line Title (작성자 직함)
0x025A City (도시)
0x025C Sub-location (세부 장소)
0x025F Province/State (지역)
0x0265 Country Name (국가)
0x0274 Copyright Notice (저작권 표기)
0x0276 Contact (연락처)
0x0237 Date Created (생성 날짜)
0x023C Time Created (생성 시각)
0x0278 Caption/Abstract (캡션)
0x0219 Keywords (키워드)