한글 다운로드 파일명이 깨질 때: Content-Disposition의 filename과 filename*
HTTP 다운로드에서 한글 파일명을 전달하는 filename과 filename*의 차이, UTF-8 퍼센트 인코딩, ASCII 대체 이름과 수신 측 보안 처리를 RFC 6266과 RFC 8187로 설명합니다.
서버는 보고서.pdf를 의도했지만 수신 측에 제안된 이름이 다르거나 깨졌다면 Content-Disposition 응답 헤더를 확인해야 합니다. 이 헤더는 응답 처리 방식과 저장할 때 제안할 파일명을 전달합니다. 비ASCII 이름을 plain filename에 직접 넣으면 실패할 수 있습니다. RFC 6266은 호환성을 위해 filename과 확장 매개변수 filename*를 함께 보내라고 조언합니다.
attachment와 파일명은 다른 정보다
attachment는 미디어 타입에 따른 일반 처리 대신 로컬 저장을 안내하라는 disposition type입니다. filename과 filename*는 저장 이름을 만드는 데 쓰는 정보입니다.
Content-Disposition: attachment; filename="report.pdf"; filename*=UTF-8''%EB%B3%B4%EA%B3%A0%EC%84%9C.pdf
filename="report.pdf"는 확장 문법을 모르는 오래된 수신자를 위한 ASCII 대체 이름입니다. filename*는 실제 이름 보고서.pdf를 담습니다. 둘 다 있으면 RFC 6266은 filename*를 이해하는 수신자가 그것을 선택하고 filename을 무시하도록 권고합니다. 호환성 조언에 따라 대체용 filename을 먼저 적었습니다.
같은 이름의 매개변수를 두 번 쓰면 유효하지 않습니다. 언어별 이름을 여러 filename*에 나열하는 구조가 아닙니다. filename*의 언어 부분은 선택 사항이며 파일명에서는 효용이 제한적이어서 예시에서는 비웠습니다.
별표 값은 UTF-8 바이트를 싣는다
RFC 6266은 이 문법의 출처로 RFC 5987을 인용하지만, RFC 8187이 나중에 RFC 5987을 대체했습니다. 따라서 현재 인코딩 문법은 RFC 8187을 따릅니다. 확장 값은 문자 인코딩'언어'값 구조입니다. 생성자는 UTF-8을 사용해야 하고 수신자도 UTF-8을 지원해야 합니다. 보고서.pdf를 UTF-8로 바꾸면 다음 바이트가 됩니다.
EB B3 B4 EA B3 A0 EC 84 9C 2E 70 64 66
허용되는 ASCII 문자는 그대로 두고 나머지 옥텟을 %와 두 자리 16진수로 적습니다.
filename*=UTF-8''%EB%B3%B4%EA%B3%A0%EC%84%9C.pdf
첫 작은따옴표 앞의 UTF-8은 필수 문자 인코딩이고, 두 작은따옴표 사이는 선택 언어 태그입니다. 여기서는 빈 문자열입니다. 공백도 허용 문자 집합에 없으므로 %20으로 써야 합니다. 수신자는 16진수의 대문자와 소문자를 모두 해석해야 합니다. 표기를 통일하면 읽기는 쉽습니다.
이는 URL 전체를 인코딩한다는 뜻이 아닙니다. UTF-8 옥텟을 퍼센트 표기로 바꾸는 점은 URL 인코딩과 같지만, 적용 문법은 HTTP 헤더 매개변수입니다.
받은 이름은 명령이 아니라 제안이다
RFC 6266은 수신자가 파일명을 참고 정보로만 취급해야 한다고 강조합니다. ../../etc/passwd처럼 경로가 섞여 와도 허용된 위치 밖에 쓰면 안 됩니다. \와 /로 나뉜 마지막 부분만 취하는 것이 한 가지 방어법입니다. 수신자가 미디어 타입을 판단할 때 확장자에 의존한다면 안전한 확장자인지 반드시 확인해야 하며, 응답 미디어 타입과 일치하는 값이 바람직합니다. 제어 문자, 앞뒤 공백, ., .., 장치 이름처럼 파일 시스템이나 셸에서 특별한 이름도 제거하거나 바꾸는 것이 좋습니다.
서버 쪽의 실용적인 기본값은 간단합니다. ASCII filename을 먼저 두고 원하는 이름을 UTF-8로 변환한 filename*를 뒤에 둡니다. 수신 측에서는 어느 매개변수를 골랐든 경로와 확장자를 검증합니다. plain filename에 UTF-8 문자를 직접 넣었을 때 각 브라우저가 어떻게 복구하는지는 RFC가 보장하는 동작이 아니며 이 글의 범위에도 포함하지 않았습니다.
ZIP 파일명 인코딩은 다운로드 뒤 압축 파일 내부 이름이 깨지는 별개의 문제를 다룹니다.
참고한 명세
문서 상태와 정오표를 포함해 2026년 10월 5일에 확인했습니다.