URI 딥 링크 일치

계층식 URI를 패턴과 일치시키고 인수를 추출하려면 UriDeepLinkMatcher를 사용합니다. kotlinx.serialization를 사용하여 일치하는 인수를 키 클래스로 역직렬화합니다.

UriDeepLinkMatcher를 만들려면 해당 키의 패턴 DeepLinkUri과 직렬 변환기를 제공합니다.

계층 구조가 아닌 URI 또는 맞춤 스키마 (예: tel:)의 경우 맞춤 딥 링크 일치자 만들기를 참고하세요.

지원되는 일치 패턴

UriDeepLinkMatcher는 스키마, 권한, 경로, 쿼리, 프래그먼트의 5가지 구성요소를 기반으로 URI를 일치시킵니다. 다음 섹션에서는 각 구성요소에 지원되는 패턴 문법, 인수 자리표시자, 일치 규칙을 설명합니다.

스키마 일치

URI 패턴에 스키마가 없으면 http 및 https가 모두 일치합니다. 특정 스키마를 일치시키려면 패턴에 포함합니다. 예외적으로 패턴의 http 스키마는 http 및 https 요청 URI와 모두 일치하지만 패턴의 https는 https 요청과만 일치합니다.

패턴 URI 요청 URI 일치
www.example.com https://www.example.com ✅
www.example.com http://www.example.com ✅
http://www.example.com http://www.example.com ✅
http://www.example.com https://www.example.com ✅
https://www.example.com http://www.example.com ❌
myapp://www.example.com myapp://www.example.com ✅

권한 일치

UriDeepLinkMatcher는 URI 권한 (호스트 및 선택적 포트)에서 대소문자를 구분하지 않는 정확한 일치를 수행합니다. 권한에는 자리표시자나 와일드 카드가 지원되지 않으며 인수가 추출되지 않습니다.

패턴 URI 요청 URI 일치
example.com https://example.com ✅
example.com https://EXAMPLE.COM ✅
example.com https://sub.example.com ❌
example.com https://www.example.com ❌
example.com https://example.com:8080 ❌
example.com:8080 https://example.com:8080 ✅
example.com:8080 https://example.com ❌

경로 일치

지원되는 경로 패턴은 다음과 같습니다.

패턴 URI 요청 URI 일치 추출된 인수
www.example.com/users https://www.example.com/users ✅ 없음
www.example.com/users/{id} https://www.example.com/users/123 ✅ id: "123"
www.example.com/users/{first}-{last} https://www.example.com/users/john-doe ✅ first: "john", last: "doe"
www.example.com/users/{id}/profile https://www.example.com/users//profile ✅ id: "" (빈 문자열)
www.example.com/users/user_{id} https://www.example.com/users/user_123 ✅ id: "123"
www.example.com/users/{userId}/posts/{postId} https://www.example.com/users/123/posts/456 ✅ userId: "123", postId: "456"
www.example.com/users/.* https://www.example.com/users/john-doe ✅ 없음
www.example.com/users https://www.example.com/users/ ❌ (끝에 슬래시가 있으면 추가 세그먼트가 생성됩니다) 해당 사항 없음

검색어 매칭

요청 URI의 쿼리 매개변수 순서는 패턴 URI의 순서와 일치하지 않아도 됩니다. 또한 요청 URI에 있지만 패턴 URI에는 없는 매개변수는 무시됩니다.

지원되는 쿼리 매개변수 패턴은 다음과 같습니다.

패턴 URI 요청 URI 추출된 인수
www.example.com/users?name={name} https://www.example.com/users?name=john name: "john"
www.example.com/users?name={name} https://www.example.com/users?name= name: "" (빈 문자열)
www.example.com/users?{rawQuery} https://www.example.com/users?anything&else rawQuery: ["anything", "else"]
www.example.com/users?type=user_{id} https://www.example.com/users?type=user_123 id: "123"
www.example.com/users?name={first}_{last} https://www.example.com/users?name=john_doe first: "john", last: "doe"
www.example.com/users?list={list} https://www.example.com/users?list=10&list=20 list: ["10", "20"]
www.example.com/users?name={name}&{other} https://www.example.com/users?name=john&tab=info name: "john", other: ["tab=info"]
www.example.com/users?type=user_.* https://www.example.com/users?type=user_admin type: "admin"

프래그먼트 일치

지원되는 프래그먼트 패턴 유형은 다음과 같습니다.

