웹 플랫폼으로 라우팅을 가져오는 URLPattern

공통 패턴 일치 사용 사례를 표준화하는 접근 방식

배경

라우팅은 모든 웹 애플리케이션의 핵심 요소입니다. 라우팅의 핵심은 URL을 가져와 일부 패턴 일치 또는 기타 앱별 로직을 이 URL에 적용한 다음, 일반적으로 결과를 기반으로 웹 콘텐츠를 표시하는 것입니다. 라우팅은 다양한 방법으로 구현할 수 있습니다. 디스크의 파일에 경로를 매핑하는 서버에서 실행되는 코드이거나 현재 위치의 변경사항을 대기하고 표시할 해당 DOM 조각을 만드는 단일 페이지 앱의 로직이 있을 수 있습니다.

하나의 확정적인 표준은 없지만 웹 개발자는 regular expressions와 많은 공통점을 공유하지만 경로 세그먼트 일치를 위한 토큰과 같은 일부 도메인별 추가 기능이 있는 URL 라우팅 패턴을 표현하기 위한 공통 구문에 매료되었습니다. ExpressRuby on Rails와 같은 널리 사용되는 서버 측 프레임워크는 이 구문 (또는 이와 매우 유사한 구문)을 사용하며, 자바스크립트 개발자는 path-to-regexp 또는 regexpparam와 같은 모듈을 사용하여 이 로직을 자체 코드에 추가할 수 있습니다.

URLPattern는 이러한 프레임워크로 만들어진 기반을 기반으로 하는 웹 플랫폼에 추가됩니다. 목표는 와일드 카드, 이름이 지정된 토큰 그룹, 정규 표현식 그룹, 그룹 수정자에 대한 지원을 비롯한 라우팅 패턴 구문을 표준화하는 것입니다. 이 구문으로 만든 URLPattern 인스턴스는 전체 URL 또는 URL pathname에 대한 일치 여부 확인, 토큰 및 그룹 일치 항목에 대한 정보 반환과 같은 일반적인 라우팅 작업을 수행할 수 있습니다.

웹 플랫폼에서 직접 URL 매칭을 제공하는 또 다른 이점은 공통 구문을 URL과도 일치해야 하는 다른 API와 공유할 수 있다는 것입니다.

브라우저 지원 및 폴리필

URLPattern는 Chrome 및 Edge 버전 95 이상에서 기본적으로 사용 설정됩니다.

urlpattern-polyfill 라이브러리는 기본 제공되는 지원이 없는 Node와 같은 브라우저나 환경에서 URLPattern 인터페이스를 사용하는 방법을 제공합니다. polyfill을 사용하는 경우 현재 환경에서 지원되지 않는 경우에만 기능 감지를 사용하여 로드하도록 해야 합니다. 그러지 않으면 URLPattern의 주요 이점 중 하나를 잃게 됩니다. 바로 지원 환경에서 코드를 사용하기 위해 추가 코드를 다운로드하고 파싱할 필요가 없다는 점입니다.

if (!(globalThis && 'URLPattern' in globalThis)) {
  // URLPattern is not available, so the polyfill is needed.
}

구문 호환성

URLPattern의 기본 철학은 재창조를 피하는 것입니다. Express 또는 Ruby on 레일즈에서 사용되는 라우팅 구문에 이미 익숙하다면 새로 배울 필요는 없습니다. 그러나 널리 사용되는 라우팅 라이브러리의 구문 간에 약간의 차이가 있으므로 기본 구문으로 무언가를 선택해야 했으며, URLPattern 디자이너는 path-to-regexp (API 노출 영역이 아님)의 패턴 구문을 시작점으로 사용하기로 했습니다.

이 결정은 path-to-regexp의 현재 유지관리 담당자와 긴밀히 협의한 후에 내려진 것입니다.

지원되는 구문의 핵심에 익숙해지는 가장 좋은 방법은 path-to-regexp 문서를 참조하세요. 현재 GitHub 홈에서 MDN에 게시하는 문서를 확인할 수 있습니다.

추가 기능

URLPattern 구문은 path-to-regexp가 지원하는 항목의 상위 집합입니다. URLPattern는 라우팅 라이브러리 중에서 출처와 일치하는 드문 기능(호스트 이름 내 와일드 카드 포함)을 지원하기 때문입니다. 대부분의 다른 라우팅 라이브러리는 경로 이름만 처리하며 경우에 따라 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의 지정된 부분의 모든 값과 일치합니다.

생성자는 더 간단한 사용을 위해 여러 단축키를 제공합니다. searchhash, 또는 다른 속성을 완전히 생략하는 것은 이를 '*' 와일드 카드로 설정하는 것과 같습니다. 위의 예는

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'});

객체를 생성자에 전달하는 대신 문자열 한 개 또는 두 개를 제공할 수 있습니다. 한 개의 문자열이 제공되면 출처와 일치하는 데 사용된 패턴 정보를 포함하여 전체 URL 패턴을 나타내야 합니다. 문자열 2개를 제공하면 두 번째 문자열이 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 URLabout: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의 구성요소에 상응하는 속성이 있습니다. 따라서 그룹이 URLPatternpathname 부분의 일부로 정의된 경우 반환 값의 pathname.groups에서 일치 항목을 찾을 수 있습니다. 해당 패턴이 익명 그룹인지 이름이 지정된 그룹인지에 따라 일치 항목을 다르게 표시합니다.

배열 색인을 사용하여 익명 패턴 일치 값에 액세스할 수 있습니다. 익명 패턴이 여러 개 있는 경우 색인 0는 가장 왼쪽에 있는 패턴과 일치하는 값을 나타내며 1과 후속 패턴에는 추가 색인이 사용됩니다.

이름이 지정된 그룹을 패턴에 사용하면 일치 항목이 각 그룹 이름에 해당하는 이름의 속성으로 노출됩니다.

유니코드 지원 및 정규화

URLPattern는 몇 가지 방법으로 유니코드 문자를 지원합니다.

  • :café과 같이 이름이 지정된 그룹에는 유니코드 문자가 포함될 수 있습니다. 유효한 JavaScript 식별자에 사용되는 규칙은 이름이 지정된 그룹에 적용됩니다.

  • 패턴 내 텍스트는 해당 구성요소의 URL 인코딩에 사용된 규칙과 동일한 규칙에 따라 자동으로 인코딩됩니다. pathname 내의 유니코드 문자는 백분율로 인코딩되므로 /café과 같은 pathname 패턴은 자동으로 /caf%C3%A9로 정규화됩니다. hostname의 유니코드 문자는 백분율 인코딩이 아닌 퓨니코드를 사용하여 자동으로 인코딩됩니다.

  • 정규 표현식 그룹에는 ASCII 문자만 포함되어야 합니다. 정규 표현식 문법을 사용하면 이러한 그룹에서 유니코드 문자를 자동으로 인코딩하기가 어렵고 안전하지 않습니다. 정규 표현식 그룹에서 유니코드 문자를 일치시키려면 café와 일치하도록 (caf%C3%A9)와 같이 수동으로 퍼센트 인코딩해야 합니다.

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를 사용하는 방법에 관한 논의가 진행 중입니다.

감사의 말

감사의 전체 목록은 설명 문서 원본을 참고하세요.