Skip to content
isdnetworks
Go back

인코딩된 이름이 실제 키가 되는 자리

(수정됨)

명품몰에 한글 파일명으로 올린 상품 이미지가 안 열리고 주소에 %25ED%2595%259C 처럼 퍼센트 기호가 이중으로 들어간 문자열이 보였다. 이중 인코딩처럼 보여서 주소를 만드는 쪽을 의심했다.

Table of contents

Open Table of contents

증상 — 목록에는 한글로 보이던 키

오브젝트 스토리지 콘솔에서 버킷을 목록으로 조회하니 파일명이 한글로 보였다. 그러면 저장은 정상이고 주소 생성이 잘못된 것으로 읽힌다.

그런데 한글 키로 doesObjectExist() 를 부르니 없다는 응답이 왔다. 목록에 보이는 것과 실제로 조회되는 것이 어긋나 있었다.

검증 — 원시 키와 개별 조회의 교차

listObjects() 로 원시 키를 그대로 출력하는 방식으로 다시 보니 %ED%95%9C%EA%B8%80.jpg 같은 퍼센트 인코딩된 문자열이 실제 키였다. 콘솔이 표시할 때 디코딩해서 보여 주고 있었던 것이다.

도구가 보여 주는 것과 실제 저장된 값이 다를 수 있으므로 원시 키 조회와 개별 존재 확인을 교차해야 확정된다. 한글 키로 없고 인코딩 키로 있으면 인코딩된 문자열이 실제 이름이라는 뜻이다.

원인 — 이중 인코딩이 정상 경로였다

그러면 지금까지 어떻게 동작했는지가 남는다. 우리 코드가 저장된 파일명을 주소에 넣으면서 URLEncoder 로 한 번 더 인코딩하고 있었다.

RFC 3986 대로 % 자체도 인코딩 대상이라 %ED 는 %25ED 가 되고, 두 번 인코딩된 주소를 서버가 한 번 디코딩하면 실제 키와 일치한다. 이중 인코딩처럼 보이던 것이 우연이 아니라 일관되게 동작하는 정상 경로였다.

디코딩 없이 저장한 지점

거슬러 올라가니 브랜드 사이트 주소에서 이미지를 받아오는 ImageFetcher 가 주소의 인코딩된 부분을 URLDecoder 로 풀지 않고 그대로 파일명으로 저장하고 있었다. 저장소에도 그 문자열 그대로 올라갔다.

copyObject() 를 쓰는 복제 함수는 그 값을 그대로 물려주므로 복제본도 같은 상태가 된다. 수만 건이 이미 그 형태로 굳어 있었다.

판단 기준 — 부분 정상화가 가장 나쁜 이유

두 가지 방법이 있었다. 저장소 키를 정본으로 보고 지금 상태를 유지하는 것과, 업로드에 디코딩을 넣고 기존 키를 전부 이름 변경하는 것이다. 앞쪽을 골랐다. 이유는 뒤쪽이 옳아 보이지만 수만 건 이름 변경 중에 접근하면 안 열리고 그 비용을 감당할 시기가 아니어서다. 대신 코드에 이중 인코딩이 의도된 경로라는 주석을 남겨야 하는 것을 감수했다.

확실한 것은 신규만 한글로 저장하는 방식은 하면 안 된다는 것이었다. 저장소에 두 형식이 섞이면 조회 코드가 어느 쪽인지 판단할 방법이 없어져서 섞인 상태가 어느 한쪽으로 통일된 상태보다 나쁘다.

정리


Share this post on:

Previous Post
건너뛴 조건의 전체 목록
Next Post
파일명이 같아도 경로가 갈린다