쿼리 문자열

**쿼리 문자열** 또는 **쿼리 스트링**(Query string)은 특정 매개변수에 값을 할당하는 균일 자원 지시자의 일부이다. 쿼리 문자열은 일반적으로 웹 브라우저나 다른 클라이언트 애플리케이션이 HTML 문서의 일부로, 페이지의 모양을 선택하거나 멀티미디어 콘텐츠 내의 위치로 이동하는 등의 목적으로 기본 URL에 추가하는 필드를 포함한다.

[frame|center|[구글 크롬의 주소창에 쿼리 문자열 `?title=Query_string&action=edit`이 포함된 URL이 표시되어 있다.]]

웹 서버는 URL 경로를 기반으로 파일 시스템에서 파일을 읽거나 리소스 유형에 특정한 로직을 사용하여 하이퍼텍스트 전송 프로토콜 (HTTP) 요청을 처리할 수 있다. 특수 로직이 호출되는 경우, 쿼리 문자열은 URL의 경로 구성 요소와 함께 해당 로직에서 처리하는 데 사용할 수 있다.

## 구조
쿼리 문자열을 포함하는 일반적인 URL은 다음과 같다.

서버가 이러한 페이지에 대한 요청을 받으면, 쿼리 문자열(이 경우 `name=ferret`)을 프로그램에 변경 없이 전달하면서 프로그램을 실행할 수 있다. 물음표는 구분자로 사용되며, 쿼리 문자열의 일부가 아니다.

웹 프레임워크는 특정 구분자로 구분된 쿼리 문자열의 여러 매개변수를 파싱하는 메서드를 제공할 수 있다. 아래 예시 URL에서 여러 쿼리 매개변수는 앰퍼샌드인 "`&amp;`"로 구분된다.

쿼리 문자열의 정확한 구조는 표준화되어 있지 않다. 쿼리 문자열을 파싱하는 데 사용되는 메서드는 웹사이트마다 다를 수 있다.

웹 페이지의 링크에는 쿼리 문자열을 포함하는 URL이 있을 수 있다. HTML은 사용자 에이전트가 쿼리 문자열을 생성하는 세 가지 방법을 정의한다.
*  요소를 통한 HTML 폼
*  요소에  속성과  구조를 사용하는 서버 측 이미지 맵
* 현재는 사용되지 않는  요소를 통한 인덱스 검색

### 웹 폼
원래 사용 목적 중 하나는 웹 폼이라고도 알려진 HTML 폼의 내용을 담는 것이었다. 특히, `field1`, `field2`, `field3` 필드를 포함하는 폼이 제출될 때, 필드의 내용은 다음과 같이 쿼리 문자열로 인코딩된다.

* 쿼리 문자열은 일련의 필드-값 쌍으로 구성된다.
* 각 쌍 내에서 필드 이름과 값은 등호 "`=`"로 구분된다.
* 쌍의 연속은 앰퍼샌드 "`&amp;`"로 구분된다 (쌍반점 "`;`"은 더 이상 W3C에서 권장되지 않는다. 아래 참조).

명확한 표준은 없지만, 대부분의 웹 프레임워크는 단일 필드에 여러 값을 연결할 수 있도록 허용한다(예: `field1=value1&field1=value2&field2=value3`).

폼의 각 필드에 대해 쿼리 문자열은 `<var>필드</var>=<var>값</var>` 쌍을 포함한다. 웹 폼에는 사용자에게 보이지 않는 필드가 포함될 수 있으며, 이러한 필드는 폼이 제출될 때 쿼리 문자열에 포함된다.

이 규칙은 W3C 권장 사항이다. 1999년 권장 사항에서 W3C는 모든 웹 서버가 앰퍼샌드 외에 쌍반점 구분자를 지원할 것을 권장했다. 이는 HTML 문서 내의 URL에서 앰퍼샌드를 이스케이프할 필요 없이 application/x-www-form-urlencoded 쿼리 문자열을 허용하기 위함이었다. 2014년부터 W3C는 쿼리 구분자로 앰퍼샌드만 사용할 것을 권장한다.

폼 콘텐츠는 폼 제출 방식이 GET일 때만 URL의 쿼리 문자열로 인코딩된다. 제출 방식이 POST일 때도 기본적으로 동일한 인코딩이 사용되지만, 결과는 수정된 URL에 포함되는 대신 HTTP 요청 본문으로 제출된다.

