Custom Search Param Serialization
기본적으로, TanStack Router는 JSON.stringify
와 JSON.parse
를 사용하여 URL 검색 매개변수를 자동으로 구문 분석하고 직렬화합니다. 이 과정은 검색 문자열의 이스케이프 및 이스케이프 해제를 포함하며, 검색 객체를 직렬화하고 역직렬화하는 URL 검색 매개변수의 일반적인 관행입니다.
예를 들어, 기본 설정을 사용하여 다음과 같은 검색 객체가 있다면:
const search = {
page: 1,
sort: "asc",
filters: { author: "tanner", min_words: 800 },
};
다음과 같이 직렬화되고 이스케이프된 검색 문자열이 생성됩니다:
?page=1&sort=asc&filters=%7B%22author%22%3A%22tanner%22%2C%22min_words%22%3A800%7D
기본 동작은 다음과 같은 코드로 구현할 수 있습니다:
import {
createRouter,
parseSearchWith,
stringifySearchWith,
} from "@tanstack/react-router";
const router = createRouter({
// ...
parseSearch: parseSearchWith(JSON.parse),
stringifySearch: stringifySearchWith(JSON.stringify),
});
그러나 이 기본 동작이 모든 사용 사례에 적합하지 않을 수 있습니다. 예를 들어, base64 인코딩과 같은 다른 직렬화 형식을 사용하거나, query-string (opens in a new tab), JSURL2 (opens in a new tab), 또는 Zipson (opens in a new tab)과 같은 특수 제작된 직렬화/역직렬화 라이브러리를 사용하고 싶을 수 있습니다.
이러한 경우, Router
구성의 parseSearch
및 stringifySearch
옵션에 사용자 정의 직렬화 및 역직렬화 함수를 제공하여 구현할 수 있습니다. 이때, TanStack Router의 내장 헬퍼 함수인 parseSearchWith
와 stringifySearchWith
를 사용하면 프로세스를 간소화할 수 있습니다.
[!TIP] 직렬화와 역직렬화에서 중요한 점은 역직렬화 후 동일한 객체를 반환할 수 있어야 한다는 것입니다. 만약 직렬화와 역직렬화 과정이 제대로 이루어지지 않으면 일부 정보가 손실될 수 있습니다. 예를 들어, 중첩 객체를 지원하지 않는 라이브러리를 사용하는 경우, 역직렬화 시 중첩 객체가 손실될 수 있습니다.
다음은 TanStack Router에서 검색 매개변수 직렬화를 사용자 정의하는 방법에 대한 몇 가지 예제입니다:
Using Base64
검색 매개변수를 base64로 인코딩하여 브라우저와 URL 확장기 등의 호환성을 극대화하는 것이 일반적입니다. 다음 코드로 구현할 수 있습니다:
import {
Router,
parseSearchWith,
stringifySearchWith,
} from "@tanstack/react-router";
const router = createRouter({
parseSearch: parseSearchWith((value) => JSON.parse(decodeFromBinary(value))),
stringifySearch: stringifySearchWith((value) =>
encodeToBinary(JSON.stringify(value))
),
});
function decodeFromBinary(str: string): string {
return decodeURIComponent(
Array.prototype.map
.call(atob(str), function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
})
.join("")
);
}
function encodeToBinary(str: string): string {
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode(parseInt(p1, 16));
})
);
}
이 구성으로 이전 객체를 검색 문자열로 변환하면 다음과 같이 나타납니다:
?page=1&sort=asc&filters=eyJhdXRob3IiOiJ0YW5uZXIiLCJtaW5fd29yZHMiOjgwMH0%3D
Using the query-string library
query-string (opens in a new tab) 라이브러리는 쿼리 문자열을 신뢰성 있게 구문 분석하고 문자열화하는 데 인기 있는 라이브러리입니다. 이를 사용하여 검색 매개변수의 직렬화 형식을 사용자 정의할 수 있습니다:
import { createRouter } from "@tanstack/react-router";
import qs from "query-string";
const router = createRouter({
// ...
stringifySearch: stringifySearchWith((value) =>
qs.stringify(value, {
// ...options
})
),
parseSearch: parseSearchWith((value) =>
qs.parse(value, {
// ...options
})
),
});
이 구성으로 이전 객체를 검색 문자열로 변환하면 다음과 같이 나타납니다:
?page=1&sort=asc&filters=author%3Dtanner%26min_words%3D800
Using the JSURL2 library
JSURL2 (opens in a new tab)는 URL을 읽기 쉽게 유지하면서도 압축할 수 있는 비표준 라이브러리입니다:
import {
Router,
parseSearchWith,
stringifySearchWith,
} from "@tanstack/react-router";
import { parse, stringify } from "jsurl2";
const router = createRouter({
// ...
parseSearch: parseSearchWith(parse),
stringifySearch: stringifySearchWith(stringify),
});
이 구성으로 이전 객체를 검색 문자열로 변환하면 다음과 같이 나타납니다:
?page=1&sort=asc&filters=(author~tanner~min*_words~800)~
Using the Zipson library
Zipson (opens in a new tab)은 매우 사용자 친화적이고 런타임 성능과 압축 성능 모두에서 뛰어난 JSON 압축 라이브러리입니다. 다음 코드를 사용하여 검색 매개변수를 압축할 수 있습니다:
import {
Router,
parseSearchWith,
stringifySearchWith,
} from "@tanstack/react-router";
import { stringify, parse } from "zipson";
const router = createRouter({
parseSearch: parseSearchWith((value) => parse(decodeFromBinary(value))),
stringifySearch: stringifySearchWith((value) =>
encodeToBinary(stringify(value))
),
});
function decodeFromBinary(str: string): string {
return decodeURIComponent(
Array.prototype.map
.call(atob(str), function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
})
.join("")
);
}
function encodeToBinary(str: string): string {
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode(parseInt(p1, 16));
})
);
}
이 구성으로 이전 객체를 검색 문자열로 변환하면 다음과 같이 나타납니다:
?page=1&sort=asc&filters=JTdCJUMyJUE4YXV0aG9yJUMyJUE4JUMyJUE4dGFubmVyJUMyJUE4JUMyJUE4bWluX3dvcmRzJUMyJUE4JUMyJUEyQ3UlN0Q%3D
Safe Binary Encoding/Decoding
브라우저에서 atob
및 btoa
함수는 비-UTF8 문자를 제대로 처리하지 못할 수 있습니다. 아래의 인코딩/디코딩 유틸리티를 사용하는 것을 권장합니다:
문자열을 이진 문자열로 인코딩하려면:
export function encodeToBinary(str: string): string {
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode(parseInt(p1, 16));
})
);
}
이진 문자열을 문자열로 디코딩하려면:
export function decodeFromBinary(str: string): string {
return decodeURIComponent(
Array.prototype.map
.call(atob(str), function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
})
.join("")
);
}