URLSearchParams 객체에 대해 알아보자! (feat. URL 객체)

DevSheryl·2022년 9월 1일
3

개발 상식 쌓기

목록 보기
3/11

Effitizer 프로젝트의 기존 코드를 보다가 new URLSearchParams라는 생소한 표현을 발견했다. 어딘가에서 import해 온 흔적이 보이지 않아서 구글에 검색해보니 주소창의 경로를 다룰 수 있는 브라우저의 내장 객체였다. URL 객체와 URLSearchParams를 비교한 제로초 님의 블로그 글과 공식 문서 MDN을 읽고 공부한 내용을 작성해본다.

개요

둘 다 IE에서는 동작하지 않고 모던 브라우저에서만 가능한 기능이라고 한다. (IE는 올해 6월부로 bye했으니..) 프론트엔드 개발자는 웹을 다루니 웹 주소를 자유자재로 조작할 줄 안다면 편리할 것이다. 또한 이렇게 내장된 객체들을 활용하면 queryString 파싱과 같은 귀찮은 작업을 처리하는 것도 편해진다.

URL 객체

new 키워드로 인스턴스를 생성하고 조작할 경로를 인자로 전달한다. URL 객체만의 내장 프로퍼티로 주소의 경로를 조작할 수 있다.

// new 키워드로 URL 객체 생성
const url = new URL('https://www.zerocho.com:8080/category/HTML?hi=yena');

// 여러 프로퍼티로 주소의 일부 구성요소 조회하기
url.href; // 전체 웹 주소 반환 (https://www.zerocho.com:8080/category/HTML)
url.origin; // protocol에서 port까지 반환 (https://www.zerocho.com:8080)
url.protocol; // http:인지 https:인지 반환 (https:)

url.host; // www.부터 port까지 반환 (www.zerocho.com:8080)
url.hostname; // host에서 port만 빼고 반환 (www.zerocho.com)
url.port; // port 번호 반환 (8080)

url.pathname; // 상대경로 반환 (/category/HTML)
url.search; // '?'부터 hash('#')를 제외하고 반환 (?hi=yena)

url.searchParams; // (X) 위에처럼 조회가 안 됨 => *메서드로 조작하는 프로퍼티 (하단 참고!)

구성 방식: WHATWG

URL 객체는 다음과 같은 WHATWG 방식으로 구성된다.
(다시 보니 '주소'가 이 방식으로 구성되어 있다고 보는 게 맞겠다)
(두 개의 origin 칸은 병합해서 하나의 origin 칸으로 보자)

상대경로 추가하기

  • 상대 경로는 URL 객체에서 직접 설정할 수 있다.
new URL('추가할 상대 경로', '기본 경로');
  • 추가할 상대경로 앞에 붙인 '.'은 기본 경로에 추가되면 사라진다.
const url2 = new URL('./category/HTML', 'https://www.zerocho.com');

url2.href; // 전체 경로 반환 (https://www.zerocho.com/category/HTML)

params 추가 또는 수정하기

  • params를 추가/수정하고 싶다면 URL의 프로퍼티에 직접 값을 할당하면 된다. (**searchParams 프로퍼티는 제외! - 바로 아래 참고)
url.search = '?hello=zerocho';

url.href; // 전체 경로 반환 (https://www.zerocho.com/category/HTML?hello=zerocho)

🍎 searchParams 프로퍼티 사용하기

  • URL 객체의 searchParams는 다른 프로퍼티와 달리, 직접 조회나 수정이 안 되고 메서드로 조작해야 하는 프로퍼티이다.
const url3 = new URL('https://www.zerocho.com?hello=zerocho&hi=yena&hi=js');

url3.search; // 조회 가능 - '?'부터 hash('#') 제외하고 반환 (?hello=zerocho&hi=yena&hi=js)
url3.searchParams; // (X) 불가능 - 출력하면 빈 객체({}) 반환
  • 주로 GET 요청 시 데이터를 전달할 때 사용한다.
  • 예시: 변경된 페이지를 주소에 반영할 때
    * 만약 ?page=1&limit=50이라는 주소가 있을 때 다음 페이지로 넘어가는 주소를 만들려면 ?page=2&limit=50으로 바꿔줘야 한다. 이때 searchParams 프로퍼티로 처리하면 편하다.

searchParams의 메서드 활용하기

