개발자 도구 · URL 인코더 및 디코더
URIError: 잘못된 URI — decodeURIComponent가 발생하는 이유 및 해결 방법
· 작동 방식
URL 인코딩 자바스크립트 오류 처리
decodeURIComponent는 백분율 기호 뒤에 두 개의 16진수 숫자가 없거나 디코딩된 바이트가 유효하지 않은 경우(UTF-8) 발생합니다. 이 게시물에서는 이를 트리거하는 입력과 방어적으로 디코딩하는 방법을 보여줍니다.
충돌이 발생한 백분율 기호 — "100% off"가 decodeURIComponent를 중단하는 이유
양식에 할인 코드 '100% 할인'이 수집됩니다. JavaScript은 이를 URL 디코더의 decodeURIComponent에 전달합니다. 이 함수는 URIError: URI malformed를 발생시킵니다. 백분율 기호 뒤에 두 개의 16진수 숫자가 오지 않습니다. 이는 백분율 인코딩 규칙을 완전히 위반합니다. decodeURIComponent는 모든 %가 %20 또는 %C3과 같은 삼중항을 시작할 것으로 예상합니다. 고독한 %는 실행을 즉시 중지하고 오류를 발생시키는 구문 오류입니다.
이 오류를 안전하게 포착하면 애플리케이션 충돌을 완전히 방지할 수 있습니다. URL은 사용자 입력, 리디렉션, QR 코드 및 이메일을 통해 도착합니다. 오타가 자주 발생합니다. URIError가 포함된 충돌 보고서는 신속하게 조사할 위치를 알려줍니다. 방어적 디코딩을 통해 애플리케이션이 계속 실행되고 오류 로그가 디버깅에 유용해집니다.
두 가지 종류의 실패 — 잘못된 형식의 16진수 이스케이프 및 잘못된 UTF-8 바이트 시퀀스
decodeURIComponent는 정확히 두 가지 상황에서 발생합니다. 첫째: 잘못된 이스케이프 시퀀스입니다. 백분율 뒤에 두 개의 16진수 숫자가 없습니다(0-9, A-F, a-f). 예: %ZZ, %2, %2g. 둘째: %E9와 같은 유효한 삼중항을 잘못된 UTF-8 바이트로 디코딩합니다. 첫 번째는 형식 오류입니다. 두 번째는 의미론적 오류입니다. 즉시 실행을 던지고 중지합니다.
UTF-8에는 바이트 순서에 대한 엄격한 규칙이 있습니다. 바이트 0x80–0xFF는 멀티바이트 시퀀스에만 나타납니다. 단일 %E9는 단독으로 유효한 UTF-8일 수 없습니다. 이 고아 바이트는 오류를 유발합니다. 형식 오류는 명백합니다. 의미론적 오류는 미묘하지만 똑같이 실제적입니다. 두 경우 모두 프로덕션 코드에서 try/catch 처리가 필요합니다.
레거시 단일 바이트 인코딩 — %E9만 발생하지만 %C3%A9가 살아남는 경우
혼란은 웹 표준의 역사에서 비롯됩니다. 이전 페이지에서는 UTF-8 대신 라틴어-1을 사용했습니다. 라틴어로 -1, %E9는 é를 나타냅니다. 최신 브라우저는 UTF-8만을 사용합니다. UTF-8는 é를 %C3%A9로 인코딩합니다. 최신 디코더는 UTF-8를 예상하고 %E9를 잘못된 형식으로 거부합니다. 이는 올바른 동작입니다. 오류는 소스 데이터에 문제가 있음을 나타냅니다.
현대적인 합의: UTF-8 모든 곳에서. URL 표준은 UTF-8을 지정합니다. 현재의 모든 브라우저는 UTF-8를 사용합니다. 이전 시스템에서 %E9가 발생하면 오류를 포착하고 원시 문자열로 대체하세요. 최신 코드에서는 Latin-1로 디코딩하지 마십시오. 데이터의 출처를 조사합니다.
3개의 입력, 3개의 오류 메시지 — 동일한 깨진 문자열에서 엔진이 어떻게 다른지
브라우저 엔진은 잘못된 입력을 일관되게 거부하지만 단어 오류는 다르게 거부합니다. Chrome에서 "URI 형식이 잘못되었습니다"라고 보고합니다. Firefox는 "잘못된 URI 시퀀스"를 보고합니다. Safari에서는 "정의되지 않은 객체를 객체로 변환할 수 없습니다"라고 보고합니다. 세 엔진 모두 동일한 입력을 거부합니다. 정확한 메시지 문구는 다양한 엔진이나 버전에 걸쳐 표준화되지 않습니다. 코드 논리를 안내하기 위해 오류 텍스트에 의존하지 마십시오.
프로그램 결정을 위해 오류 메시지를 문자열로 일치시키지 마십시오. 항상 유형별로 URIError를 포착하세요. decodeUrl 함수는 decodeURIComponent를 래핑하고 일관된 코드 INVALID_PERCENT_ENCODING을 제공합니다. 이는 정확한 문제 위치를 지정합니다. 엔진 문구 변형에 의존하지 않기 때문에 런타임 전반에 걸쳐 작동합니다. 이 접근 방식은 더 안정적이고 유지 관리가 용이합니다.
안전하게 예외 읽기 — try/catch, 유효성 검사 및 대체 패턴 시도
가장 간단한 방어 패턴: try/catch.에서 decodeURIComponent를 래핑합니다. 오류가 발생하는 경우 원시 문자열 또는 대체 문자를 사용합니다. 이렇게 하면 잘못된 형식의 입력이 충돌하는 것을 방지할 수 있습니다. 쿼리 값의 경우 URL로 인코딩된 형식을 표시합니다. 사용자에게 표시되는 텍스트의 경우 대체 문자를 삽입하세요. 이는 잘못된 입력으로 인해 애플리케이션이 중단되는 것을 방지하고 안정성을 유지합니다.
속도와 안전성을 위해 정규식으로 사전 검증합니다. 디코딩하기 전에 입력에 유효한 %XX 삼중항만 포함되어 있는지 확인하십시오. /%[0-9A-Fa-f]{2}/g 패턴은 유효한 이스케이프를 포착합니다. 일치하지 않는 것은 모두 유효하지 않습니다. 명백한 쓰레기로 인해 형식 오류가 빨리 실패합니다. UTF-8 오류에는 여전히 try/catch.가 필요합니다. 이는 오류에 대한 포괄적인 방어 보호를 제공합니다.
자동 실패로 인해 버그가 숨겨집니다. 블라인드 디코딩이 손상된 인코딩만큼 위험한 이유
미묘한 위험: 디코더가 오류를 발생시키지 않지만 자동으로 잘못된 텍스트를 생성합니다. 더 이상 사용되지 않는 이스케이프 해제를 사용하는 이전 코드는 메모리에 잘못된 UTF-8을 남깁니다. UTF-8을 엄격하게 검증하는 시스템에 도달할 때까지 텍스트는 화면에서 정상적으로 보입니다. 최신 코드는 자동으로 손상되기보다는 발생합니다. 예외는 다운스트림으로 퍼지는 자동 데이터 손상보다 더 명확하고 안전합니다.
사용자 입력의 형식이 잘못되었다고 가정합니다. 항상 통화를 마무리하세요. 디버깅을 위해 원래 입력으로 오류를 기록합니다. 모든 %가 유효하다고 가정하지 마십시오. 오타와 잘림은 불완전한 이스케이프를 만듭니다. 논리 오류가 아닌 데이터 오류로 처리합니다. 방어 코드는 잘못된 입력을 정상적으로 견뎌내고 시스템을 안정적으로 유지합니다.
실제 도구가 건너뛰는 것 — 서버 측 프레임워크 동작 및 오류 복구
서버 프레임워크는 브라우저보다 더 관대하게 잘못된 인코딩을 처리합니다. Ruby, Python 및 PHP는 URL에서 유효하지 않은 이스케이프를 처리하기 위한 구성을 제공합니다. 일부 대체 문자는 자동으로 대체됩니다. 다른 사람들은 조용히 바이트를 삭제합니다. 일부는 JavaScript와 같은 예외를 발생시킵니다. 실제 동작은 개발자가 선택한 프레임워크 및 구성 설정에 따라 다릅니다.
이 문서에서는 브라우저 JavaScript 동작만 다룹니다. 서버 API에서 값이 도착하면 서버는 보내기 전에 이미 오류를 디코딩했거나 건너뛴 것입니다. 서버는 클라이언트보다 더 관대할 수 있습니다. API 계약을 작성할 때 값이 원시인지 사전 디코딩되었는지 지정하세요. URL 쿼리 문자열은 퍼센트 인코딩되어 도착해야 합니다. JSON은 사전 디코딩되어 도착할 수 있습니다.
조기 유효성 검사 - URL 인코더 및 디코더를 사용하여 의심스러운 문자열을 먼저 확인합니다.
의심스러운 URL을 decodeURIComponent에 전달하기 전에 URL 인코더 및 디코더에 붙여넣으세요. 이 도구는 정확한 인코딩을 보여주고, 잘못된 형식의 이스케이프를 찾아내고, 애플리케이션을 중단시키지 않고 오류를 설명합니다. %ZZ, %E9 및 100%로 테스트하여 다양한 오류와 정확한 오류 메시지를 확인하세요. 이 작업은 몇 초가 걸리며 자신감이 쌓입니다.
조기에 유효성을 검사하고, 오류를 적절하게 포착하고, 손상된 내용을 기록합니다. 방어 디코더와 테스트 도구를 사용하면 애플리케이션을 계속 실행하고 디버그할 수 있습니다. URL 인코더 및 디코더는 '잘못된 URI'를 즉시 사용할 수 있는 실행 가능한 정보로 변환합니다. 프로덕션 환경의 탄력성과 유지 관리성을 위해 이 패턴을 자체 디코더에 적용하세요.