블로그 사진의 위치 정보, 업로드 전에 지우기

사진의 방향을 바로잡고 EXIF를 제거한 뒤 WebP로 바꾸는 업로드 흐름을 정리했다. 현재 스크립트가 확인하는 범위와 예외 형식도 함께 짚는다.

휴대폰 사진에는 촬영 시각, 기종, GPS 좌표 같은 메타데이터가 들어갈 수 있다. 사진을 그대로 블로그에 올리면 내가 의도하지 않은 장소 정보까지 공개할 수 있다. 그래서 게시용 사진은 업로드 전에 별도로 변환한다.

업로드 흐름

현재 upload-media.sh는 JPEG·PNG·HEIC·WebP·TIFF·AVIF 같은 이미지를 WebP로 변환한다.

원본 사진 → 방향 보정 → 프로필·주석 제거 → 긴 변 최대 1920px
          → WebP 저장 → EXIF 재검사 → S3 media/연/월/ 업로드

출력 이름이 이미 S3에 있으면 업로드를 멈추고, 성공하면 글에 붙일 Markdown 이미지 구문을 출력한다. 게시용 파일에는 1년 캐시와 immutable을 붙이므로, 같은 주소에 새 파일을 덮어쓰지 않는 운영 규칙이 중요하다.

순서가 중요한 ImageMagick 명령

magick input.jpg -auto-orient -strip -resize '1920x1920>' \
  -quality 82 -define webp:method=6 output.webp

-auto-orient가 EXIF의 회전 값을 실제 픽셀에 먼저 반영한다. 그 뒤 -strip으로 이미지 프로필과 주석을 제거한다. 순서를 뒤집으면 회전 정보를 없앤 뒤 방향을 맞추려 해, 세로 사진이 눕는 문제가 생길 수 있다. 1920x1920>는 가로세로 비율을 유지한 채 그 크기보다 큰 이미지만 줄인다. -quality 82는 화질과 파일 크기 사이에서 고른 내 설정값이지, 모든 사진에 맞는 표준값은 아니다.

HEIC를 처리하려면 ImageMagick 빌드에 해당 형식 지원이 있어야 한다. 내 CI 이미지에는 관련 라이브러리를 넣었다. 다른 환경에서는 magick -list format으로 지원 여부를 먼저 확인하는 편이 좋다.

‘EXIF가 없다’와 ‘메타데이터가 없다’는 다르다

현재 스크립트는 변환 후 다음 명령으로 EXIF 속성이 남았는지 검사한다.

magick identify -format '%[EXIF:*]' output.webp

출력이 있으면 업로드를 멈춘다. 하지만 이 검사는 EXIF만 본다. -strip은 다른 프로필과 주석도 제거하도록 설계됐지만, 위 검사 결과만으로 모든 형식의 메타데이터가 완전히 없어졌다고 증명할 수는 없다. 특히 민감한 사진은 결과 파일을 ExifTool 같은 독립 도구로 한 번 더 살펴보는 편이 안전하다.

또 현재 스크립트는 GIF·SVG·PDF를 변환 없이 그대로 업로드한다. 이 형식에는 같은 보호 절차가 적용되지 않는다. GPS 제거가 필요한 사진은 변환 대상 형식으로 넣고, SVG·PDF의 내용과 메타데이터는 따로 검토해야 한다.

업로드 권한과 마지막 확인

사진 업로드용 IAM 계정은 media/ 경로를 읽고 올릴 수 있지만 삭제 권한은 없다. 스크립트는 먼저 같은 이름이 있는지 조회한 뒤 올린다. 다만 조회와 업로드는 별도 요청이라 동시에 같은 이름을 올리는 경쟁까지 원자적으로 막지는 못한다. 꼭 보장하려면 S3 조건부 쓰기를 사용해야 한다.

메타데이터를 지워도 사진 속 번호판, 주소, 집 주변 풍경, 송장은 남는다. 업로드 전에는 변환 결과를 눈으로 한 번 더 확인한다. 기술적 제거와 육안 검토가 함께 있어야 익명 블로그에 맞는 사진이 된다.

참고: ImageMagick 명령 옵션, S3 조건부 쓰기