나는 당신의 URL에 쿼리 문자열을 추가하지 않겠다
(susam.net)- Susam Pal은 Chris Morgan의 쿼리 문자열을 금지했다를 읽은 뒤 Wander Console에 추가했던
via=쿼리 매개변수를 제거함 - Wander Console은 개인 웹사이트 방문자가 커뮤니티가 추천한 페이지를 무작위로 탐색하게 해주는 분산형 자체 호스팅 웹 콘솔이며, 현재 50개 넘는 웹사이트가 호스팅하고 1500개 넘는 웹페이지를 추천함
via=기능은 추천된 웹사이트 운영자가 접근 로그에서 방문 출처를 볼 수 있게 했지만,https://midnight.pub/?via=https://susam.net/wander/처럼 목적지 URL을 직접 바꾸는 방식이었음- 쿼리 문자열을 붙이면 새 URL이 되어 다른 리소스를 가리키거나 404를 낼 수 있으며,
int10h.org의 글꼴 페이지처럼 쿼리 문자열을 자체 식별자로 쓰는 사이트를 실제로 깨뜨림 - 브라우저에는 이미 Referer와 Referrer-Policy가 있어 출처 정보 전송을 제어할 수 있으므로, Wander Console 0.6.0부터는 다른 사람의 URL에 추천 출처용 쿼리 문자열을 추가하지 않음
Chris Morgan의 쿼리 문자열 비판이 계기가 됨
- Susam Pal은 Chris Morgan의 글 쿼리 문자열을 금지했다를 읽고, 자신의 프로젝트 Wander Console에 추가했던
via=쿼리 매개변수를 제거함 - Chris Morgan은
https://chrismorgan.info/no-query-strings?ref=example.com처럼 다른 사람이 자신의 URL에 추적용 정보를 붙이는 것을 원하지 않음 - 출처 정보가 필요하다면 HTTP
Referer헤더를 보면 되고, 그 헤더가 없다면 그럴 만한 이유가 있을 가능성이 높음 - Susam Pal은 과거 Hacker News에서 Chris Morgan이 자신의 CSS 보일러플레이트 규칙에 남긴 상세한 피드백을 통해 링크 밑줄 유지와 방문한 링크의 보라색 유지 같은 교훈을 얻었음
- 이후 Chris Morgan의 웹 관련 글과 피드백을 계속 읽어 왔고, Lobsters의 RSS에 작성자 맥락 추가하기에 달린 최근 댓글도 유용한 예로 듦
Wander Console의 구조와 목적
- Wander Console은 개인 웹사이트 방문자가 독립 개인 웹사이트 운영자 커뮤니티가 추천한 흥미로운 웹사이트와 페이지를 탐색할 수 있게 하는 작고 분산형이며 자체 호스팅 가능한 웹 콘솔임
- Susam Pal의 콘솔은 susam.net/wander/에 있으며,
Wander버튼을 누르면 Wander 커뮤니티가 추천한 무작위 개인 웹페이지를 불러옴 - 도구는 콘솔을 구현한 HTML 파일 하나와, 사이트 운영자가 이웃 콘솔 목록 및 추천 웹페이지 목록을 정의하는 JavaScript 파일 하나로 구성됨
- 두 파일을 웹서버에 복사하면 일반 웹서버만으로 실행할 수 있으며, 별도의 서버 측 로직이나 서버 측 소프트웨어가 필요 없음
- Codeberg Pages나 GitHub Pages 같은 제약이 있는 환경에서도 호스팅 가능함
Wander버튼을 누르면 콘솔이 다른 원격 콘솔에 연결하고, 웹페이지 추천을 가져온 뒤, 하나를 무작위로 골라 브라우저에 로드함- 사라진 StumbleUpon과 조금 비슷하지만 완전히 분산형이라는 차이가 있음
- 웹링과도 조금 비슷하지만 커뮤니티 네트워크가 순환 구조에 제한되지 않고 어떤 형태의 그래프도 될 수 있음
- 현재 50개가 넘는 웹사이트가 이 도구를 호스팅하고 있으며, 합쳐서 1500개가 넘는 웹페이지를 추천함
- 알려진 콘솔과 추천 페이지의 최근 스냅샷은 susam.codeberg.page/wcn/에서 볼 수 있음
- 도구를 더 알아보거나 자신의 웹사이트에 설정하려면 codeberg.org/susam/wander를 참고하면 됨
via= 쿼리 매개변수라는 잘못된 기능
- Wander Console 0.4.0에는 웹페이지를 로드할 때
via=쿼리 매개변수를 붙이는 기능이 추가됨 - 예를 들어 susam.net/wander/ 콘솔에서 midnight.pub를 만나면 다음 URL로 페이지를 로드했음
https://midnight.pub/?via=https://susam.net/wander/
- 이 방식은 추천된 웹사이트의 운영자가 접근 로그를 통해 방문이 Wander Console에서 왔다는 것을 확인할 수 있게 해줌
- 이 기능은 Codeberg의 기능 요청을 보고 추가됐지만, 처음에는 망설임이 있었음
- 당시 대수적 그래프 이론 연구 마감이 임박해 있었고, Wander Console의 대부분도 연구 중 짧은 휴식 시간에 만들어짐
- 콘솔의 첫 버전은 어느 이른 아침 약 1시간 30분 만에 만들어졌고,
via=기능도 비슷한 짧은 휴식 시간에 구현됨 - Susam Pal은 작은 취미 프로젝트에 기능을 계속 추가하기보다 범위를 제한하고, 필수 요구사항을 만족하면 기능 완성 상태로 두는 유지 방식을 선호함
- 그럼에도 피로와 강도 높은 연구 작업 때문에 해당 기능 요청을 무시하지 못했다고 봄
via=기능에는 비활성화할 수 있는 설정이 있었지만, 나중에는 이 역시 실수였다고 판단함- 의심스러운 기능은 구현하더라도 기본 활성화 후 비활성화가 아니라 명시적 활성화 방식이어야 함
- Jurassic Park의 “할 수 있는지에 너무 몰두한 나머지 해야 하는지 생각하지 않았다”는 인용구가 이 상황에 맞아 보임
쿼리 문자열이 실제 URL을 깨뜨림
via=기능을 구현한 뒤, 좋아하던 웹사이트의 한 페이지가 콘솔에서 로드되지 않음- 문제가 된 페이지의 비슷하지만 조금 다른 URL은 다음과 같음
- 첫 번째와 두 번째 URL은 정상 로드되지만, 세 번째 URL은 HTTP 404 오류 페이지를 반환함
- 해당 웹사이트는 여러 글꼴 컬렉션 중 어떤 것을 보여줄지 결정하기 위해 쿼리 문자열을 사용함
- 임의의 쿼리 문자열을 붙이면 사이트가 이를 글꼴 컬렉션 식별자로 해석하려 하므로 페이지 로드가 실패함
- Wander Console이 첫 번째 URL에
via=쿼리 매개변수를 붙였을 때도 같은 이유로 페이지가 깨짐 - URL을 변경하면 작은 변경처럼 보이는 쿼리 문자열 추가라도 새 URL이 됨
- 새 URL은 완전히 다른 리소스를 가리키거나, 아무 리소스도 가리키지 않을 수 있음
- Susam Pal은
via=쿼리 문자열을 붙임으로써 자신이 좋아하는 웹사이트의 정상 URL을 깨뜨렸다고 판단함
Referer와 Referrer-Policy를 우회하는 문제
- 웹 브라우저에는 이미 출처 정보를 위한 HTTP Referer 헤더가 있음
- 이 헤더는 Referrer-Policy에 의해 제어됨
- Referrer-Policy는 서버 수준, 문서 수준, 개별 링크 수준에서 설정할 수 있음
- 웹 표준은 어떤 범위의 출처 정보를 보낼지 결정할 수 있는 의도적인 제어 수단을 이미 제공함
- URL에 추천 출처용 쿼리 문자열을 덧붙이는 방식은 이러한 제어를 우회함
- 프라이버시와 출처 표시 문제를 리퍼러 메커니즘 밖으로 꺼내 목적지 URL 안에 직접 박아 넣는 셈임
- HTML 도구가 이런 방식으로 URL을 바꾸면 안 된다고 판단함
- 사용자 대신 URL을 수정해 추천 출처 쿼리 문자열을 넣는 행위 자체도 옳지 않다고 봄
기능 제거와 이후 원칙
- Wander Console에서 추천 출처 쿼리 문자열 기능은 제거됨
- 기능을 명시적 활성화 옵션으로 남겨둘 수도 있었지만, 잘못된 기능이라고 판단한 뒤에는 어떤 형태로도 소프트웨어에 남기고 싶지 않았음
- 프로젝트가 아직 새롭고 0.x 릴리스 단계이므로 기능을 제거하기에 좋은 시점이었다고 봄
- Chris Morgan의 쿼리 문자열을 금지했다가 피드 리더에 나타난 것을 계기로, 연구 시간을 잠시 떼어 이 기능을 제거함
- 제거 내용은 커밋 b26d77c에서 확인할 수 있음
- 최신 릴리스인 0.6.0에는 이 기능이 더 이상 포함되지 않음
- 앞으로 새 취미 프로젝트에서 URL을 로드하게 된다면 웹사이트 작성자가 의도한 그대로 로드하겠다는 원칙을 세움
- 다른 사람의 URL에 쿼리 문자열을 추가하지 않겠다는 결론에 도달함
Lobste.rs 의견들
-
내 글이 어떻게 도움이 됐는지 알려줘서 고마움. 자세한 리뷰를 쓰는 이유는 여러 가지인데, 내 만족도 있고, 원 프로젝트를 돕기 위해서이기도 하고 개발자가 관심을 보일 때도 있지만 아닌 경우도 많고, 인터넷에서 누군가가 틀렸기 때문이기도 함
하지만 가장 큰 이유는 가르치는 걸 좋아하고, 다른 사람들이 이 리뷰를 읽는다는 걸 알기 때문임. 실제로 내 리뷰들은 꾸준히 가장 많은 추천을 받는 댓글에 속함
가끔 모르는 사람이 남겨주는 감사 댓글을 정말 소중하게 여기고, 이렇게 자세한 감사는 더 따뜻한 기분을 줌
재미있는 건 1월에 당신 사이트를 발견했고 특히 “more purple links, please”를 아주 마음에 들어 했는데, 오늘 보니 내가 모르는 사이 당신의 입장에 영향을 준 셈이었음
어제 새 웹사이트를 공개했고, 앞으로 여러 매체에서 리뷰를 훨씬 더 많이 올릴 생각임. 지난달에 이 계획을 조금 적어둠: https://lobste.rs/s/vpdpkq/llm_reviews_cargo_crev#c_8uk441
또 이미 추가 쿼리 문자열에 알레르기 반응을 보이는 페이지 예시가 하나 더 있었다는 점이 조금 놀라웠음. 그 사이트에서는 해당 페이지만?1,?2,?3,?4처럼 쿼리 문자열을 하위 페이지 라우팅에 쓰고, 다른 페이지들은 쿼리 문자열을 받아줌. 순차 페이지네이션은 명백히 계층적이라 URL의 정신에는 어긋나지만,?page=1같은 방식도 흔하긴 함
어떤 상태 코드를 반환할지 정할 때 404가 잘못된 가정 때문에 부작용을 낼까 걱정했는데, 어쩌면 그 걱정은 과했을지도 모름. 웹의 상당 부분이 경로를 의미 있게 쓰지 않는다는 걸 깜빡했음- 권한 없는 쿼리 문자열에 대해
"418 I'm not a teapot"응답을 반환하는 건 고려하지 않았나?
- 권한 없는 쿼리 문자열에 대해
-
좋음. Wander console이 훌륭하게 성장하고 있고, Susam이 여기서 보여주는 세심함이 작동하는 큰 이유로 보임
내 URL에도 원치 않는 쿼리 문자열이 붙는 변형을 몇 가지 봤음. Programmer Weekly 뉴스레터는 쿼리를 붙이지만 참조자 헤더도 있어서 중복임
또 다른 경우는 구독자마다 고유 ID가 붙는 듯한데, 전혀 원치 않음. 곤란하게도 참조자가 없어서 어느 사이트가 그러는지도 모름
/blog/modeling-on-demand-pricing/?ck_subscriber_id=<unique-id> -
“알고 싶으면 Referer 헤더를 보면 되고, 없다면 아마 그럴 만한 이유가 있을 것”이라는 말에 동의하고 싶지만, Referer는 몇 년째 어느 정도 망가졌거나 쓸모없는 상태였음. 이런 것들이 생긴 유일한 이유가 그 때문임
- 어떻게 그렇다는 건가?
-
“왜 추가했냐고? 대중적 요구에 굴복했다”라니, 정말 그랬나? 관련 없는 이슈에 달린 추천 5개짜리 가벼운 댓글 하나였음. 굴복하기 전 싸움이 그리 치열하진 않았던 듯 ;-)
- 여기서 ‘가벼운 댓글’이 무슨 뜻인지 잘 모르겠음. 그 댓글은 내 소프트웨어를 직접 써보고, 자기 웹사이트에 설치하고, 그 사이트를 커뮤니티 네트워크의 일부로 만든 사람이 남긴 것이었음. 그걸 ‘가벼운 것’으로 치부하진 않겠음
이 프로젝트에 사용자가 열 명 정도뿐이던 시점에 새 기능 제안이 추천 5개를 받았다면, 내게는 대중적 요구처럼 느껴졌음
내 프로젝트들은 보통 취미로 만드는 작은 도구임. 몇 가지 예외를 빼면 사용자 수가 많지 않음. 그래서 기능 요청이나 버그 보고를 받으면, 관련 이슈든 관련 없는 이슈든 내게는 중요함. 항상 바로 작업하진 못해도, 어떤 요청이 더 많은 수요를 받았는지는 마음속에 기록해 둠
- 여기서 ‘가벼운 댓글’이 무슨 뜻인지 잘 모르겠음. 그 댓글은 내 소프트웨어를 직접 써보고, 자기 웹사이트에 설치하고, 그 사이트를 커뮤니티 네트워크의 일부로 만든 사람이 남긴 것이었음. 그걸 ‘가벼운 것’으로 치부하진 않겠음