쿼리 문자열 파서

URL이나 쿼리 문자열을 키/값 쌍으로 분해해 편집한 뒤, 정돈된 쿼리 문자열로 다시 조립합니다.

Loading…

모든 처리는 브라우저 내부에서 실행됩니다 — 파일·입력은 서버로 전송되지 않습니다.

사용법

완전한 URL(`https://example.com/?a=1&b=2#frag`)이나 쿼리 문자열만(`?a=1&b=2` 또는 `a=1&b=2`) 붙여 넣으세요. 파서가 편집 가능한 키·값 행으로 분해합니다. 쌍을 추가·삭제·이름 변경하면 아래쪽의 재조립된 쿼리 문자열이 실시간으로 갱신됩니다. "+ for spaces"를 켜면 HTML 폼 형식(`+ = 공백`, `URLSearchParams.toString()` 출력 형식), 끄면 엄격한 RFC 3986 형식(`%20 = 공백`, 현대 API가 선호하는 형식)으로 전환됩니다.

애널리틱스, 리다이렉트 체인, 어필리에이트 URL을 디버깅할 때 사용하세요. UTM 태그·세션 키·트래킹 ID의 긴 나열이 테이블로 읽힙니다. 빠진 파라미터를 더하거나, 키 오타를 고치거나, 링크를 공유하기 전에 트래킹 잡음을 제거하고 정돈된 결과를 다시 복사할 수 있습니다. 프래그먼트(`#…`)는 쿼리 계층에 속하지 않아 제거됩니다. 처리는 모두 네이티브 URL·URLSearchParams API로 브라우저 안에서 끝나므로 토큰이나 세션 ID가 들어간 링크도 기기 밖으로 나가지 않습니다.

예제

애널리틱스 URL 점검

입력
https://shop.example.com/products?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale&product_id=42&ref=alice
출력
utm_source     newsletter
utm_medium     email
utm_campaign   spring_sale
product_id     42
ref            alice

5개짜리 쿼리 문자열이 훑어보고 편집할 수 있는 깔끔한 테이블이 됩니다. 링크 공유 전에 트래킹 항목을 제거하려면 `utm_*` 4행과 `ref`를 지우고 재조립된 쿼리를 복사하세요. 남는 것은 `?product_id=42`뿐입니다.

다중 선택 필터의 반복 키

입력
?tag=react&tag=typescript&tag=performance&page=2
출력
tag    react
tag    typescript
tag    performance
page   2

같은 키 반복은 "이 필터가 여러 값을 갖는다"를 의미하는 URL의 표준 관례입니다(검색 패싯, 다중 선택 드롭다운 등). 백엔드 프레임워크마다 노출 방식이 다릅니다. Express는 `req.query.tag = ["react", "typescript", "performance"]`, Rails는 `params[:tag] = "performance"`(마지막 1개만, `tag[]=` 형식을 쓰지 않는 한), Django는 `request.GET.getlist('tag')` 같은 식입니다. 파서는 순서를 유지하므로 각 행을 점검할 수 있습니다.

엄격한 RFC 3986 인코드로 재조립

입력
query (raw): q=hello world&lang=ko
plusForSpaces: off
출력
q=hello%20world&lang=ko

"+ for spaces"를 끄면 공백이 `%20`이 되며 `application/x-www-form-urlencoded`의 엄격한 변종과 일치합니다. 다양한 클라이언트를 가로지르는 예측 가능한 인코드가 필요할 때 사용하세요. 오래된 PHP나 특정 Java 서블릿처럼 `+` 해석을 폼 바디에서만 올바르게 하고 쿼리 문자열에서는 틀리는 백엔드가 있습니다.

자주 묻는 질문

`+` vs `%20` — 어느 쪽을 써야 하나요?

둘 다 쿼리 문자열 안에서 유효하지만 출처가 다릅니다. `%20`은 RFC 3986의 범용 공백 퍼센트 인코드로 어디서나 동작합니다. `+`는 `application/x-www-form-urlencoded` 관례로(원래 1990년대 HTML 폼 유래) 대부분의 쿼리 파서에서 동작하지만 엄밀하게는 폼 바디 전용입니다. 현대 지침은 양 끝을 통제할 수 있으면 `%20`을 출력하고, 수신 측은 양쪽을 허용하는 것입니다. JavaScript의 `URLSearchParams.toString()`은 항상 `+`를 뱉기 때문에 세상에 손으로 짠 대체 구현이 많습니다.

URL에서 배열·다중 값은 어떻게 표현되나요?

관례가 네 가지 있고, 어느 것도 보편적이지 않습니다. **반복 키**(`?tag=a&tag=b`)가 가장 이식성이 좋고 이 도구가 출력하는 형식입니다. 모든 파서가 처리합니다. **브래킷 표기**(`?tag[]=a&tag[]=b`)는 PHP 관례로 Rails도 같은 형식을 채택했습니다. **인덱스 표기**(`?tag[0]=a&tag[1]=b`)는 드물지만 일부 Rails 폼에서 사용됩니다. **콤마 구분**(`?tag=a,b`)은 OpenAPI 3의 `style: form, explode: false` 출력입니다. 서버가 기대하는 형식을 고르세요. 한 URL에서 섞어 쓰면 버그가 됩니다.

