둘다 모두 js에서 url 링크를 다룰 때 기본적으로 제공되어 사용하는 web api이다. 용도와 역할이 비슷하지만 다른 이 두가지에 대해 알아보자.
const url = new URL("https://example.com/page?search=apple&sort=asc");
console.log(url.protocol); // "https:"
console.log(url.hostname); // "example.com"
console.log(url.pathname); // "/page"
console.log(url.search); // "?search=apple&sort=asc"
console.log(url.hash); // ""
참고로, url.toString() 과 url.href 는 같은 값을 반환한다. 전자는 읽기 전용이고 후자는 읽고 쓰기가 가능하다는 차이가 있다.
const base = new URL("https://api.example.com/");
base.pathname += "products/1234";
base.searchParams.set("lang", "ko");
console.log(base.toString()); // "https://api.example.com/products/1234?lang=ko"
window.location.origin이 없는 환경에서 절대 경로 생성const absoluteUrl = new URL("/images/logo.png", "https://example.com/");
console.log(absoluteUrl.href); // "https://example.com/images/logo.png"
const currentUrl = new URL(window.location.href);
console.log(currentUrl.pathname); // 예: "/products"
?key=value 구조의 문자열을 다루는데 특화되어있음const params = new URLSearchParams("?search=baguette&sort=asc");
params.set("sort", "desc");
params.append("tag", "new");
params.delete("search");
console.log(params.toString()); // "sort=desc&tag=new"
// 객체 형태로도 생성 가능
const params = new URLSearchParams({
mode: 'dark',
page: '1',
draft: 'false',
sort: 'email',
})
params.append('sort', 'date') // email은 date로 변경됨
console.log(params.toString()) // mode=dark&page=1&draft=false&sort=email&sort=date
const params = new URLSearchParams("a=1&a=2&b=3");
for (const [key, value] of params) {
console.log(key, value);
}
// a 1
// a 2
// b 3
const objectToSearchParams = (obj: Record<string, any>) {
return new URLSearchParams(obj).toString();
}
const searchParamsToObject = (search: string) => {
const params = new URLSearchParams(search);
return Object.fromEntries(params.entries());
}
console.log(objectToSearchParams({ page: 1, sort: "asc" }));
// "page=1&sort=asc"
console.log(searchParamsToObject("page=1&sort=asc"));
// { page: "1", sort: "asc" }
export const makeUrl = (path: string, query?: Record<string, string | number | undefined>) => {
const url = new URL(path, "https://api.example.com");
if (query) {
Object.entries(query).forEach(([k, v]) => {
if (v !== undefined) url.searchParams.set(k, String(v));
});
}
return url.toString();
};
console.log(makeUrl("/products", { category: "bread", page: 2 }));
// "https://api.example.com/products?category=bread&page=2"
append() 와 set() 의 차이append() 는 기존 파라미터 키에 새로운 값을 추가하며, set()은 기존 값을 지워버리고 새로운 값을 추가함const searchParams = new URLSearchParams();
searchParams.set("mode", "dark");
searchParams.set("page", 1);
searchParams.set("draft", false);
searchParams.set("sort", "email");
searchParams.set("sort", "date");
searchParams.toString(); // 'mode=dark&page=1&sort=date&draft=false'
기존의 URL의 쿼리 스트링을 접근하거나 조작하고 싶을 때는 URL 과 함께 URLSearchParams를 쓰면 유용하다. URL 객체의 search 속성에는 쿼리 스트링이 문자열로 저장되어 있고, searchParams 속성에는 쿼리 스트링이 URLSearchParams 객체로 저장이 되어 있다.
const url = new URL("https://example.com/pokemon/post?q=pitchu");
url.search; // '?q=pitchu'
url.searchParams; // URLSearchParams {size: 1}
url.searchParams.get("q"); // 'pitchu'
url.searchParams.set("q", "updated");
url.searchParams.append("r", 1);
url.searchParams.append("r", false);
url.toString(); // 'https://example.com/pokemon/post?q=updated&r=1&r=false'
const url = new URL("https://example.com/pokemon/post?q=pitchu");
url.searchParams = new URLSearchParams("q=updated&r=2&r=false");
url.toString(); // 'https://example.com/pokemon/post?q=pitch'
대신에 search 속성은 쓰기가 가능하기 때문에 아래와 같이 URLSearchParams 객체를 문자열로 변환한 후에 URL객체 search속성에 할당해주면 된다.
const url = new URL("https://example.com/pokemon/post?q=pitchu");
url.search = new URLSearchParams("q=updated&r=2&r=false").toString();
url.toString(); // 'https://example.com/pokemon/post?q=pitch'
요약하자면,
- URL - 전체 URL 다루기
- URLSearchParams - 쿼리 문자열만 다루기
- 전체 URL에서 도메인, 경로, 쿼리 등 다양한 부분을 파악해야할 때
URL을 사용하고, 쿼리 문자열만 빠르게 파싱하거나 조작하고 싶을 때는URLSearchParams를 사용하면 된다.