HTTP Content-Disposition은 응답을 어떻게 다룰지와 저장할 때 제안할 파일명을 전달한다. attachment는 다운로드 처리를 제안하고 inline은 기본 처리에 맡긴다. 파일명은 서버가 정하는 절대 저장 경로가 아니라 수신자에게 주는 제안이다. 한글 파일명이 깨지는 문제와 안전한 저장 위치의 문제는 이 헤더의 서로 다른 측면이다.

제안된 파일명과 제한된 저장 위치의 개념도

실제 저장 결과를 표시하지 않는 개념 설명입니다.

응답 처리와 파일명을 나눠 보기

RFC 6266은 attachment를 일반적인 미디어 유형 처리 대신 저장하도록 지시하는 용도로 설명한다. inline은 기본 처리를 뜻하며, 파일명 같은 부가 매개변수와 함께 쓸 수 있다. 따라서 같은 PDF라도 표시 방식의 요청과 저장 이름의 제안을 나눠 읽어야 한다. 파일명을 붙였다는 사실만으로 attachment가 되는 것은 아니다.

브라우저는 자신의 동작과 화면을 통해 저장을 진행하므로 서버가 사용자의 디렉터리를 직접 결정하지 않는다. 이 글은 HTTP 응답의 다운로드 파일명에 집중하며, multipart 폼의 각 필드 이름과는 구분한다. 같은 헤더 이름이 다른 문맥에서도 쓰인다고 해서 응답용 규칙을 그대로 폼 업로드에 적용해서는 안 된다. 응답 처리 규칙

다국어 이름에는 filename*가 필요하다

RFC는 filename과 filename*를 구분하며, 뒤의 형식이 확장 인코딩으로 더 다양한 문자를 표현할 수 있다고 설명한다. UTF-8 문자 데이터를 그 형식에 맞게 전달하면 한글과 일본어 같은 이름을 표현할 수 있다. 단순히 일반 파일명 값에 퍼센트로 바꾼 글자를 넣는 것과는 다른 형식이다.

둘을 함께 보내면 규격은 지원하는 수신자가 filename*를 선택하고 filename을 무시하도록 권고한다. 따라서 확장 이름과 구형 수신자를 위한 기본 이름을 같은 파일의 두 표현으로 설계할 수 있다. 기본 이름은 읽을 수 있는 ASCII 대체 이름으로 두고 확장 이름에는 원래 표시 이름을 유지하는 방식이 실무적으로 유용하다. 두 값이 다른 문서를 가리키는 것처럼 보이지 않게 의미를 맞춘다.

예를 들어 기본 이름은 report.pdf로 두고 확장 이름은 보고서.pdf로 정할 수 있다. 파일의 실제 내용과 확장자는 같고, 이름의 언어 표현만 달라지는 비교 사례다.

구문 예를 filename="report.txt"; filename*=UTF-8''%EB%B3%B4%EA%B3%A0%EC%84%9C.txt로 읽을 수 있다. 두 작은따옴표 사이의 언어 표시는 비어 있고, 뒤의 퍼센트 표현은 UTF-8 바이트를 나타낸다. 확장 값 자체는 따옴표 문자열이 아니다. 이는 보고서.txt라는 이름의 설명용 예이며 실제 다운로드나 브라우저 시험 결과가 아니다. RFC 8187은 생성자의 UTF-8 사용과 확장 매개변수 형식을 규정한다. 확장 매개변수 구문 파일명 선택 규칙

전문 관점: 인코딩과 브라우저 차이

MDN의 전문 안내는 호환성을 위해 두 매개변수를 함께 제공하는 방법을 설명한다. 또한 filename 안의 퍼센트 이스케이프를 브라우저가 서로 다르게 다룰 수 있다고 경고한다. 따라서 주소 문자열 인코딩을 파일명 전체에 무작정 적용하기보다 어느 매개변수 형식을 만드는지 먼저 구분해야 한다.

공백과 다국어가 들어간 이름, 단순한 ASCII 이름을 실제 대상 브라우저에서 각각 저장해 확인하는 것이 적절하다. 화면에 표시된 이름과 디스크에 저장된 이름도 비교한다. MDN은 파일 시스템 요구에 맞춰 경로 구분자가 바뀌는 등 브라우저가 이름을 변환할 수 있다고 설명한다. 모든 환경에서 서버 문자열이 그대로 보존된다는 기대는 맞지 않는다. 수신 환경 안내

수신자는 이름을 경로로 믿지 않는다

RFC는 파일명을 권고 정보로만 취급해야 한다고 강조한다. 경로 구분자를 포함한 이름이 오더라도 허용된 위치 밖에 쓸 수 있어서는 안 된다. 문서가 제시하는 방법 중 하나는 경로 정보를 믿지 않고 마지막 이름 부분만 사용하는 것이다. 서버의 제안은 수신자가 저장 권한을 넓힐 근거가 아니다.

확장자도 검토 대상이다. 저장된 파일을 확장자로 해석하는 환경에서는 응답이 제안한 확장자를 그대로 신뢰하면 위험한 처리를 유도할 수 있다. RFC는 안전한 확장자를 요구하고, 수신한 미디어 유형과 일치하는 것을 최적의 선택으로 설명하며, 제어 문자나 혼동을 주는 공백도 정리하도록 권고한다. 이는 이름의 가독성을 넘어 저장 후 동작을 다루는 문제다. 권고 이름의 안전 경계

다운로드 계약을 확인하는 순서

먼저 응답의 처리 방식, 표시할 다국어 이름, 기본 대체 이름을 정한다. 이어서 두 파일명 표현이 같은 의미인지 확인하고, 실제 수신 환경에서 결과를 본다. 수신 프로그램을 직접 만드는 경우에는 저장 위치와 이름 검사를 별도 단계로 두는 것이 실무적 권고다.

이 헤더는 파일 내용의 진위나 다운로드 권한을 증명하지 않는다. 이름이 잘 표시된다는 사실과 내용이 안전하다는 판단을 구분해야 한다. 처리 방식과 인코딩을 올바르게 전달하고, 수신자가 제안 이름을 자신의 규칙에 맞게 제한하는 두 책임을 함께 이해하면 다국어 다운로드를 더 명확히 설계할 수 있다.

송신자도 헤더를 만드는 단계에서 별도의 책임이 있다. RFC 9110은 필드 값의 CR, LF, NUL을 유효하지 않고 위험한 값으로 다룬다. 원래 이름을 검증하지 않은 채 헤더 문자열에 연결하는 문제와, 수신자가 디코딩한 이름을 저장 경로로 쓰는 문제는 구분해야 한다. 파일명 인코딩만으로 두 경계를 모두 해결한다고 보장할 수 없다. HTTP 필드 값

가상의 점검표에서는 원래 표시 이름, 생성한 두 매개변수, 실제 표시 결과, 최종 저장 위치를 별도 칸에 적을 수 있다. 한 칸의 성공이 다음 칸의 안전성을 증명하지는 않는다. 생성 오류와 저장 제한을 서로 다른 질문으로 남기는 것이 이 비교 연습의 목적이다.

출처