한국어

개발자 도구 · URL 인코더 및 디코더

WHATWG URL 표준과 RFC 3986: 브라우저와 라이브러리가 일치하지 않는 이유

· 배경

URL 인코딩 표준 개발자 도구

URL 구문 분석 시 브라우저와 라이브러리의 차이
원본 ToolAcre 벡터 일러스트레이션

URL에는 두 가지 정의가 있으며 의도적으로 서로 일치하지 않습니다. 이 게시물에서는 WHATWG가 자체 표준을 작성한 이유, 인코딩과 구문 분석이 다른 두 표준, 그리고 코드가 따르는 표준을 설명합니다.

엄격한 라이브러리가 거부하고 브라우저가 만족스럽게 로드하는 URL — 문자열 1개, 판정 2개

JavaScript에서 백슬래시가 있는 문자열은 브라우저에서 URL 경로의 일부로 원활하게 해석될 수 있습니다. 동일한 문자열이 Python 라이브러리 백엔드에 도달하지만 백슬래시가 허용되지 않기 때문에 구문 분석을 거부합니다. 하나의 URL, 두 가지 다른 결과. 둘 다 틀린 것은 아닙니다. 그들은 서로 다른 표준을 따릅니다. WHATWG 표준은 브라우저가 잘못된 입력을 처리하는 방법을 포함하여 실제 URL로 실제로 수행하는 작업을 설명합니다. RFC 3986는 URL이 이상적으로 준수해야 하는 공식 문법을 정의합니다. RFC 3986를 기반으로 구축된 많은 백엔드 라이브러리는 해당 문법을 엄격하게 적용하고 그 밖의 모든 것을 거부합니다.

이러한 차이는 환경 간에 데이터를 이동할 때 중요합니다. URL 브라우저가 수락하면 백엔드 도구에서 유효성 검사가 실패할 수 있습니다. 코드가 어떤 표준을 구현하는지 이해하면 URL이 한 곳에서는 잘 작동하지만 알 수 없는 이유 없이 다른 곳에서는 이상하게 실패하는 등의 유령 문제 디버깅을 방지할 수 있습니다.

WHATWG가 다시 시작된 이유 — 브라우저가 유효한 입력이 아닌 잘못된 입력으로 실제로 수행하는 작업을 설명합니다.

WHATWG 워킹 그룹은 브라우저가 따르지 않을 더 엄격한 공식 규칙을 정의하는 대신 브라우저가 실제로 URL을 처리하는 방법을 표준화하기 위해 2004에 구성되었습니다. RFC 2396은 공식적인 문법 사양을 설명했지만 실제로 브라우저는 이를 정확하게 따르지 않았습니다. 실제 브라우저에서는 공백 허용, 이스케이프 문자 처리, RFC가 예상하지 못한 잘못된 입력 복구를 위한 실용적인 규칙을 개발했습니다.

RFC 3986는 올바른 형식의 URL에 대한 공식 문법과 엄격한 요구 사항과 함께 2005에 도착했습니다. 브라우저는 WHATWG를 구현합니다. 백엔드 라이브러리는 종종 RFC 3986를 구현합니다.

인코딩 세트와 예약 문자 — URL 표준의 구성 요소별 목록이 RFC 3986의 카테고리와 어떻게 관련되는지

RFC 3986는 문자를 예약된 항목, 예약되지 않은 항목, 인코딩해야 하는 기타 모든 항목의 세 가지 범주로 나눕니다. 콜론, 슬래시, 물음표, 해시와 같은 예약 문자는 URL에서 구조적 의미를 갖습니다. 예약되지 않은 문자는 문자, 숫자, 하이픈, 밑줄, 마침표 및 물결표입니다. 이것들은 항상 안전합니다. 다른 모든 것은 바이트로 백분율로 인코딩됩니다. 표준은 하나의 명확한 규칙을 제공합니다. 즉, 캐릭터가 어떤 카테고리에 속하는지 파악하는 것입니다.

WHATWG URL 표준은 구성 요소 기반 접근 방식을 취합니다. 전역 카테고리를 사용하는 대신 체계, 권한, 경로, 쿼리 및 조각에 대해 서로 다른 인코딩 규칙을 별도로 지정합니다. 앰퍼샌드는 경로에서 인코딩될 수 있지만 쿼리 문자열에는 단독으로 남겨질 수 있습니다. 공백은 항상 인코딩되지만 정확한 표현은 상황에 따라 다릅니다. 이 구성 요소별 디자인은 브라우저 동작과 훨씬 더 잘 일치하지만 인코딩 중인 URL 부분을 알아야 합니다.

오류 허용 범위: 공백, 백슬래시 및 탭 — 하나의 표준 거부 입력과 다른 수정 입력

공백은 두 표준 모두에서 %20이 되어야 하지만 브라우저는 자동으로 리터럴 공백을 변환합니다. 백슬래시는 두 표준 모두에서 금지되지만 일부 브라우저에서는 이를 경로 구분 기호로 처리합니다. 탭, 줄 바꿈 및 제어 문자는 금지됩니다. WHATWG는 관대 한 파서 동작을 지정합니다: 변환하거나 무시합니다.