### 인덱스 검색
HTML 폼이 HTML에 추가되기 전에는 브라우저가 – 요소를 단일 행 텍스트 입력 컨트롤로 렌더링했다. 이 컨트롤에 입력된 텍스트는 기본 URL 또는  속성으로 지정된 다른 URL에 대한 GET 요청에 쿼리 문자열로 추가되어 서버로 전송되었다. 이는 웹 서버가 제공된 텍스트를 쿼리 기준으로 사용하여 일치하는 페이지 목록을 반환할 수 있도록 하기 위함이었다.

인덱스 검색 컨트롤에 입력된 텍스트가 제출되면 다음과 같이 쿼리 문자열로 인코딩된다.

* 쿼리 문자열은 텍스트를 공백으로 파싱하여 일련의 인수로 구성된다.
* 일련의 인수는 더하기 기호 '`+`'로 구분된다.

 요소는 더 이상 사용되지 않으며 대부분의 브라우저가 이를 지원하거나 렌더링하지 않지만, 인덱스 검색의 흔적은 여전히 남아 있다. 예를 들어, 이는 브라우저 URL 퍼센트 인코딩 내에서 더하기 기호 '`+`'를 특별히 처리하는 원인이다(현재 인덱스 검색이 폐기되면서 `%20`과 거의 중복된다). 또한 일부 CGI를 지원하는 웹 서버(예: 아파치 HTTP 서버)는 쿼리 문자열에 등호 '`=`'가 포함되어 있지 않으면 쿼리 문자열을 명령줄 인수로 처리한다(CGI 1.1 섹션 4.4에 따름). 일부 CGI 스크립트는 HTML에 포함된 URL에 대한 이러한 역사적인 동작에 여전히 의존하고 사용한다.

## URL 인코딩

일부 문자는 URL의 일부가 될 수 없으며(예: 공백), 일부 다른 문자는 URL에서 특별한 의미를 가진다. 예를 들어, 문자 `#`는 문서의 하위 섹션(또는 프래그먼트)을 추가로 지정하는 데 사용될 수 있다. HTML 폼에서 문자 `=`는 이름과 값을 구분하는 데 사용된다. URI 일반 구문은 이 문제를 해결하기 위해 URL 인코딩을 사용하는 반면, HTML 폼은 모든 그러한 문자에 퍼센트 인코딩을 적용하는 대신 일부 추가 대체를 수행한다. SPACE는 '`+`' 또는 "`%20`"으로 인코딩된다.

HTML 5는 "GET" 메서드로 HTML 폼을 웹 서버에 제출하기 위한 다음 변환을 지정한다. 다음은 알고리즘에 대한 간략한 요약이다.
* 올바른 문자셋으로 변환할 수 없는 문자는 HTML 숫자 문자 참조로 대체된다
* SPACE는 '`+`' 또는 '`%20`'으로 인코딩된다.
* 문자(`A`–`Z` 및 `a`–`z`), 숫자(`0`–`9`) 및 문자 '`~`', '`-`', '`.`', '`_`'는 그대로 유지된다.
* `+`는 %2B로 인코딩된다.
* 다른 모든 문자는 십육진법 표현인 `%HH`로 인코딩되며, 비 ASCII 문자는 먼저 UTF-8(또는 지정된 다른 인코딩)으로 인코딩된다.

틸데("`~`")에 해당하는 옥텟은 RFC3986에 따라 쿼리 문자열에서 허용되지만, HTML 폼에서는 "`%7E`"로 퍼센트 인코딩되어야 한다.

SPACE를 '`+`'로 인코딩하고 "그대로" 문자를 선택하는 것은 이 인코딩을 RFC 3986과 구별한다.

## 예시
HTML 페이지에 다음과 같이 폼이 포함되어 있다면:

```html
<form action="/cgi-bin/test.cgi" method="get">
  <input type="text" name="first" />
  <input type="text" name="second" />
  <input type="submit" />
</form>
```


사용자가 두 텍스트 상자에 "this is a field"와 "was it clear (already)?"라는 문자열을 입력하고 제출 버튼을 누르면, 프로그램 `test.cgi` (위 예시에서 `form` 요소의 `action` 속성으로 지정된 프로그램)는 다음 쿼리 문자열을 받게 된다.
`first=this+is+a+field&amp;second=was+it+clear+%28already%29%3F`.

폼이 서버에서 CGI 스크립트에 의해 처리되는 경우, 스크립트는 일반적으로 쿼리 문자열을 `QUERY_STRING`이라는 환경 변수로 받게 된다.

## 추적
쿼리 문자열을 받는 프로그램은 그 일부 또는 전체를 무시할 수 있다. 요청된 URL이 프로그램이 아닌 파일에 해당하면 전체 쿼리 문자열은 무시된다. 그러나 쿼리 문자열의 사용 여부와 관계없이 이를 포함한 전체 URL은 서버 로그 파일에 저장된다.

