요약

  • 1996년 5월 RFC 1945는 목적지 서버가 Referer를 통해 링크가 놓인 페이지의 URI를 받을 수 있다고 설명했다. 역방향 링크 목록, 기록, 잘못된 링크 수정이 용도였다. 같은 절에서 출발 주소가 사적인 문서를 드러낼 수 있다고 경고했다.
  • 1997년 1월 RFC 2068은 이 필드를 유지하고 Referer가 영어 단어를 잘못 쓴 이름이라고 명시했다. 주소를 직접 입력했다면 보낼 출발 페이지가 없고 URI의 프래그먼트는 값에 포함되지 않는다. 보안 절은 사적인 문서 URI의 노출을 다뤘다.
  • 2017년 1월 26일 W3C 후보 권고안은 완전한 URL, 사이트의 오리진만, 참조 정보 없음 등을 선택하는 Referrer-Policy를 정의했다. 문서는 해당 날짜의 설계를 보여주며 브라우저별 실제 보급률을 세지는 않는다.

받는 서버에는 유용한 반송 주소

1996년 5월의 HTTP/1.0 원문 RFC 1945는 방문자를 맞는 서버에 경로의 단서를 줬다. 브라우저가 어떤 페이지의 링크를 따라갈 때 요청의 Referer 필드에 링크가 있던 페이지의 URI를 담을 수 있다. 서버는 자신을 가리키는 페이지 목록을 만들고, 접속 기록을 남기고, 캐시 작업을 조정하고, 오래되거나 잘못 적힌 링크를 찾아낼 수 있었다. 명세가 직접 열거한 용도다.

자료를 새 주소로 옮긴 도서관을 생각해 보자. 다른 사이트에는 옛 주소를 가리키는 링크가 남아 있다. 그 링크에서 온 요청이 원래 페이지 주소까지 알려주면 도서관은 어디에 수정을 부탁해야 할지 안다. 다른 사이트를 소유하지 않아도 링크 지도의 뒷면 일부를 볼 수 있다. 수많은 운영자가 각자 페이지를 만드는 웹에서 이런 반송 주소는 실질적인 유지보수 도구였다.

처음부터 경계도 있었다. 사용자가 주소창에 직접 URL을 넣으면 출발 페이지의 URI가 없다. RFC는 이 경우 Referer를 보내지 말라고 했다. URI의 프래그먼트도 값에서 뺀다. 링크를 누른 방문과 주소를 직접 입력한 방문은 다른 경로다. 목적지 서버가 없는 이전 페이지를 만들어 기록해서는 안 됐다.

유용한 설명 바로 옆에 비용이 적혀 있었다. 링크의 출발지는 사적인 정보일 수 있고, 그 주소만으로 사적인 자료의 위치가 알려질 수도 있다. 문서 작성자들은 필드 전송 여부를 이용자가 고를 수 있도록 강하게 권했고, 브라우저에서 공개적인 탐색과 익명 탐색을 전환하는 예를 들었다. 1996년의 설계 문서는 링크 수리의 편의와 사적인 주소 유출을 한꺼번에 봤다.

빠진 철자보다 큰 문제

1997년 1월 HTTP/1.1 원문 RFC 2068은 이름을 짚었다. Referer는 올바른 영어 ‘referrer’를 잘못 쓴 표기다. 그래도 브라우저와 서버가 교환하는 필드명은 바뀌지 않았다. 역방향 링크 목록과 로그, 틀린 주소 추적의 용도도 남았다. 직접 입력한 주소에 출발 페이지를 붙이지 않는 원칙과 프래그먼트를 제외하는 규칙도 이어졌다.

오타는 웃기 쉽다. 더 큰 결정은 정보의 이동 방향이다. 새 서버로 가는 요청에 다른 사이트의 이전 페이지 주소가 실린다. 도착지 운영자가 유입을 알고 싶은 이유는 분명하다. 그러나 어느 기관이 독자를 보냈는지와 그 기관의 누구의 개인 페이지가 보냈는지는 정보의 깊이가 다르다. 앞의 사실만으로 고장 난 링크를 다루는 데 충분한 경우가 있다.

RFC 2068의 보안 절은 Referer로 읽기 패턴을 연구하고 역방향 링크를 만들 수 있다고 설명했다. 직접적인 개인 정보를 따로 떼더라도 사적인 문서의 URI가 노출될 수 있다. 프로필 경로, 내부 문서 이름, 세션 매개변수는 URL 자체에 문맥을 새긴다. 링크의 화면상 글자에는 아무런 비밀이 없어도 요청 헤더가 그 문맥을 옮긴다.

두 RFC는 필드의 의미와 주의점을 기록한다. 당시 모든 브라우저가 어느 주소를 얼마나 보냈는지를 세는 자료는 아니다. 하지만 이해관계의 충돌은 이미 선명하다. 받는 서버는 링크를 고칠 정확한 실마리가 필요하고, 출발 페이지와 독자는 사적인 방의 주소까지 넘기고 싶지 않을 수 있다.

