요약

  • HTML download 속성은 링크를 파일로 저장해 달라고 요청하고 이름을 제안한다. HTTP 응답도 Content-Disposition으로 이름을 보낼 수 있다.
  • 2013년 Mozilla 버그 기록과 2017년 WHATWG 논의는 다른 출처의 파일을 내려받을 때 이 요청이 부딪힌 경계를 보여 준다.

다운로드 폴더에 report.pdf가 놓였다. 누군가 이름표를 붙였겠지만, 화면은 그 과정을 보여 주지 않는다. 버튼을 만든 페이지가 먼저 이름을 썼을 수 있다. 파일을 보내는 서버가 새 이름표를 달았을 수도 있다. 브라우저는 그 둘을 보고 사용자의 컴퓨터에 실제 파일을 만든다. 택배 기사에게 상자 이름까지 마음대로 정하라고 할 수 없듯, 웹에서도 보내는 쪽과 받는 쪽의 권한을 나누는 일이 필요했다.

서버의 방법은 2011년 6월 발표된 RFC 6266에 정리돼 있다. HTTP Content-Disposition의 attachment는 저장을 유도하고, filename과 국제 문자를 다룰 수 있는 filename*는 파일 이름을 제안한다. RFC는 이 이름을 조언으로 취급한다. 경로 조각이 엉뚱한 폴더를 가리키거나, 위험한 확장자가 붙거나, 특수 문자가 이용자를 헷갈리게 만들면 받는 프로그램이 손봐야 한다. 서버가 배송장에 주소를 썼다고 해서 컴퓨터 안의 아무 서랍이나 열 수는 없다.

페이지에도 도구가 생겼다. Chromium의 웹 플랫폼 기록에는 a[download]가 M14부터 제공된 기능으로 적혀 있다. 링크에 이 속성을 붙이면 페이지 작성자는 열어 보기 대신 저장을 요청하고 파일 이름도 권할 수 있다. 그래프를 내보내거나 페이지에서 만든 자료를 저장할 때 매우 편하다. 그러나 버튼이 있는 사이트와 파일을 실제로 호스팅하는 사이트가 다르면, 그 편리함은 곧 권한 문제가 된다.

2013년 Mozilla 버그 보고는 차이를 한 장의 그림으로 보여 준다. 다른 사이트의 이미지를 가리키는 링크에 download="filename.png"를 붙였더니 Firefox는 이미지를 열고 Chrome은 저장했다. 보고자는 Firefox의 동작을 고쳐야 한다고 봤다. Mozilla는 필요한 보안 조치라고 답하고 보고를 종료했다. 사용자 눈에는 같은 클릭이지만, 브라우저에는 남의 사이트가 제공한 내용을 파일로 만들라는 지시가 들어온 셈이었다.

2017년 4월 WHATWG의 논의는 당시의 구현 차이를 더 정확히 적었다. 해당 교차 출처 상황에서 Firefox와 Safari는 download를 무시했고, Chrome은 다운로드하되 페이지가 제시한 이름을 버렸다. 표준 편집자는 당시 알고리즘이 양쪽 결과를 허용한다고 설명하며 동작을 맞출 가능성을 언급했다. ‘저장할 것인가’와 ‘어떤 이름으로 저장할 것인가’가 별개의 결정임을 보여 준 대목이다. 그 무렵 WebKit은 macOS의 Safari 10.1에 이 속성이 들어왔다고 발표하며 페이지가 만든 Blob 파일 저장도 소개했다. 기능은 이미 생활 속으로 들어왔고, 경계는 계속 다듬어졌다.

현재 HTML 표준은 페이지의 download를 저장 의도와 이름 제안으로 다룬다. 서버의 Content-Disposition 이름이 그 제안을 덮을 수 있다. 출처를 넘는 다운로드에는 파일을 제공하는 서버의 attachment가 중요한 신호가 된다. 그래야 다른 페이지가 뜻밖의 파일을 이용자에게 밀어 넣는 상황을 막을 수 있다. 마지막에는 브라우저가 로컬 이름과 저장 위치를 판단한다.

다운로드 버튼은 작은 창구다. 페이지는 주문서를 쓰고 서버는 물건을 보내며 브라우저는 집 안에 들일지 확인한다. 폴더에 남은 파일 이름은 그 세 단계가 합의한 결과다. 이름표가 하나처럼 보여도, 그 뒤에는 서로 다른 책임을 가진 손이 여럿 있었다.