상대 URL 해석기 (RFC 3986)
RFC 3986대로 상대 참조를 기준 URI에 대해 해석하고, 점 세그먼트 추적과 브라우저의 답을 나란히 보여 줍니다.
위 기준으로 시도해 볼 만한 참조
http://a/b/c/y
http://a/b/c/y
RFC 3986 결과와 일치합니다.
§5.2.2의 어느 분기가 실행됐는지
R.path is relative — merged with the base path
대상 구성요소 (§5.3)
| 스킴 | http |
| 오소리티 | a |
| 경로 | /b/c/y |
| 쿼리 | — |
| 프래그먼트 | — |
remove_dot_segments 단계별 (§5.2.4)
| 규칙 | 입력 버퍼 | 출력 버퍼 |
|---|---|---|
| — | /b/c/g;x=1/../y | "" |
| E | /c/g;x=1/../y | /b |
| E | /g;x=1/../y | /b/c |
| E | /../y | /b/c/g;x=1 |
| C | /y | /b/c |
| E | "" | /b/c/y |
| — | "" | /b/c/y |
규칙 A~E는 규격 자체의 이름이고, 마지막 행이 반환되는 출력 버퍼입니다.
RFC 3986 §5.2를 단계 그대로 구현했습니다. WHATWG를 따르는 라이브러리는 항상 일치하지 않으므로 브라우저 결과를 나란히 보여 줍니다.
사용법
- 기준 URI와 상대 참조를 입력하면 대상이 브라우저 결과와 함께 나옵니다.
- 예시 참조 버튼을 누르면 규격 자체 테스트의 한 케이스가 들어갑니다.
- 답이 뜻밖일 때 점 세그먼트 추적을 읽으세요. 각 단계에서 어느 규칙이 걸렸는지 보여 줍니다.
- 엄격 모드를 끄면 같은 스킴 예외를 허용하는 파서가 대신 무엇을 내놓는지 볼 수 있습니다.
자세한 설명
펼치기접기
기준 URI와 상대 참조를 주면 RFC 3986 §5.2가 말하는 방식대로 대상 URI를 만들고, 그 옆에 브라우저 자체의 답을 함께 보여 주며 둘이 일치하는지 알려 줍니다. 대개는 일치하지만, 어긋나는 곳의 차이는 실제이고 문서화되어 있으며, 내가 쓰는 라이브러리가 어느 쪽을 따르는지 아는 것이 링크가 되는 것과 404가 되는 것의 차이입니다. 규격 자체의 테스트가 42개인데 그중 둘이 모든 브라우저와 Node가 싣는 WHATWG URL 파서와 어긋납니다. //g는 RFC로는 http://g, 브라우저에서는 http://g/가 되는데 WHATWG가 빈 경로를 슬래시로 정규화하기 때문입니다. 그리고 http 기준에 대한 http:g는 엄격하게는 http:g지만, 브라우저는 하위 호환 예외를 적용해 http://a/b/c/g를 냅니다. 여기 엄격 모드 토글이 바로 그 예외라서 둘 다 볼 수 있습니다. 볼 만한 부분은 점 세그먼트 추적입니다. §5.2.4는 버퍼 두 개로 .과 ..을 제거하는데, 규칙은 그것이 완전한 경로 세그먼트일 때만 점 세그먼트로 취급합니다 — 그래서 g.이나 ..g는 살아남는 평범한 이름이지만, g;x=1/../y는 y로 해석되면서 매트릭스 파라미터까지 데려갑니다. 추적은 매 단계 뒤의 입력·출력 버퍼를 규격 자체의 규칙 A~E 이름과 함께 인쇄하므로, 놀라운 답을 믿고 넘기는 대신 확인할 수 있습니다. 쿼리와 프래그먼트는 이 모든 것 전에 경로에서 분리되며, 그래서 g?y/../x는 /../를 그대로 유지합니다.
자주 묻는 질문
//g에서 브라우저는 왜 RFC와 다른가요?
RFC 3986은 빈 경로로 http://g로 해석합니다. 브라우저와 Node가 구현하는 WHATWG URL 표준은 특수 스킴의 빈 경로를 /로 정규화하므로 http://g/가 됩니다. 둘 다 의도된 동작입니다. URL을 문자열로 비교하거나 캐시 키로 쓸 때 문제가 되는데, 같은 자원을 가리켜도 두 형태는 같지 않기 때문입니다.
엄격 옵션은 무엇을 위한 것인가요?
§5.2.2는 옛 부분 URI 규칙과의 하위 호환을 위한 비엄격 변형을 제공합니다. 참조의 스킴이 기준과 같으면 무시하고 참조를 상대 참조로 다루는 것입니다. 그러면 http:g가 http:g로 남는 대신 http://a/b/c/g가 됩니다. RFC는 이를 허용하면서 의존하지 말라고 권하고, 브라우저는 그렇게 합니다. 토글로 내 경우가 어느 동작에 의존하는지 볼 수 있습니다.
g;x=1/../y에서 ;x=1은 왜 사라졌나요?
..은 바로 앞 세그먼트 전체를 제거하고, g;x=1이 한 세그먼트이기 때문입니다 — 세미콜론은 일반 문법에서 특별한 의미가 없습니다. 그래서 경로가 /b/c/y가 됩니다. 그렇게 쓴 매트릭스 파라미터가 취약한 이유가 정확히 이것이고, 뒤에 점 세그먼트가 하나라도 오면 함께 사라집니다.
g?y/../x는 왜 안에 든 점 세그먼트의 영향을 받지 않나요?
점 세그먼트 제거 전에 참조가 경로·쿼리·프래그먼트로 나뉘고, 거기서 /../는 쿼리 안에 있기 때문입니다. §5.4.2가 이를 특별히 언급하며, 일부 파서가 참조 전체를 먼저 병합해 틀린다고 적어 뒀습니다. 쿼리에 슬래시가 들어가는 일이 드물어 좀처럼 드러나지 않는 버그입니다.
결과를 정규화하나요?
해석 자체가 요구하는 것 외에는 하지 않습니다. 스킴·호스트의 대소문자, 퍼센트 인코딩, 기본 포트, 빈 경로는 모두 §5.2가 남긴 그대로 둡니다. 정규화는 §6이고 별개의 결정이기 때문입니다. 비교해서 같아야 하는 URL이 필요하면 해석기가 해 주기를 기대하지 말고 의도적으로 정규화하세요.
관련 도구
/.well-known/* URI 레퍼런스
IANA 등록 well-known URI 검색 카탈로그 — security.txt·openid-configuration·apple-app-site-association·acme-challenge 외 30+개, RFC 레퍼런스·사용 사례 포함.
네트워크
JSON 포인터 리졸버 (RFC 6901)
/user/roles/0 같은 RFC 6901 JSON 포인터를 JSON 문서에서 해석 — ~0/~1 이스케이프와 URI 프래그먼트(#/…) 지원 — 문서 내 모든 포인터의 클릭 가능한 목록 포함, 브라우저에서.
개발
URI 템플릿 확장기 (RFC 6570)
직접 정의한 변수로 RFC 6570 URI 템플릿 확장 — 네 레벨 모두 지원: 경로·쿼리·프래그먼트·라벨·경로형 연산자, explode·prefix 수정자, 브라우저에서.
네트워크
URL 인코더 / 디코더
URL용으로 텍스트를 퍼센트 인코딩하거나, 인코딩된 URL을 디코딩하세요.
개발
Data URI 파서 및 디코더
data: URI를 디코드해 MIME 타입, 인코딩, 크기, 디코드된 내용을 브라우저에서 확인합니다.
개발
HTTP 상태 코드 레퍼런스
1xx-5xx 모든 HTTP 상태 코드 검색 — 요약·RFC·사용 시점·흔한 함정 포함.
네트워크