# 나는 당신의 URL에 쿼리 문자열을 추가하지 않겠다

> Clean Markdown view of GeekNews topic #29342. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=29342](https://news.hada.io/topic?id=29342)
- GeekNews Markdown: [https://news.hada.io/topic/29342.md](https://news.hada.io/topic/29342.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-10T09:10:51+09:00
- Updated: 2026-05-10T09:10:51+09:00
- Original source: [susam.net](https://susam.net/no-query-strings.html)
- Points: 1
- Comments: 1

## Topic Body

- Susam Pal은 Chris Morgan의 [쿼리 문자열을 금지했다](https://chrismorgan.info/no-query-strings)를 읽은 뒤 **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의 글 [쿼리 문자열을 금지했다](https://chrismorgan.info/no-query-strings)를 읽고, 자신의 프로젝트 **Wander Console**에 추가했던 `via=` 쿼리 매개변수를 제거함
- Chris Morgan은 `https://chrismorgan.info/no-query-strings?ref=example.com`처럼 다른 사람이 자신의 URL에 추적용 정보를 붙이는 것을 원하지 않음
- 출처 정보가 필요하다면 HTTP `Referer` 헤더를 보면 되고, 그 헤더가 없다면 그럴 만한 이유가 있을 가능성이 높음
- Susam Pal은 과거 Hacker News에서 Chris Morgan이 자신의 CSS 보일러플레이트 규칙에 남긴 [상세한 피드백](https://news.ycombinator.com/item?id=25321222#25322611)을 통해 링크 밑줄 유지와 방문한 링크의 보라색 유지 같은 교훈을 얻었음
- 이후 Chris Morgan의 웹 관련 글과 피드백을 계속 읽어 왔고, Lobsters의 [RSS에 작성자 맥락 추가하기](https://lobste.rs/s/crcktq/adding_author_context_rss#c_wb5ryy)에 달린 최근 댓글도 유용한 예로 듦

### Wander Console의 구조와 목적
- **Wander Console**은 개인 웹사이트 방문자가 독립 개인 웹사이트 운영자 커뮤니티가 추천한 흥미로운 웹사이트와 페이지를 탐색할 수 있게 하는 작고 분산형이며 자체 호스팅 가능한 웹 콘솔임
- Susam Pal의 콘솔은 [susam.net/wander/](https://susam.net/wander/)에 있으며, `Wander` 버튼을 누르면 Wander 커뮤니티가 추천한 무작위 개인 웹페이지를 불러옴
- 도구는 콘솔을 구현한 HTML 파일 하나와, 사이트 운영자가 이웃 콘솔 목록 및 추천 웹페이지 목록을 정의하는 JavaScript 파일 하나로 구성됨
- 두 파일을 웹서버에 복사하면 일반 웹서버만으로 실행할 수 있으며, 별도의 서버 측 로직이나 서버 측 소프트웨어가 필요 없음
- Codeberg Pages나 GitHub Pages 같은 제약이 있는 환경에서도 호스팅 가능함
- `Wander` 버튼을 누르면 콘솔이 다른 원격 콘솔에 연결하고, 웹페이지 추천을 가져온 뒤, 하나를 무작위로 골라 브라우저에 로드함
- 사라진 [StumbleUpon](https://en.wikipedia.org/wiki/StumbleUpon)과 조금 비슷하지만 완전히 분산형이라는 차이가 있음
- 웹링과도 조금 비슷하지만 커뮤니티 네트워크가 순환 구조에 제한되지 않고 어떤 형태의 그래프도 될 수 있음
- 현재 50개가 넘는 웹사이트가 이 도구를 호스팅하고 있으며, 합쳐서 1500개가 넘는 웹페이지를 추천함
- 알려진 콘솔과 추천 페이지의 최근 스냅샷은 [susam.codeberg.page/wcn/](https://susam.codeberg.page/wcn/)에서 볼 수 있음
- 도구를 더 알아보거나 자신의 웹사이트에 설정하려면 [codeberg.org/susam/wander](https://codeberg.org/susam/wander#readme)를 참고하면 됨

### `via=` 쿼리 매개변수라는 잘못된 기능
- Wander Console **0.4.0**에는 웹페이지를 로드할 때 `via=` 쿼리 매개변수를 붙이는 기능이 추가됨
- 예를 들어 [susam.net/wander/](https://susam.net/wander/) 콘솔에서 [midnight.pub](https://midnight.pub/)를 만나면 다음 URL로 페이지를 로드했음

```text
https://midnight.pub/?via=https://susam.net/wander/
```

- 이 방식은 추천된 웹사이트의 운영자가 접근 로그를 통해 방문이 Wander Console에서 왔다는 것을 확인할 수 있게 해줌
- 이 기능은 Codeberg의 [기능 요청](https://codeberg.org/susam/wander/issues/1#issuecomment-11795493)을 보고 추가됐지만, 처음에는 망설임이 있었음
- 당시 대수적 그래프 이론 연구 마감이 임박해 있었고, Wander Console의 대부분도 연구 중 짧은 휴식 시간에 만들어짐
- 콘솔의 첫 버전은 어느 이른 아침 약 1시간 30분 만에 만들어졌고, `via=` 기능도 비슷한 짧은 휴식 시간에 구현됨
- Susam Pal은 작은 취미 프로젝트에 기능을 계속 추가하기보다 범위를 제한하고, 필수 요구사항을 만족하면 기능 완성 상태로 두는 유지 방식을 선호함
- 그럼에도 피로와 강도 높은 연구 작업 때문에 해당 기능 요청을 무시하지 못했다고 봄
- `via=` 기능에는 비활성화할 수 있는 설정이 있었지만, 나중에는 이 역시 실수였다고 판단함
- 의심스러운 기능은 구현하더라도 기본 활성화 후 비활성화가 아니라 **명시적 활성화** 방식이어야 함
- Jurassic Park의 “할 수 있는지에 너무 몰두한 나머지 해야 하는지 생각하지 않았다”는 인용구가 이 상황에 맞아 보임

### 쿼리 문자열이 실제 URL을 깨뜨림
- `via=` 기능을 구현한 뒤, 좋아하던 웹사이트의 한 페이지가 콘솔에서 로드되지 않음
- 문제가 된 페이지의 비슷하지만 조금 다른 URL은 다음과 같음
  - [https://int10h.org/oldschool-pc-fonts/fontlist/](https://int10h.org/oldschool-pc-fonts/fontlist/)
  - [https://int10h.org/oldschool-pc-fonts/fontlist/?2](https://int10h.org/oldschool-pc-fonts/fontlist/?2)
  - [https://int10h.org/oldschool-pc-fonts/fontlist/?foo](https://int10h.org/oldschool-pc-fonts/fontlist/?foo)
- 첫 번째와 두 번째 URL은 정상 로드되지만, 세 번째 URL은 HTTP 404 오류 페이지를 반환함
- 해당 웹사이트는 여러 글꼴 컬렉션 중 어떤 것을 보여줄지 결정하기 위해 쿼리 문자열을 사용함
- 임의의 쿼리 문자열을 붙이면 사이트가 이를 글꼴 컬렉션 식별자로 해석하려 하므로 페이지 로드가 실패함
- Wander Console이 첫 번째 URL에 `via=` 쿼리 매개변수를 붙였을 때도 같은 이유로 페이지가 깨짐
- URL을 변경하면 작은 변경처럼 보이는 쿼리 문자열 추가라도 **새 URL**이 됨
- 새 URL은 완전히 다른 리소스를 가리키거나, 아무 리소스도 가리키지 않을 수 있음
- Susam Pal은 `via=` 쿼리 문자열을 붙임으로써 자신이 [좋아하는](https://news.ycombinator.com/item?id=39419054#39439453) 웹사이트의 정상 URL을 깨뜨렸다고 판단함

### Referer와 Referrer-Policy를 우회하는 문제
- 웹 브라우저에는 이미 출처 정보를 위한 HTTP [Referer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referer) 헤더가 있음
- 이 헤더는 [Referrer-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy)에 의해 제어됨
- Referrer-Policy는 서버 수준, 문서 수준, 개별 링크 수준에서 설정할 수 있음
- 웹 표준은 어떤 범위의 출처 정보를 보낼지 결정할 수 있는 의도적인 제어 수단을 이미 제공함
- URL에 추천 출처용 쿼리 문자열을 덧붙이는 방식은 이러한 제어를 우회함
- 프라이버시와 출처 표시 문제를 리퍼러 메커니즘 밖으로 꺼내 목적지 URL 안에 직접 박아 넣는 셈임
- HTML 도구가 이런 방식으로 URL을 바꾸면 안 된다고 판단함
- 사용자 대신 URL을 수정해 추천 출처 쿼리 문자열을 넣는 행위 자체도 옳지 않다고 봄

### 기능 제거와 이후 원칙
- Wander Console에서 추천 출처 쿼리 문자열 기능은 제거됨
- 기능을 명시적 활성화 옵션으로 남겨둘 수도 있었지만, 잘못된 기능이라고 판단한 뒤에는 어떤 형태로도 소프트웨어에 남기고 싶지 않았음
- 프로젝트가 아직 새롭고 0.x 릴리스 단계이므로 기능을 제거하기에 좋은 시점이었다고 봄
- Chris Morgan의 [쿼리 문자열을 금지했다](https://chrismorgan.info/no-query-strings)가 피드 리더에 나타난 것을 계기로, 연구 시간을 잠시 떼어 이 기능을 제거함
- 제거 내용은 커밋 [b26d77c](https://codeberg.org/susam/wander/commit/b26d77c4da9ec11b655ba64a4ae4f3af56e06370)에서 확인할 수 있음
- 최신 릴리스인 **0.6.0**에는 이 기능이 더 이상 포함되지 않음
- 앞으로 새 취미 프로젝트에서 URL을 로드하게 된다면 웹사이트 작성자가 의도한 그대로 로드하겠다는 원칙을 세움
- 다른 사람의 URL에 쿼리 문자열을 추가하지 않겠다는 결론에 도달함

## Comments



### Comment 57141

- Author: neo
- Created: 2026-05-10T09:10:52+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/vbit2a/i_will_not_add_query_strings_your_urls) 
- 내 글이 어떻게 도움이 됐는지 알려줘서 고마움. 자세한 리뷰를 쓰는 이유는 여러 가지인데, 내 만족도 있고, 원 프로젝트를 돕기 위해서이기도 하고 개발자가 관심을 보일 때도 있지만 아닌 경우도 많고, [인터넷에서 누군가가 *틀렸기* 때문](https://xkcd.com/386/)이기도 함  
  하지만 가장 큰 이유는 **가르치는 걸 좋아하고**, 다른 사람들이 이 리뷰를 읽는다는 걸 알기 때문임. 실제로 내 리뷰들은 꾸준히 가장 많은 추천을 받는 댓글에 속함  
  가끔 모르는 사람이 남겨주는 감사 댓글을 정말 소중하게 여기고, 이렇게 자세한 감사는 더 따뜻한 기분을 줌  
  재미있는 건 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=&lt;unique-id&gt;`

- “알고 싶으면 Referer 헤더를 보면 되고, 없다면 아마 그럴 만한 이유가 있을 것”이라는 말에 동의하고 싶지만, **Referer**는 몇 년째 어느 정도 망가졌거나 쓸모없는 상태였음. 이런 것들이 생긴 유일한 이유가 그 때문임
  - 어떻게 그렇다는 건가?

- “왜 추가했냐고? 대중적 요구에 굴복했다”라니, 정말 그랬나? 관련 없는 이슈에 달린 추천 5개짜리 **가벼운 댓글 하나**였음. 굴복하기 전 싸움이 그리 치열하진 않았던 듯 ;-)
  - 여기서 ‘가벼운 댓글’이 무슨 뜻인지 잘 모르겠음. 그 댓글은 내 소프트웨어를 직접 써보고, 자기 웹사이트에 설치하고, 그 사이트를 커뮤니티 네트워크의 일부로 만든 사람이 남긴 것이었음. 그걸 ‘가벼운 것’으로 치부하진 않겠음  
    이 프로젝트에 사용자가 열 명 정도뿐이던 시점에 새 기능 제안이 추천 5개를 받았다면, 내게는 **대중적 요구**처럼 느껴졌음  
    내 프로젝트들은 보통 취미로 만드는 작은 도구임. [몇 가지 예외](https://github.com/susam/)를 빼면 사용자 수가 많지 않음. 그래서 기능 요청이나 버그 보고를 받으면, 관련 이슈든 관련 없는 이슈든 내게는 중요함. 항상 바로 작업하진 못해도, 어떤 요청이 더 많은 수요를 받았는지는 마음속에 기록해 둠