패턴 URI 요청 URI 추출된 인수
www.example.com/#section1 https://www.example.com/#section1 없음
www.example.com/#section_{id} https://www.example.com/#section_123 id: "123"
www.example.com/#section_.* https://www.example.com/#section_123 없음

지원되는 데이터 유형

UriDeepLinkMatcher은 URI 인수를 기본 유형, enum, 컬렉션, 맞춤 객체로 역직렬화하는 것을 지원합니다. 직렬화는 다음 두 가지 카테고리로 분류됩니다.

  • 표준 직렬화: kotlinx.serialization를 사용하여 다음으로 역직렬화합니다.
    • 기본 요소 (Boolean, Int, Long, Float, Double, Char, Byte, Short) 및 String
    • 열거형
    • Set, List 또는 기본 요소, 문자열, enum의 Array
    • 중첩된 @Serializable 클래스 (속성이 개별 URI 자리표시자로 평면화됨)
  • DeepLinkSerializer를 사용한 커스텀 직렬화: 단일 String와 커스텀 객체, 외부 유형 (예: java.time.LocalDate) 또는 커스텀 구분 컬렉션 간에 변환합니다.

표준 직렬화

UriDeepLinkMatcher는 커스텀 직렬 변환기 구현 없이도 표준 유형 및 평면화된 구조에 즉시 사용할 수 있습니다.

기본 요소 및 문자열

UriDeepLinkMatcher는 기본 유형 (Boolean, Int, Long, Float, Double, Char, Byte, Short)과 String를 자동으로 디코딩합니다.

열거형

enum 값은 enum 요소 이름과 대소문자를 구분하여 일치합니다.

반복되는 쿼리 컬렉션

반복되는 키 (예: ?id=10&id=20)가 있는 쿼리 매개변수는 자동으로 List<T>, Set<T> 또는 Array<T>로 역직렬화됩니다. 여기서 T는 기본 유형, String 또는 enum입니다.

중첩된 @Serializable 클래스

NavKey에 유형이 다른 @Serializable 클래스인 속성이 포함된 경우 UriDeepLinkMatcher는 속성을 평면화하여 중첩 클래스의 각 속성이 동일한 이름의 개별 URI 매개변수에 직접 매핑되도록 합니다.

커스텀 객체 (예: Filter(key = "brand", value = "pixel")), 외부 유형 (예: java.time.LocalDate) 또는 커스텀 구분 문자열 (예: 쉼표로 구분된 값)을 역직렬화하려면 DeepLinkSerializer<T>를 확장합니다.

DeepLinkSerializer<T>는 String와 T 간에 변환하는 추상 KSerializer<T>입니다.

abstract class DeepLinkSerializer<T : Any> : KSerializer<T> {
    abstract val serialName: String
    abstract fun deserialize(value: String): T
    abstract fun serialize(value: T): String
}

예를 들어 다음 스니펫에 사용되는 Filter 및 FilterSerializer 정의를 살펴보세요.

단일 커스텀 객체

단일 URI 매개변수 문자열 (예: ?filter=brand:google)에서 객체를 디코딩하려면 @Serializable(with = ...)로 속성에 주석을 추가합니다.

반복되는 쿼리 매개변수의 커스텀 객체

반복되는 쿼리 매개변수를 커스텀 객체 컬렉션(List<T>, Set<T> 또는 Array<T>)으로 역직렬화하려면 요소 유형 T에 DeepLinkSerializer<T>를 구현하고 속성의 유형 인수에 @Serializable(with = ...)로 주석을 추가합니다.

단일 매개변수의 구분된 컬렉션

쉼표로 구분되거나 커스텀 구분 기호로 구분된 값 (예: ?ids=1,2,3)을 컬렉션으로 파싱하려면 전체 컬렉션 유형에 DeepLinkSerializer를 구현하고 @Serializable(with = ...)로 속성에 주석을 추가합니다.

인수 검증 및 일치 결과

UriDeepLinkMatcher는 불일치 (다른 일치자를 시도할 수 있도록 null 반환)와 지원되지 않는 구성 (예외 발생)을 구분합니다.

불일치

수신 요청 URI가 패턴 또는 유형 요구사항을 충족하지 않으면 불일치가 발생합니다.

  • 필수 매개변수 누락: 해당 URI 매개변수가 요청 URI에 없는 기본값이 없는 null을 허용하지 않는 키 속성입니다.
  • 유형 파싱 실패: 예상 속성 유형으로 파싱할 수 없는 추출된 인수 값 (예: Int 속성의 "abc")