é 또는 中과 같은 비ASCII 문자는 UTF-8 인코딩을 사용하여 백분율로 인코딩되어야 합니다. RFC 3986은 실제로 문자 인코딩 단계 자체를 지정하지 않습니다. 바이트가 존재한다고 가정하지만 텍스트에서 바이트를 얻는 방법은 알려주지 않습니다. WHATWG 표준은 명시적으로 UTF-8를 요구합니다. 먼저 문자열을 UTF-8 바이트로 변환한 다음 백분율로 인코딩합니다. 두 표준 모두 동일한 인코딩 결과에 도달하지만 서로 다른 기본 가정에서 시작하며 동일한 사항에 대해 명시적이지 않습니다.

작업 예: 두 모델 모두에서 백슬래시와 공백이 있는 URL을 구문 분석합니다. 출력 비교

문자열 "https://example.com/café\ 검색"을 예로 들어 보겠습니다. 브라우저는 백슬래시를 발견하고 이를 경로 문자로 간주합니다. 공백을 확인하고 이를 %20로 인코딩하여 https://example.com/café%5C%20search.와 같은 결과를 생성합니다. RFC 3986 구문 분석기는 백슬래시와 공백이 금지되므로 전체 URL을 즉시 거부합니다. 브라우저는 계속해서 구문 분석을 수행합니다. 엄격한 구문 분석기가 완전히 중지됩니다. 다른 예를 시도해 보세요. "https://user@example.com:80/path?q=a&b=c". 두 표준 모두 사용자 정보, 호스트, 포트, 경로 및 쿼리를 명확하게 식별합니다. 이 구조화된 URL에 완전히 동의합니다. 불일치는 비정상적이거나 잘못된 입력에서만 발생합니다.

URL 인코더 및 디코더를 열고 RFC 3986 모드를 브라우저 동작과 비교합니다. 공백, 백슬래시 또는 기타 특별한 경우가 포함된 문자열을 붙여넣습니다. 이 도구는 각 표준이 동일한 입력을 어떻게 다르게 변환하는지 정확하게 보여줍니다. 어느 것이 더 엄격한지, 각각의 기능은 무엇인지 즉시 알 수 있습니다.

귀하의 환경에서 사용하는 것 — 브라우저와 노드는 URL 표준을 따릅니다. 많은 서버 라이브러리는 일반적으로 설명되는 RFC를 따릅니다.

브라우저에서 JavaScript는 기본적으로 WHATWG URL 표준을 사용합니다. URL API는 이를 정확하게 구현합니다. Node.js도 WHATWG를 사용합니다. Python 라이브러리는 RFC 3986를 구현하는 경향이 있습니다. urllib는 이를 밀접하게 따릅니다. Java 라이브러리는 다양합니다. java.net.URL은 RFC 3986을 지향하는 경향이 있습니다. Rust의 URL 크레이트는 WHATWG를 따릅니다. Go의 net/url는 WHATWG의 영향을 받습니다. 이는 절대적인 규칙이 아닌 일반적인 패턴입니다.

프로그래밍 방식으로 URL을 구축하고 브라우저와 백엔드 사이를 이동할 때 하나의 표준을 선택하고 이를 고수하세요. WHATWG에는 브라우저의 URL API를 사용하세요. 백엔드 라이브러리가 더 엄격하다면 이는 모순이 아니라 디자인 선택입니다.

여기서 다루지 않는 내용 — 호스트 이름 구문 분석, IPv6 리터럴 및 IDNA 처리

호스트 이름 구문 분석에는 URL 구문 분석 자체를 완전히 넘어서는 IDNA, 퓨니코드 및 등록자 규칙이 포함됩니다. IPv6 주소, mailto: 또는 data:와 같은 특수 체계 및 빈 구성 요소는 백분율 인코딩과 완전히 별개의 주제입니다. 도메인 길이 제한과 호스트 이름 유효성은 등록기관에 따라 다르며 이 논의와 관련이 없습니다. 또한 제외: 상대 참조 및 체계별 구문 분석 규칙. 이 게시물은 인코딩 및 구문 분석 차이점에만 중점을 둡니다.

이 토론에서는 이러한 표준을 구별하는 인코딩 및 구문 분석 차이점에 중점을 둡니다. 호스트 이름 규칙, DNS 규칙 및 체계별 동작을 제외하면 백분율 인코딩 규칙에 대한 혼동을 방지할 수 있습니다.

요점: 동일한 URL이 한 세계에서는 유효하고 다른 세계에서는 오류가 있습니다. URL 인코더 및 디코더가 일반 RFC 3986 인코딩을 제공하여 브라우저가 정규화한 내용을 확인할 수 있는 방법

동일한 URL 문자열이 한 표준에서는 유효하고 다른 표준에서는 유효하지 않을 수 있습니다. 둘 다 자체 설계 목표 내에서 정확합니다. 프로그래밍 방식으로 URL 구성 요소를 인코딩하는 경우 환경에 적합한 도구를 사용하십시오. WHATWG는 브라우저가 실제로 수행하는 작업을 설명합니다. RFC 3986는 형식적인 문법을 정의합니다. URL 인코더 및 디코더는 브라우저 동작과 함께 RFC 3986 규칙을 표시하므로 정확한 차이점을 확인하고 상황에 맞는 것을 선택할 수 있습니다.

문제는 URL이 브라우저와 백엔드 경계를 넘을 때 가장 자주 나타납니다. 이 차이를 이해한다는 것은 우연히 또는 실수로 교차하는 것이 아니라 의도적으로 교차를 처리하는 것을 의미합니다.