이러한 사실을 통해 쿼리 문자열은 HTTP 쿠키와 유사한 방식으로 사용자를 추적하는 데 사용될 수 있다. 이를 위해서는 사용자가 페이지를 다운로드할 때마다 고유 식별자를 선택하여 페이지에 포함된 모든 링크의 URL에 쿼리 문자열로 추가해야 한다. 사용자가 이 링크 중 하나를 따라가자마자 해당 URL이 서버에 요청된다. 이런 식으로 이 페이지의 다운로드는 이전 페이지와 연결된다.

예를 들어, 다음이 포함된 웹 페이지가 요청될 때:

```html
<a href="foo.html">see my page!</a>
 <a href="bar.html">mine is better</a>
```


`e0a72cb2a2c7`와 같은 고유한 문자열이 선택되고, 페이지는 다음과 같이 수정된다.

```html
<a href="foo.html?e0a72cb2a2c7">see my page!</a>
 <a href="bar.html?e0a72cb2a2c7">mine is better</a>
```


쿼리 문자열을 추가해도 페이지가 사용자에게 표시되는 방식은 변경되지 않는다. 예를 들어, 사용자가 첫 번째 링크를 따라가면 브라우저는 서버에 `foo.html?e0a72cb2a2c7` 페이지를 요청하고, 서버는 `?` 뒤의 내용을 무시하고 예상대로 `foo.html` 페이지를 보내면서 해당 링크에도 쿼리 문자열을 추가한다.

이런 식으로 이 사용자의 모든 후속 페이지 요청은 동일한 쿼리 문자열 `e0a72cb2a2c7`을 전달하여 이 모든 페이지가 동일한 사용자에 의해 조회되었음을 확인할 수 있다. 쿼리 문자열은 종종 웹 버그와 함께 사용된다.

추적에 사용되는 쿼리 문자열과 HTTP 쿠키의 주요 차이점은 다음과 같다.
# 쿼리 문자열은 URL의 일부이므로 사용자가 URL을 저장하거나 다른 사용자에게 보내면 포함된다. 쿠키는 브라우징 세션 간에 유지될 수 있지만, URL과 함께 저장되거나 전송되지 않는다.
# 사용자가 두 개(또는 그 이상)의 독립적인 경로를 통해 동일한 웹 서버에 도착하면 두 개의 다른 쿼리 문자열이 할당되는 반면, 저장된 쿠키는 동일하다.
# 사용자는 쿠키를 비활성화할 수 있으며, 이 경우 추적에 쿠키를 사용하는 것은 작동하지 않는다. 그러나 추적에 쿼리 문자열을 사용하는 것은 모든 상황에서 작동해야 한다.
# 페이지에 대한 다른 방문에서 전달된 다른 쿼리 문자열은 페이지가 브라우저(또는 프록시) 캐시에서 절대 제공되지 않아 웹 서버의 부하가 증가하고 사용자 경험이 느려진다는 것을 의미한다.

## 호환성 문제
HTTP 사양에 따르면:
요청 줄 길이에 대한 다양한 임시적인 제한이 실제로 발견된다. 모든 HTTP 발신자와 수신자는 최소한 8000 옥텟의 요청 줄 길이를 지원하는 것이 권장된다.

URL이 너무 길면 웹 서버는 414 Request-URI Too Long HTTP 상태 코드로 실패한다.

이러한 문제에 대한 일반적인 해결책은 GET 대신 POST를 사용하고 매개변수를 요청 본문에 저장하는 것이다. 요청 본문의 길이 제한은 일반적으로 URL 길이 제한보다 훨씬 높다. 예를 들어, POST 크기 제한은 기본적으로 IIS 4.0에서는 2MB이고 IIS 5.0에서는 128KB이다. Apache2에서는 `LimitRequestBody` 지시어를 사용하여 제한을 구성할 수 있으며, 이는 요청 본문에 허용되는 바이트 수를 0(무제한 의미)에서 2147483647(2GB)까지 지정한다.

## 같이 보기

* 간편 URL
* 클릭 식별자
* 공용 게이트웨이 인터페이스 (CGI)
* HTTP 쿠키
* 하이퍼텍스트 전송 프로토콜 (HTTP)
* 시맨틱 URL
* URI 프래그먼트
* URI 정규화
* URI 스키마
* UTM 매개변수
* 웹 버그

## 각주

분류:문자열
분류:URL