불일치가 발생하면 UriDeepLinkMatcher.match는 null를 반환하여 후속 일치자를 평가할 수 있습니다.

기본값, 중첩 객체, enum으로 구성된 키 클래스와 일치자를 고려하세요.

다음 표는 다양한 요청 URI의 일치 결과를 보여줍니다.

요청 URI 디코딩 결과 경기 결과
https://www.example.com/map/paris?zoom=15&style=dark&layer=SATELLITE 성공 (모든 매개변수 제공됨) UriMatchResult(MapKey("paris", 15, LayerOptions("dark", MapLayer.SATELLITE)))
https://www.example.com/map/paris?style=dark 성공 (zoom 기본값은 12, layer 기본값은 STANDARD) UriMatchResult(MapKey("paris", 12, LayerOptions("dark", MapLayer.STANDARD)))
https://www.example.com/map/paris?zoom=&style=dark 성공 (비어 있는 선택적 쿼리 매개변수는 기본 12 사용) UriMatchResult(MapKey("paris", 12, LayerOptions("dark", MapLayer.STANDARD)))
https://www.example.com/map?style=dark 불일치 (필수 location 매개변수 누락) null
https://www.example.com/map/paris?zoom=close&style=dark 불일치 ("close"은 Int가 아님) null
https://www.example.com/map/paris?style=dark&layer=HYBRID 불일치 ("HYBRID"가 enum에 없음) null

지원되지 않는 구성

키 클래스에 지원되지 않는 데이터 유형이 포함된 경우 UriDeepLinkMatcher는 일치하는 동안 null를 반환하는 대신 예외를 발생시킵니다.

  • 지도 및 다차원 컬렉션: UriDeepLinkMatcher는 DeepLinkSerializer로 주석이 달린 프리미티브, 문자열, enum 또는 맞춤 유형의 1차원 컬렉션만 지원합니다. Map 유형은 IllegalArgumentException를 발생시키고 중첩된 컬렉션 (예: List<List<String>>)은 SerializationException를 발생시킵니다.
  • 주석이 없는 커스텀 객체 컬렉션: 커스텀 유형의 컬렉션 (예: List<Filter>)은 요소 유형에 DeepLinkSerializer 주석이 추가되지 않는 한 SerializationException를 발생시킵니다.
  • 평면화되지 않은 중첩 클래스: 중첩된 @Serializable 클래스는 DeepLinkSerializer 없이 단일 자리표시자 (예: ?user={user})에 매핑할 수 없습니다.

UriMatchResult 비교

UriMatchResult 인스턴스는 다음 기준을 순서대로 사용하여 순위가 지정됩니다.

  1. MatchResult 유형: UriMatchResult는 다른 MatchResult 유형보다 순위가 높습니다.
  2. 정확한 경로: 리터럴 경로 일치가 자리표시자 또는 와일드 카드 일치보다 순위가 높습니다.
  3. 경로 인수 수: 경로 인수가 더 많은 일치 항목이 더 높은 순위를 차지합니다.
  4. 인수 존재: 인수를 캡처하는 일치 항목은 그렇지 않은 일치 항목보다 순위가 높습니다.
  5. 총 인수 수: 총 인수 수 (경로, 쿼리, 프래그먼트)가 최종 타이 브레이커입니다.

UriDeepLinkMatcher 맞춤설정

UriDeepLinkMatcher는 URI 일치 및 인수 추출 동작을 맞춤설정하기 위해 서브클래스로 만들 수 있는 open 클래스입니다.

  • matchRequest: 수신 DeepLinkRequest의 최상위 일치 진입점입니다. URI 일치 전에 요청 추가 항목을 검사하거나 커스텀 전제 조건을 적용하려면 이 메서드를 재정의합니다.
  • matchUri: DeepLinkUri을 구성된 패턴과 일치시킵니다. super.matchUri를 호출하기 전에 수신 URI를 가로채고 정규화하려면 (예: 동적 하위 도메인 또는 기존 경로 형식 재작성) 이 메서드를 재정의합니다.
  • matchArguments: 제공된 serializer를 사용하여 추출된 경로, 쿼리, 프래그먼트 인수 맵을 탐색 키 인스턴스로 역직렬화합니다. 키 인스턴스화 전에 동적 값을 삽입하거나 인수를 변환하려면 이 메서드를 재정의합니다.

다음 예시에서는 일치시키기 전에 기존 URL 경로 프리픽스를 정규화하기 위해 UriDeepLinkMatcher를 서브클래스화하는 방법을 보여줍니다.