왜 여권 사진이 계속 거부되는가 (문제는 파일, 사진이 아니라)
Source: Dev.to
정부 포털에 여권 사진을 업로드하고 모호한 “photo rejected” 오류를 받은 적이 있다면, 문제는 보통 사진 자체가 아니라 파일에 있습니다.
저는 IDPhotoSnap이라는 무료 브라우저 기반 여권 사진 도구를 운영하고 있습니다. 가장 흔한 지원 문의는 “내 사진은 괜찮은데, 왜 포털에서 틀렸다고 하는가?”라는 변형입니다. 답은 거의 항상 눈에 보이는 이미지가 아니라 파일 메타데이터에 있습니다.
8가지 파일‑레벨 거절 사유
1. 파일 크기 범위 초과
대부분의 대사관 포털은 엄격한 용량 제한을 두고 있습니다:
- 미국 국무부 DS‑160: 최대 240 KB
- 영국 여권 포털: 50 KB – 10 MB
- 쉥겐 비자 포털: 240 KB – 6 MB (국가마다 다름)
- 인도 여권 Seva: 20 KB – 300 KB
현대 스마트폰은 기본 설정으로 4–8 MB 정도의 사진을 촬영하므로, 사람의 눈으로 사진을 보기 전에 포털에서 업로드를 거부하는 경우가 많습니다.
2. DPI 오류
DPI는 메타데이터에 저장되며 픽셀 데이터 자체는 바뀌지 않습니다. 휴대폰 카메라는 사진에 72 DPI를 태그하지만, 대사관 인쇄 파이프라인은 300 DPI를 요구합니다.
// JPEG에서는 DPI가 JFIF 헤더(바이트 13‑18) 혹은 EXIF 태그 0x011A에 저장됩니다.
// 이를 변경해도 재압축이나 리사이즈가 일어나지 않으며, 해당 바이트만 다시 씁니다.
ImageMagick으로 DPI를 확인할 수 있습니다:
identify -format "%x x %y\n" photo.jpg # → 72x72 (필요한 값은 300x300)
픽셀 내용은 동일하지만, 메타데이터 태그가 검증기를 통과하지 못하게 합니다.
3. 치수 오류
각 국가마다 요구하는 사진 크기가 다릅니다:
| 국가 | 크기 |
|---|---|
| 미국 | 600 × 600 px (2 × 2 in) |
| 쉥겐 | 35 × 45 mm |
| 영국 | 35 × 45 mm, 최소 600 × 750 px |
| 인도 | 51 × 51 mm, 최소 600 × 600 px |
| 일본 | 35 × 45 mm, 최소 413 × 531 px |
한 국가에서 통과된 사진이 다른 국가에서는 실패할 수 있습니다—보편적인 크기는 없습니다.
4. 형식 오류 (HEIC, WebP, PNG)
iPhone은 기본적으로 HEIC 형식으로 저장하고, Android는 때때로 WebP를 사용합니다. 대부분의 정부 포털은 JPG만을 허용하며, 절반 정도는 PNG도 거부합니다.
HEIC → JPG 변환은 WASM으로 컴파일된 libheif를 사용해 클라이언트 측에서 수행할 수 있습니다:
import { decode } from 'libheif-js'
async function heicToJpeg(file) {
const buf = await file.arrayBuffer()
const decoder = new Decoder()
const data = decoder.decode(new Uint8Array(buf))
// …canvas에 그린 뒤 품질 0.92로 JPEG로 내보내기
}
5. 배경이 순백이 아님
배경 검증기는 RGB(255,255,255) ± 작은 오차 범위를 찾습니다. 흔히 발생하는 실패 사례:
- 약간 누런 벽 (255, 250, 245)
- 창문 빛에 의해 벽에 생긴 그라데이션
- 머리 뒤에 드리운 부드러운 그림자
정식 요건을 만족하려면 배경을 완전히 교체해야 합니다. 브라우저 내에서 동작하는 MODNet(~25 MB ONNX) 같은 ML 세그멘테이션 모델을 onnxruntime-web으로 실행할 수 있습니다.
6. 압축 아티팩트
품질 60 % JPEG는 눈에 띄는 블록 아티팩트를 보여줍니다. 검증기는 종종 낮은 SSIM을 플래그합니다. 90‑95 % 품질로 다시 압축하고, 파일이 여전히 크면 픽셀 치수를 줄이되 최소 크기 이하로는 절대 낮추지 마세요.
7. 색 프로필 불일치
iPhone에서 촬영한 사진은 Display‑P3일 수 있지만, 검증기는 sRGB를 기대합니다. 내보내기 전에 변환하세요:
ctx.imageSmoothingEnabled = true
ctx.drawImage(img, 0, 0)
const data = ctx.getImageData(0, 0, w, h)
// Canvas는 기본적으로 sRGB이며, 그리면서 프로필이 변환됩니다.
8. 내장 썸네일 불일치
일부 포털은 EXIF 썸네일을 본 이미지와 비교합니다. 메인 이미지를 크롭했지만 썸네일이 원본 그대로라면 파일이 편집된 것으로 판단됩니다. EXIF를 완전히 제거하세요:
// Canvas를 통한 재인코딩은 모든 EXIF/XMP/IPTC 메타데이터를 제거합니다.
canvas.toBlob(blob => {
// blob을 업로드 …
}, 'image/jpeg', 0.95)
여기서 브라우저‑전용 도구가 의미가 있는 이유
위의 모든 작업은 순수한 픽셀 조작이며 브라우저에서 로컬로 수행할 수 있습니다—서버 연산도, 클라우드 AI도 필요 없습니다. 배경 교체조차도 onnxruntime-web을 사용해 중간 사양 노트북에서 약 2‑5 초 안에 로컬로 실행됩니다.
WebAssembly에서 잘 동작하는 작업을 위해 얼굴 사진을 제3자 서비스에 업로드하는 것은 설계가 좋지 않을 뿐만 아니라 프라이버시에도 악영향을 줍니다.
이 방식을 실제로 보고 싶다면, IDPhotoSnap이 85개국 이상에 대한 8가지 문제를 모두 업로드 없이 처리합니다. 또한 **Photo Rejected hub**는 거부된 사진을 진단하고 특정 문제를 완전히 클라이언트‑사이드에서 수정합니다.
Lesson
정부 포털이 “예쁜 사진”을 거부할 때, **90 %**는 사진 자체가 아니라 파일 메타데이터를 읽고 있기 때문입니다. 이를 위한 엔지니어링은 주로 JPEG 헤더에 무엇을 넣을지 신중하게 결정하는 것—DPI 태그, 해상도, 색상 프로필, 내장 썸네일—에 초점을 맞추며, 픽셀 자체보다는 메타데이터에 중점을 둡니다.
FAQ
Q: 왜 여권 포털은 구체적인 오류 메시지를 제공하지 않을까요?
A: 그들은 검증기 체인(크기 → 형식 → DPI → 차원 → 배경)을 실행하고 첫 번째 실패에서 중단합니다. 일부는 마지막 실패 코드를 표시할 뿐이며, 많은 경우 유용한 피드백을 전혀 제공하지 않습니다.
Q: 사진을 인쇄하면 DPI가 해결되나요?
A: 대면 제출의 경우에는 예, 하지만 아니오 온라인 포털의 경우—포털은 파일 메타데이터를 읽으며 인쇄물을 읽지 않습니다.
Q: HEIC를 JPG로 변환하고 끝낼 수 있나요?
A: 크기와 형식 검사는 종종 가능하지만, 변환기는 일반적으로 DPI 태그를 72 DPI로 재설정하고 전화 기본 차원을 그대로 유지하므로, 종종 리사이즈와 DPI 재작성도 필요합니다.
Q: 서버‑사이드 처리가 필요할까요?
A: 99 %의 경우 필요하지 않습니다. 배경 제거가 유일한 경계 사례(대형 모델 파일)입니다. 나머지는 Canvas와 몇 KB의 JavaScript만으로 충분히 처리됩니다.