searchParams는 메서드로 조작이 가능하다고 하였다. 여러 메서드를 활용하여 '?' 이하 경로의 조회/수정/삭제를 해보자. (참고: searchParams로 수정된 경로를 확인할 때는 기본 경로까지 모두 보여주는 url.href보다 '?'부터 보여주는 url.search가 더 편하다)

// 조회하기
url3.searchParams.get('hello'); // 특정 param 하나 조회 (zerocho)
url3.searchParams.getAll('hi'); // 특정 param의 여러 값을 모두 조회 (2개 이상일 경우 배열: ['yena', 'js'])

// 추가하기 (같은 키로 여러 값을 추가하는 것도 가능)
url3.searchParams.append('bye', 'java');
url3.search; // '?'부터 전체 반환 (?hello=zerocho&hi=yena&hi=js&bye=java)
url3.searchParams.append('bye', 'ruby');
url3.search; // 똑같은 'bye'로 한번 더 추가 (?hello=zerocho&hi=yena&hi=js&bye=java&bye=ruby)

// 수정하기 (set: 기본적으로 추가 역할, 기존 키가 있다면 전부 삭제하고 새로운 내용으로 교체)
url3.searchParams.set('bye', 'python');
url3.search; // 기존의 bye가 모두 사라지고 python 하나로 교체 (?hello=zerocho&hi=yena&hi=js&bye=python)

// 삭제하기
url3.searchParams.delete('bye');
url3.search; // 특정 키로 삭제 (?hello=zerocho&hi=yena&hi=js)

URLSearchParams 객체

  • URL 객체보다 URLSearchParams 객체의 활용도가 더 높다.
  • searchParams 부분만 단독으로 조작할 때 사용한다. (내장 메서드는 URL 객체의 searchParams와 동일)
const searchParams = new URLSearchParams('hello=zerocho&hi=yena&hi=js');

searchParams.set('bye', 'C#');

// URLSearchParams 객체로 만들어진 주소는 문자열로 변환해줘야 한다.
searchParams.toString(); // 문자열로 변환된 값 (hello=zerocho&hi=yena&hi=js&bye=C%23)

// 'C#'의 '#'이 '%23'으로 변경되었다.

MDN 예시

URL 객체와 URLSearchParams 객체 같이 쓰기

(feat. URLSearchParams에 인자를 전달하는 다양한 방법)

let url = new URL('https://example.com?foo=1&bar=2');

// url.search로 url 주소를 검색할 때
let params1 = new URLSearchParams(url.search);

// 문자열 리터럴 전달하기
let params2 = new URLSearchParams("foo=1&bar=2");
let params2a = new URLSearchParams("?foo=1&bar=2");

// 2차원 배열 전달하기
let params3 = new URLSearchParams([["foo", "1"], ["bar", "2"]]);

// 객체 전달하기
let params4 = new URLSearchParams({ "foo": "1", "bar": "2" });

여러 개의 params를 한번에 추가하기

// params로 추가할 내용을 객체로 선언 (값은 전부 문자열화)
const add_params = {
	c: 'a',
    d: new String(2),
    e: false.toString(),
};

// 기존 url 뒤에 새로운 params 추가
const new_params = new URLSearchParams([

      // url.searchParams의 entries(): 기존 url의 params를 각각 배열로 변환 	
      // Array.from 메서드로 하나의 배열로 만듦
      ...Array.from(url.searchParams.entries()), // [["a", "hello"], ["b", "world"]]

      // Object.entries(객체): 객체를 바로 2차원 배열로 반환
      ...Object.entries(add_params), // [["c", "a"], ["d", "2"], ["e", "false"]]
    
	]).toString(); // URLSearchParams 객체로 만들어진 값은 반드시 따로 문자열화 해줘야 한다!

// '&'로 연결된 새로운 params 반환
console.log(new_params); // a=hello&b=world&c=a&d=2&e=false

추가: 여러 개의 params를 한번에 추가하는 고차 함수

위의 내용을 고차 함수로 커스텀한 것이다. (출처: MDN)

// url에 params가 없을 때를 대비하여 params에 기본값으로 빈 객체 할당
const addSearchParams = (url, params = {}) => { 
	return (
    	new URL(
        	`${url.origin}$url.pathname}?
             ${new URLSearchParams([
              ...Array.from(url.searchParams.entries()),
              ...Object.entries(params),
          	 ])
             .toString()}`
        );
    );
}

참고 링크

URL과 URLSearchParams (제로초님 블로그)
URLSearchParams (MDN)

profile
2024 가보자고~!

0개의 댓글