일반적인 패턴 일치 사용 사례를 표준화하는 접근 방식입니다.
배경
라우팅은 모든 웹 애플리케이션의 핵심 요소입니다. 라우팅의 핵심은 URL을 가져와서 패턴 일치 또는 기타 앱별 로직을 적용한 후 일반적으로 결과를 기반으로 웹 콘텐츠를 표시하는 것입니다. 라우팅은 여러 가지 방법으로 구현할 수 있습니다. 디스크의 파일에 경로를 매핑하는 서버에서 실행되는 코드일 수도 있고, 현재 위치의 변경사항을 기다렸다가 표시할 상응하는 DOM 조각을 만드는 단일 페이지 앱의 로직일 수도 있습니다.
확실한 표준은 없지만 웹 개발자는 regular expressions
와 많은 공통점을 공유하지만 경로 세그먼트 일치용 토큰과 같은 일부 도메인별 추가 항목이 있는 URL 라우팅 패턴을 표현하기 위한 공통 문법을 선호했습니다.
Express 및 Ruby on Rails와 같은 인기 있는 서버 측 프레임워크는 이 문법 (또는 이와 매우 유사한 문법)을 사용하며 JavaScript 개발자는 path-to-regexp
또는 regexpparam
와 같은 모듈을 사용하여 자체 코드에 로직을 추가할 수 있습니다.
URLPattern
는 이러한 프레임워크에서 만든 기반을 기반으로 빌드되는 웹 플랫폼에 추가된 기능입니다. 와일드 카드, 이름이 지정된 토큰 그룹, 정규 표현식 그룹, 그룹 수정자를 지원하는 등 라우팅 패턴 문법을 표준화하는 것이 목표입니다. 이 문법으로 만든 URLPattern
인스턴스는 전체 URL 또는 URL pathname
과 일치시키고 토큰 및 그룹 일치에 관한 정보를 반환하는 것과 같은 일반적인 라우팅 작업을 실행할 수 있습니다.
웹 플랫폼에서 URL 일치를 직접 제공하면 URL과 일치시켜야 하는 다른 API와 공통 문법을 공유할 수 있다는 또 다른 이점이 있습니다.
브라우저 지원 및 폴리필
URLPattern
는 Chrome 및 Edge 버전 95 이상에서 기본적으로 사용 설정됩니다.
urlpattern-polyfill
라이브러리는 기본 제공 지원이 없는 브라우저 또는 Node와 같은 환경에서 URLPattern
인터페이스를 사용하는 방법을 제공합니다. 폴리필을 사용하는 경우 기능 감지를 사용하여 현재 환경에서 지원되지 않는 경우에만 폴리필을 로드해야 합니다. 그러지 않으면 URLPattern
의 주요 이점 중 하나인 지원 환경에서 이를 사용하기 위해 추가 코드를 다운로드하고 파싱할 필요가 없다는 이점을 놓치게 됩니다.
if (!(globalThis && 'URLPattern' in globalThis)) {
// URLPattern is not available, so the polyfill is needed.
}
구문 호환성
URLPattern
의 지침 철학은 재발명을 피하는 것입니다. Express 또는 Ruby on Rails에서 사용되는 라우팅 문법에 이미 익숙하다면 새로 배울 필요가 없습니다. 그러나 널리 사용되는 라우팅 라이브러리의 문법 간에 약간의 차이가 있으므로 기본 문법으로 선택할 항목이 필요했고 URLPattern
의 설계자는 path-to-regexp
의 패턴 문법 (API 노출 영역은 아님)을 출발점으로 사용하기로 결정했습니다.
이 결정은 path-to-regexp
의 현재 유지관리자와 긴밀히 협의한 후 내려졌습니다.
지원되는 문법의 핵심을 숙지하는 가장 좋은 방법은 path-to-regexp
의 문서를 참고하는 것입니다. MDN에 게시할 문서를 읽을 수 있습니다. 현재 GitHub의 홈에서 확인할 수 있습니다.
추가 기능
URLPattern
의 문법은 path-to-regexp
가 지원하는 문법의 상위 집합입니다. URLPattern
는 라우팅 라이브러리 간에 흔하지 않은 기능인 호스트 이름의 와일드 카드를 포함한 출처 일치를 지원하기 때문입니다. 다른 대부분의 라우팅 라이브러리는 pathname만 처리하고 경우에 따라 URL의 검색 또는 해시 부분을 처리합니다. 자체 포함 웹 앱 내에서 동일 출처 라우팅에만 사용되므로 URL의 출처 부분을 확인할 필요가 없습니다.
출처를 고려하면 서비스 워커의 fetch
이벤트 핸들러 내에서 교차 출처 요청을 라우팅하는 것과 같은 추가 사용 사례를 사용할 수 있습니다. 동일한 출처 URL만 라우팅하는 경우 이 추가 기능을 무시하고 다른 라이브러리처럼 URLPattern
를 사용할 수 있습니다.
예
패턴 구성
URLPattern
를 만들려면 생성자에 문자열 또는 일치할 패턴에 관한 정보가 속성에 포함된 객체를 전달합니다.
객체를 전달하면 각 URL 구성요소를 일치시키는 데 사용할 패턴을 가장 명시적으로 제어할 수 있습니다. 가장 상세한 경우 다음과 같이 표시될 수 있습니다.
const p = new URLPattern({
protocol: 'https',
username: '',
password: '',
hostname: 'example.com',
port: '',
pathname: '/foo/:image.jpg',
search: '*',
hash: '*',
});
속성에 빈 문자열을 제공하면 URL의 해당 부분이 설정되지 않은 경우에만 일치합니다. 와일드 카드 *
는 URL의 지정된 부분에 있는 모든 값과 일치합니다.
생성자는 더 간편하게 사용할 수 있는 여러 단축키를 제공합니다. search
및 hash
또는 기타 속성을 완전히 생략하면 '*'
와일드 카드로 설정하는 것과 같습니다. 위의 예는 다음과 같이 간소화할 수 있습니다.
const p = new URLPattern({
protocol: 'https',
username: '',
password: '',
hostname: 'example.com',
port: '',
pathname: '/foo/:image.jpg',
});
추가 단축키로 출처에 관한 모든 정보를 단일 속성 baseURL
에 제공할 수 있습니다.
const p = new URLPattern({
pathname: '/foo/:image.jpg',
baseURL: 'https://example.com',
});
이러한 모든 예시에서는 사용 사례에 출처 일치가 포함된다고 가정합니다. 출처를 제외한 URL의 다른 부분에만 일치시키는 데 관심이 있는 경우 (많은 '기존' 단일 출처 라우팅 시나리오의 경우와 같이) 출처 정보를 완전히 생략하고 pathname
, search
, hash
속성의 조합만 제공하면 됩니다. 이전과 마찬가지로 생략된 속성은 *
와일드 카드 패턴으로 설정된 것처럼 처리됩니다.
const p = new URLPattern({pathname: '/foo/:image.jpg'});
생성자에 객체를 전달하는 대신 문자열 1개 또는 2개를 제공할 수 있습니다. 문자열이 하나 제공된 경우 출처를 일치시키는 데 사용되는 패턴 정보를 포함하여 전체 URL 패턴을 나타내야 합니다. 문자열을 두 개 제공하면 두 번째 문자열이 baseURL
로 사용되고 첫 번째 문자열은 이 기준을 기준으로 간주됩니다.
문자열이 하나이든 두 개이든 URLPattern
생성자는 전체 URL 패턴을 파싱하여 URL 구성요소로 분할하고 더 큰 패턴의 각 부분을 해당 구성요소에 매핑합니다. 즉, 문자열로 만든 각 URLPattern
는 객체로 만든 상응하는 URLPattern
와 동일하게 표현됩니다. 문자열 생성자는 간결한 인터페이스를 선호하는 사용자를 위한 바로가기입니다.
const p = new URLPattern('https://example.com/foo/:image.jpg?*#*');
문자열을 사용하여 URLPattern
를 만들 때는 몇 가지 주의해야 할 사항이 있습니다.
객체를 사용하여 URLPattern
를 구성할 때 속성을 생략하면 해당 속성에 *
와일드 카드를 제공하는 것과 같습니다. 전체 URL 문자열 패턴이 파싱될 때 URL 구성요소 중 하나에 값이 누락된 경우 구성요소의 속성이 ''
로 설정된 것처럼 처리되며, 이는 구성요소가 비어 있을 때만 일치합니다.
문자열을 사용할 때 와일드 카드를 생성된 URLPattern
에서 사용하려면 와일드 카드를 명시적으로 포함해야 합니다.
// p1 and p2 are equivalent.
const p1 = new URLPattern('/foo', location.origin);
const p2 = new URLPattern({
protocol: location.protocol,
hostname: location.hostname,
pathname: '/foo',
search: '',
hash: '',
});
// p3 and p4 are equivalent.
const p3 = new URLPattern('/foo?*#*', location.origin);
const p4 = new URLPattern({
protocol: location.protocol,
hostname: location.hostname,
pathname: '/foo',
});
또한 문자열 패턴을 구성요소로 파싱하는 것은 모호할 수 있다는 점에 유의해야 합니다. :
와 같이 URL에 있지만 패턴 일치 문법에서도 특별한 의미를 갖는 문자가 있습니다. 이러한 모호성을 피하기 위해 URLPattern
생성자는 이러한 특수 문자가 URL이 아닌 패턴의 일부라고 가정합니다. 모호한 문자를 URL의 일부로 해석하려면 문자열로 제공할 때 \` character. For example, the literal URL
about:blankshould be escaped as
'about\:blank'` 로 이스케이프 처리해야 합니다.
패턴 사용
URLPattern
를 구성한 후에는 두 가지 옵션으로 사용할 수 있습니다. test()
및 exec()
메서드는 모두 동일한 입력을 사용하고 동일한 알고리즘을 사용하여 일치를 확인하며 반환 값만 다릅니다. test()
는 지정된 입력과 일치하는 경우 true
를 반환하고 일치하지 않는 경우에는 false
를 반환합니다.
exec()
는 캡처 그룹과 함께 일치에 관한 세부정보를 반환하거나 일치가 없는 경우 null
을 반환합니다. 다음 예에서는 exec()
를 사용하는 방법을 보여줍니다. 단순한 불리언 반환 값만 원하는 경우 test()
로 바꿀 수 있습니다.
test()
및 exec()
메서드를 사용하는 한 가지 방법은 문자열을 전달하는 것입니다.
생성자가 지원하는 것과 마찬가지로 단일 문자열이 제공되는 경우 원본을 포함한 전체 URL이어야 합니다. 두 문자열이 제공되면 두 번째 문자열은 baseURL
값으로 취급되고 첫 번째 문자열은 이 기준을 기준으로 평가됩니다.
const p = new URLPattern({
pathname: '/foo/:image.jpg',
baseURL: 'https://example.com',
});
const result = p.exec('https://example.com/foo/cat.jpg');
// result will contain info about the successful match.
// const result = p.exec('/foo/cat.jpg', 'https://example.com')
// is equivalent, using the baseURL syntax.
const noMatchResult = p.exec('https://example.com/bar');
// noMatchResult will be null.
또는 일치시키는 데 중요한 URL 부분으로만 설정된 속성을 사용하여 생성자가 지원하는 것과 동일한 종류의 객체를 전달할 수 있습니다.
const p = new URLPattern({pathname: '/foo/:image.jpg'});
const result = p.exec({pathname: '/foo/:image.jpg'});
// result will contain info about the successful match.
와일드 카드 또는 토큰이 포함된 URLPattern
에서 exec()
를 사용하면 반환 값에 입력 URL의 해당 값에 관한 정보가 제공됩니다. 이렇게 하면 이러한 값을 직접 파싱할 필요가 없습니다.
const p = new URLPattern({
hostname: ':subdomain.example.com',
pathname: '/*/:image.jpg'
});
const result = p.exec('https://imagecdn1.example.com/foo/cat.jpg');
// result.hostname.groups.subdomain will be 'imagecdn1'
// result.pathname.groups[0] will be 'foo', corresponding to *
// result.pathname.groups.image will be 'cat'
익명 그룹 및 이름이 지정된 그룹
URL 문자열을 exec()
에 전달하면 패턴의 모든 그룹과 일치하는 부분을 나타내는 값이 반환됩니다.
반환 값에는 pathname
와 같이 URLPattern
의 구성요소에 해당하는 속성이 있습니다. 따라서 그룹이 URLPattern
의 pathname
부분의 일부로 정의된 경우 일치는 반환 값의 pathname.groups
에서 찾을 수 있습니다. 일치는 해당 패턴이 익명 그룹인지 이름이 지정된 그룹인지에 따라 다르게 표시됩니다.
배열 색인을 사용하여 익명의 패턴 일치 값에 액세스할 수 있습니다.
익명의 패턴이 여러 개 있는 경우 색인 0
는 맨 왼쪽 패턴의 일치 값을 나타내고 1
및 후속 패턴에 사용되는 추가 색인은 다음 패턴에 사용됩니다.
패턴에 이름이 지정된 그룹을 사용하면 일치 항목이 각 그룹 이름에 해당하는 이름의 속성으로 노출됩니다.
유니코드 지원 및 정규화
URLPattern
는 여러 가지 방법으로 유니코드 문자를 지원합니다.
:café
와 같은 이름이 지정된 그룹에는 유니코드 문자가 포함될 수 있습니다. 유효한 JavaScript 식별자에 사용되는 규칙은 이름이 지정된 그룹에 적용됩니다.패턴 내 텍스트는 특정 구성요소의 URL 인코딩에 사용된 것과 동일한 규칙에 따라 자동으로 인코딩됩니다.
pathname
내의 유니코드 문자는 퍼센트 인코딩되므로/café
과 같은pathname
패턴은 자동으로/caf%C3%A9
로 정규화됩니다.hostname
의 유니코드 문자는 퍼센트 인코딩이 아닌 Punycode를 사용하여 자동으로 인코딩됩니다.정규 표현식 그룹에는 ASCII 문자만 포함해야 합니다. 정규 표현식 문법을 사용하면 이러한 그룹에서 유니코드 문자를 자동으로 인코딩하기가 어렵고 안전하지 않습니다. 정규 표현식 그룹에서 유니코드 문자를 일치시키려면
(caf%C3%A9)
를 사용하여café
와 일치시키는 것처럼 수동으로 퍼센트 인코딩해야 합니다.
URLPattern
는 유니코드 문자를 인코딩하는 것 외에도 URL 정규화를 실행합니다. 예를 들어 pathname
구성요소의 /foo/./bar
는 상응하는 /foo/bar
로 축소됩니다.
특정 입력 패턴이 어떻게 정규화되었는지 확실하지 않은 경우 브라우저의 DevTools를 사용하여 생성된 URLPattern
인스턴스를 검사합니다.
요약 정리
아래에 삽입된 Glitch 데모는 서비스 워커의 fetch event handler
내부에서 URLPattern
의 핵심 사용 사례를 보여줍니다. 이 데모에서는 특정 패턴을 네트워크 요청에 대한 응답을 생성할 수 있는 비동기 함수에 매핑합니다. 이 예시의 개념은 서버 측 또는 클라이언트 측의 다른 라우팅 시나리오에도 적용할 수 있습니다.
의견 및 향후 계획
URLPattern
의 기본 기능은 Chrome 및 Edge에 적용되었지만 추가 기능이 계획되어 있습니다. URLPattern
의 일부 측면은 아직 개발 중이며, 아직 세부적으로 조정될 수 있는 특정 동작에 관한 미해결 질문이 여러 개 있습니다. URLPattern
를 사용해 보고 GitHub 문제를 통해 의견을 보내주세요.
템플릿 지원
path-to-regexp
라이브러리는 라우팅 동작을 효과적으로 역전시킬 수 있는 compile() function
를 제공합니다. compile()
는 토큰 자리표시자의 패턴과 값을 사용하고 이러한 값이 대체된 URL 경로의 문자열을 반환합니다.
향후 URLPattern에 추가할 예정이지만 초기 출시의 범위에는 해당하지 않습니다.
향후 웹 플랫폼 기능 사용 설정
URLPattern
가 웹 플랫폼의 확립된 부분이 된다고 가정하면 라우팅이나 패턴 일치의 이점을 누릴 수 있는 다른 기능을 이를 기반으로 프리미티브로 빌드할 수 있습니다.
서비스 워커 범위 패턴 일치, 파일 핸들러로서의 PWA, 추측적 미리 가져오기와 같은 제안된 기능에 URLPattern
를 사용하는 것에 관한 논의가 진행 중입니다.
감사의 말씀
전체 저작자 표시는 원본 설명 문서를 참고하세요.