사이트 이름과 방 번호 사이

완전한 URL은 도메인 이름에서 끝나지 않는다. 경로에 개인 프로필이나 작업 공간이 드러나고 쿼리에 세션 식별자가 담길 수 있다. 이를 Referer로 보내면 도착 서버는 방문자가 어느 사이트에서 왔는지뿐 아니라 그 사이트의 어느 페이지를 떠났는지 안다. 독자는 다음 자료를 열려고 클릭했을 뿐인데 요청의 부가 정보가 이전 공간의 주소를 말한다.

도착 서버는 받은 값을 로그에 보관할 수 있다. 반면 URL의 경로가 무엇을 뜻하는지는 출발 사이트가 가장 잘 안다. 어떤 경로가 한 사람을 가리키고 어떤 매개변수가 접근 권한과 관련되는지 판단할 수 있다. 1996년 문서가 상상한 이용자 스위치는 브라우저 전반의 선택이었다. 페이지별 정책이라면 그 페이지 주소의 성격에 맞춰 공개 범위를 조절할 수 있다.

선택지마다 쓰임이 다르다. 전체 URL은 잘못된 링크의 위치를 정확히 알려준다. 오리진, 곧 방식·호스트·포트만 보내면 방문을 보낸 사이트는 알려주면서 개별 경로와 쿼리는 숨긴다. 아무것도 보내지 않으면 사이트 이름도 사라진다. 목적지의 기록이 자세해질수록 출발지가 건네는 주소 정보도 많아진다.

떠나는 쪽에서 양을 정하다

2017년 1월 26일 W3C의 「Referrer Policy」 후보 권고안은 분명한 사례를 든다. 소셜 사이트의 개인 프로필에서 음악 그룹의 사이트로 링크한다. 그룹은 방문이 소셜 사이트에서 왔다는 사실은 알아도, 프로필 주인을 드러내는 완전한 URL까지 받을 이유는 없을 수 있다. 주소 자체에 세션 식별자나 접근 권한이 담긴 웹 애플리케이션의 사례도 나온다. 이런 주소는 단순한 길 안내를 넘어선다.

초안은 공개 수준을 나눴다. no-referrer는 헤더를 생략한다. same-origin은 같은 오리진으로는 전체 URL을 보내고 다른 오리진으로는 보내지 않는다. origin은 방식·호스트·포트만 보내며 경로와 쿼리를 버린다. strict-origin은 보호된 맥락에서 신뢰하기 어려운 목적지로 갈 때 추가 제한을 둔다. 다른 값은 내부 요청과 외부 요청의 규칙을 조합한다. 질문은 ‘보낼까’에서 ‘누구에게 주소의 어디까지 보여줄까’로 바뀌었다.

페이지 작성자는 응답 헤더 Referrer-Policy, meta 요소, 일부 요소의 속성, 링크의 noreferrer 관계로 선택을 표현할 수 있었다. 새 정책의 이름은 영어 철자가 맞다. 정책이 다루는 요청 헤더는 여전히 오래된 Referer다. 새 지시문에서 영어를 고쳤지만 이미 오가는 메시지의 이름은 뒤집지 않았다.

2017년 문서는 당시 후보 권고안이었다. 각 규칙이 무엇을 하도록 설계됐는지를 보여준다. 각 브라우저가 언제 이를 구현했는지 확정하려면 날짜가 있는 구현 기록이 필요하다. 그래도 설계의 중심이 옮겨간 것은 분명하다. 자기 페이지 주소가 무엇을 드러내는지 아는 쪽이 브라우저가 밖으로 가져갈 양을 정할 수 있게 됐다.

역방향 링크에는 정보 값이 붙는다

목적지가 방문 경로를 알고 싶어 하는 데는 실제 이유가 있다. 오래된 인용을 고치고 독자가 자료를 어떻게 찾는지 이해한다. 1996년 RFC는 그 이익을 정확히 적었고, 바로 곁에 사적 URI의 위험도 적었다. 출발지가 닫힌 페이지라면 유지보수 영수증은 다른 서버에 보관될 주소 사본이기도 하다.

나중의 정책은 출발 사이트가 자기 이름만 밝히고 프로필 경로는 보관하거나 아예 침묵하도록 한다. 목적지의 링크 목록은 덜 상세해진다. 이는 공개를 줄이기 위해 지불하는 구체적인 비용이다. 자기 서버의 링크를 고쳐야 한다는 이유만으로 모든 방문자가 떠난 방의 번호를 받을 권리가 생기지는 않는다.

Referer의 철자 실수는 오래 기억된다. 더 중요한 변화는 두 질문을 갈라놓은 것이다. ‘어느 사이트가 방문을 보냈나’와 ‘그 사이트의 어느 사적인 페이지를 독자가 떠났나’는 같은 질문이 아니다.

출처