URL의 경로와 프래그먼트는 유지되나요?

아니요. 이 도구는 쿼리 계층만 분리합니다. 완전한 URL을 붙여 넣으면 쿼리만 추출하고 스킴·호스트·경로·프래그먼트를 떨어내며 `key=value&…` 부분만 재조립합니다. 완전한 URL을 붙여 넣고-편집-재조립하려면 재조립된 쿼리를 복사해 경로에 직접 이어 붙이거나(`/products?` + 결과) URL의 모든 구성 요소를 다루는 URL 파싱 도구를 사용하세요.

빈 값이 사라지는 이유는?

사라지지 않습니다. 값이 비어도 `key=` 행은 유지됩니다. 다만 키가 완전히 빈 행은 재조립 시 삭제됩니다. `=value` 같은 키 없는 형태는 주요 파서에서 의미가 정의되어 있지 않기 때문입니다. "`flag`의 값이 빈 문자열"을 표현하려면 키를 두고 값 셀을 비워 두세요. "`flag` 파라미터가 존재하되 값이 없다"를 표현하려면 같은 방식으로 값을 비워 두면 됩니다. 많은 파서가 둘을 동일하게 다룹니다.

재조립 시 키 순서는 유지되나요?

예. 에디터는 삽입 순서를 유지하고 재조립은 위에서 아래로 행을 따라갑니다. RFC 3986은 특정 순서를 요구하지 않으므로 대부분의 서버는 `?a=1&b=2`와 `?b=2&a=1`을 동일하게 다룹니다. 다만 캐시 계층(CDN 캐시 키), 웹훅 서명 검증, 사람의 리뷰에서는 안정된 순서가 선호되는 경우가 많습니다. AWS Signature v4와 OAuth 1.0a는 서명 전에 파라미터를 정렬한다고 명시합니다. 그런 서명을 재현하려면 복사 전에 행을 정렬하세요.

URL Encoder 도구와의 차이는?

URL Encoder는 단일 문자열을 다룹니다. 블롭으로 인코드하거나 디코드합니다. Query String Parser는 *구조*를 다룹니다. 키·값 행으로 분리해 편집하고 재조립합니다. 리다이렉트 대상이나 토큰처럼 단일 값을 URL에 붙여 넣기 전에 이스케이프하려면 URL Encoder, 입력이 쿼리 문자열 전체이고 개별 파라미터를 점검·수정하려면 이 도구를 쓰세요.

관련 개념

URL의 쿼리 문자열은 `?` 뒤부터 `#` 앞까지를 가리키며, RFC 3986 §3.4는 이를 불투명한 바이트열로 정의합니다. "`&`로 구분된 키·값 쌍"이라는 관례는 URI 명세가 아니라 HTML 폼 전송과 `application/x-www-form-urlencoded` 미디어 타입에서 유래합니다. 대부분의 서버와 브라우저가 폼 형식을 기본으로 채택하지만 URI 명세는 이를 요구하지 않습니다. 모든 프레임워크가 미묘하게 동작이 다른 자체 쿼리 파서를 계속 동봉하는 이유가 이것입니다.

큰 흔들림은 **공백 인코드**입니다. form-urlencoded는 `+`를, RFC 3986 퍼센트 인코드는 `%20`을 씁니다. `URLSearchParams.toString()`은 `+`를 뱉고, WHATWG URL Standard는 이를 필수로 두며, 대부분의 브라우저가 이를 따릅니다. `encodeURIComponent`는 `%20`을 뱉습니다. 수신 측은 보통 둘 다 허용하고, 송신 측이 어느 쪽을 고릅니다. 요청 서명 시에는 주의가 필요합니다. AWS Signature v4는 `%20`을, OAuth 1.0a도 `%20`을 요구하므로 `+`를 뱉으면 서명 검증이 조용히 실패합니다.

쿼리 문자열 주변에는 인접한 4가지 개념이 있습니다. **해시 프래그먼트**(`#…`)는 서버로 전송되지 않습니다. 브라우저 안에만 존재하며 싱글 페이지 앱의 클라이언트 라우팅에 쓰입니다. 헷갈리게도 옛 코드 중에는 프래그먼트 안에서 쿼리 파라미터를 빼내는 것도 있습니다(`#?a=1`). **폼 인코드**(`application/x-www-form-urlencoded`의 POST 바디)는 쿼리 문자열과 같은 구문이고 자리만 바디로 옮긴 것입니다. 같은 파서가 둘 다 처리합니다. **쿠키 파싱**은 완전히 다른 규칙(구분자는 `;`, 기본적으로 퍼센트 인코드 없음)입니다. **JSON 요청 바디**는 2010년경부터 다수의 POST·PUT API에서 쿼리 문자열을 대체했지만, GET에서는 북마크 가능·캐시 가능·복사 붙여넣기 가능이라는 성질이 작용해 여전히 쿼리 문자열이 주류로 남았습니다.

관련 도구