JavaScript URLSearchParams 사용하기
예제 기준 · JavaScript : 브라우저 내장 URLSearchParams·URL API (별도 라이브러리 없음)
URLSearchParams는 URL의 query string을 key/value 항목으로 읽고 수정하는 API입니다. 값 조회, 같은 key의 여러 값, 추가·변경·삭제, query string 생성, URL 객체와 함께 사용하는 방법을 살펴보겠습니다.
각 절의 코드는 해당 예제의 HTML 요소가 만들어진 뒤 독립적으로 사용합니다. 버튼을 누른 결과는 pre#result에 표시합니다.
query parameter 읽기
new URLSearchParams(...)에 query string을 전달합니다. 맨 앞의 ?는 있어도 됩니다. get()은 첫 번째 값을 문자열로 반환하고, 해당 key가 없으면 null을 반환합니다. has()는 key 존재 여부를 boolean으로 알려 줍니다.
입력란 #query의 초기값은 ?name=Apple&count=2입니다. ‘query 읽기’ 버튼 #read를 누르면 name 값과 존재 여부, 없는 key인 missing의 값을 확인합니다.
function show(value) {
document.getElementById('result').textContent = String(value);
}
document.getElementById('read').addEventListener('click', function () {
const params = new URLSearchParams(document.getElementById('query').value);
show('name: ' + JSON.stringify(params.get('name')) + '\nhas(name): ' + params.has('name')
+ '\nmissing: ' + JSON.stringify(params.get('missing')));
});
초기 입력값으로 버튼을 눌렀을 때의 출력입니다. 문자열과 null을 구분하기 위해 JSON.stringify()를 사용합니다.
name: "Apple"
has(name): true
missing: null
name=처럼 key는 있고 값만 비어 있으면 get('name')은 빈 문자열, has('name')은 true입니다. 숫자처럼 보이는 값도 문자열이므로 get('count')는 "2"를 반환합니다.
현재 페이지의 query parameter는 window.location.search를 그대로 전달해 읽습니다. 다음 코드는 입력란 대신 현재 주소를 사용하는 별도 예제입니다.
const params = new URLSearchParams(window.location.search);
const name = params.get('name');
const hasName = params.has('name');
console.log(name);
console.log(hasName);
URLSearchParams는 path나 hash를 분리하는 API가 아닙니다. 전체 URL을 생성자에 넣지 말고 query string만 전달하거나, 뒤에서 설명할 URL 객체의 searchParams를 사용합니다.
같은 key의 여러 값 읽기
query string에는 같은 key가 여러 번 나올 수 있습니다. get()은 첫 번째 값 하나만, getAll()은 같은 key의 모든 값을 순서대로 담은 배열을 반환합니다.
입력란 #query의 초기값은 fruit=apple&fruit=banana입니다. ‘값 비교’ 버튼 #read로 두 결과를 비교합니다.
function show(value) {
document.getElementById('result').textContent = String(value);
}
document.getElementById('read').addEventListener('click', function () {
const params = new URLSearchParams(document.getElementById('query').value);
show('get: ' + JSON.stringify(params.get('fruit'))
+ '\ngetAll: ' + JSON.stringify(params.getAll('fruit')));
});
get: "apple"
getAll: ["apple","banana"]
fruit 항목을 모두 지우면 get('fruit')는 null, getAll('fruit')은 빈 배열 []을 반환합니다. 여러 선택값을 전달하는 query string에서는 getAll()로 전체 값을 읽습니다.
parameter 추가·변경·삭제
set()은 해당 key의 값을 설정하며, 같은 key가 여러 개면 하나만 남깁니다. key가 없으면 새로 만듭니다. append()는 기존 값을 유지하고 새 항목을 끝에 추가합니다. delete(key)는 해당 key의 모든 항목을 제거합니다.
초기 상태는 fruit=apple&count=1입니다. ‘fruit를 orange로 설정’ #set, ‘banana 추가’ #append, ‘fruit 삭제’ #delete, ‘초기화’ #reset 버튼으로 같은 객체의 상태를 변경합니다.
function show(value) {
document.getElementById('result').textContent = String(value);
}
let params = new URLSearchParams('fruit=apple&count=1');
function updateState() {
show(params.toString());
}
document.getElementById('set').addEventListener('click', function () {
params.set('fruit', 'orange');
updateState();
});
document.getElementById('append').addEventListener('click', function () {
params.append('fruit', 'banana');
updateState();
});
document.getElementById('delete').addEventListener('click', function () {
params.delete('fruit');
updateState();
});
document.getElementById('reset').addEventListener('click', function () {
params = new URLSearchParams('fruit=apple&count=1');
updateState();
});
updateState();
다음 순서로 누르면 set()과 append()의 차이가 드러납니다. count는 그대로 유지됩니다.
| 동작 | toString() 결과 |
|---|---|
| 처음 또는 초기화 | fruit=apple&count=1 |
| banana 추가 | fruit=apple&count=1&fruit=banana |
| fruit를 orange로 설정 | fruit=orange&count=1 |
| fruit 삭제 | count=1 |
toString()은 현재 항목들을 query string으로 만듭니다. 결과 앞에 ?는 포함되지 않으며, 항목이 하나도 없으면 빈 문자열을 반환합니다.
query string 만들기
객체의 속성을 key/value로 전달하거나, [key, value] 쌍의 배열로 URLSearchParams를 만들 수 있습니다. 같은 key를 반복하려면 쌍의 배열을 사용하면 됩니다.
검색어 입력란 #keyword의 초기값은 Apple & Banana입니다. ‘query 생성’ 버튼 #create는 객체로 만든 q·page와 쌍의 배열로 만든 q·tag·tag를 각각 출력합니다.
function show(value) {
document.getElementById('result').textContent = String(value);
}
document.getElementById('create').addEventListener('click', function () {
const keyword = document.getElementById('keyword').value;
const fromObject = new URLSearchParams({
q: keyword,
page: '1'
});
const fromPairs = new URLSearchParams([
['q', keyword],
['tag', 'one'],
['tag', 'two']
]);
show('객체: ' + fromObject.toString() + '\n쌍: ' + fromPairs.toString());
});
객체: q=Apple+%26+Banana&page=1
쌍: q=Apple+%26+Banana&tag=one&tag=two
toString()은 application/x-www-form-urlencoded 규칙에 따라 인코딩합니다. 위 검색어의 공백은 +, 값 안의 &는 %26으로 바뀝니다. 한글 등도 percent-encoding되어 query string에 들어갑니다.
값을 직접 이어 붙이면 검색어 안의 &가 parameter 구분자로 해석될 수 있습니다. 객체나 set()·append()에는 인코딩하지 않은 원래 값을 전달합니다. 미리 encodeURIComponent()를 적용한 값을 다시 넣으면 %가 재인코딩될 수 있습니다.
URL 객체와 함께 사용하기
전체 주소를 다룰 때는 new URL()로 URL 객체를 만들고 url.searchParams로 query parameter를 수정합니다. path는 url.pathname, hash는 url.hash로 구분할 수 있습니다.
검색어 입력란 #keyword의 초기값은 Test입니다. ‘결과 URL 생성’ 버튼 #create를 누르면 현재 주소를 복사한 URL 객체에서 q를 설정하고 현재 주소와 결과 주소를 함께 표시합니다.
function show(value) {
document.getElementById('result').textContent = String(value);
}
document.getElementById('create').addEventListener('click', function () {
const url = new URL(window.location.href);
url.searchParams.set('q', document.getElementById('keyword').value);
show('현재: ' + window.location.href + '\n결과: ' + url.href);
});
아래 예제는 iframe 안에서 실행되므로 ‘현재’에 표시되는 주소는 이 블로그 글이 아닌 실행 예제의 주소입니다. query나 hash 없이 아래 경로로 열었을 때 초기 검색어를 사용하면 다음 문자열이 만들어집니다.
현재: https://playground.objlab.co.kr/javascript/url-search-params/url/
결과: https://playground.objlab.co.kr/javascript/url-search-params/url/?q=Test
실제 출력은 실행 예제를 연 주소를 기준으로 달라집니다. 기존 query가 있으면 q를 추가하거나 바꾸며, 다른 key와 path·hash는 유지합니다. searchParams를 수정하면 query의 인코딩 표현은 다시 직렬화될 수 있습니다.
url.href는 변경된 전체 URL 문자열입니다. 이 코드는 URL 객체만 수정하고 window.location에 값을 대입하지 않으므로 주소창 변경이나 실제 페이지 이동은 발생하지 않습니다.
주요 메서드 정리
| 메서드 | 역할 |
|---|---|
get(key) |
첫 번째 값 하나. key가 없으면 null |
getAll(key) |
해당 key의 모든 값 배열. key가 없으면 빈 배열 |
has(key) |
key 존재 여부를 true 또는 false로 반환 |
set(key, value) |
값 설정. 기존 동일 key 항목을 하나로 정리 |
append(key, value) |
기존 항목을 유지하고 새 항목 추가 |
delete(key) |
해당 key의 모든 항목 제거 |
toString() |
? 없이 인코딩된 query string 생성 |
URLSearchParams를 사용하면 구분자와 값의 인코딩을 직접 조합하지 않고 query parameter를 읽고 수정할 수 있습니다. 전체 URL에서 특정 parameter만 바꿀 때는 URL 객체의 searchParams를 사용하면 path·hash와 구분해서 다루기 쉽습니다.
