URL 인코더/디코더
URL을 인코딩하거나 디코딩합니다. 한글 URL, 특수문자 URL 변환에 유용합니다.
URL 퍼센트 인코딩 — RFC 3986의 정확한 해석
퍼센트 인코딩(percent-encoding, URL encoding)은 RFC 3986 §2에 정의된 메커니즘으로, URI에서 허용되지 않는 옥텟을 % 뒤에 두 자리 16진수(대문자 권장)로 표현합니다. "URL-safe"라는 표현이 자주 쓰이지만 엄밀히는 URI-safe이며, RFC 3986은 이전 RFC 2396, RFC 1738을 폐기(obsolete)시켰습니다. 이 도구는 JavaScript의 네이티브 함수(encodeURI,encodeURIComponent) 동작을 재현하면서, 어느 쪽을 쓸지 즉시 비교할 수 있게 해줍니다.
예약 문자 vs 비예약 문자
RFC 3986은 문자를 세 부류로 나눕니다.
- Unreserved (인코딩 불필요):
A-Z a-z 0-9 - _ . ~ - gen-delims:
: / ? # [ ] @— URI 컴포넌트 경계를 정의 - sub-delims:
! $ & ' ( ) * + , ; =— 컴포넌트 내부 하위 구분자
나머지는 모두 반드시 인코딩되어야 합니다. 문맥에 따라 gen-delims/sub-delims를 인코딩할지 말지가 달라지는데, 여기서 encodeURI와 encodeURIComponent의 차이가 생깁니다.
encodeURI vs encodeURIComponent — 정확한 구분표
| 문자 | encodeURI | encodeURIComponent |
|---|---|---|
| A-Z a-z 0-9 - _ . ~ ! * ' ( ) | 유지 | 유지 |
| ; , / ? : @ & = + $ # | 유지 (예약어로 취급) | 인코딩 |
| 공백 | %20 | %20 |
| 한글 "한" (U+D55C) | %ED%95%9C | %ED%95%9C |
규칙은 명확합니다. 완성된 URI를 넣을 때는 encodeURI(?,=, / 등 구조 문자를 유지), 쿼리스트링 값 하나를 이스케이프할 때는encodeURIComponent를 쓰세요. 혼동하면 ?q=a+b의 +가 공백으로 역변환되면서 "C++" 검색이 "C "가 되는 전형적 버그가 납니다.
실제 변환 예시
입력 encodeURI encodeURIComponent ───────────────────────────────────────────────────────────────────────────── "한글" %ED%95%9C%EA%B8%80 %ED%95%9C%EA%B8%80 "hello world" hello%20world hello%20world "https://ex.com/a?b=1&c=2" https://ex.com/a?b=1&c=2 https%3A%2F%2Fex.com%2Fa%3Fb%3D1%26c%3D2 "user@example.com" user@example.com user%40example.com "a+b=c" a+b=c a%2Bb%3Dc "redirect_url=https://..." redirect_url=https://... redirect_url%3Dhttps%3A%2F%2F...
실전 시나리오
- OAuth 2.0 redirect_uri — 인증 서버에 전달할 리다이렉트 URL은 쿼리 파라미터 값이므로
encodeURIComponent필수 - 네이버/다음 검색 쿼리 —
?query=한글은 UTF-8로 퍼센트 인코딩해야 함 (EUC-KR 시절의%C7%D1은 레거시) - S3 Presigned URL — 파일명에 공백·한글이 있으면 객체 키 인코딩이 SigV4 서명과 일치해야 함
- 로그 분석 — Nginx
access.log에%2520처럼 이중 인코딩이 찍힐 때 원본을 복원
보안 — 검증은 디코딩 후에
퍼센트 인코딩은 여러 고전적 공격의 진입점입니다. 이중 인코딩(%2527)으로 WAF를 우회해 SQL injection을 시도하거나, 오버롱 UTF-8(%C0%A7로 ..를 숨김)로 path traversal을 시도하는 사례가 대표적입니다. 애플리케이션은 반드시 완전히 디코딩된 후 화이트리스트 검증을 수행해야 하며, OWASP는 디코딩을 한 번만 수행하고 남은 %가 있으면 거부할 것을 권장합니다(Canonicalization Principle).
관련 도구
인코딩 전 한글 바이트 수를 미리 보려면글자수 세기에서 UTF-8 바이트를 확인하세요. Base64URL(RFC 4648 §5)과 일반 Base64 차이는Base64 인코더에서 다룹니다. 쿼리에 붙는 JSON은 JSON 포매터로 먼저 검증하면 편리합니다.
참고 자료
- IETF RFC 3986 — Uniform Resource Identifier (URI): Generic Syntax
- WHATWG URL Living Standard — application/x-www-form-urlencoded serializer
- MDN Web Docs — encodeURI() / encodeURIComponent() / URLSearchParams
- OWASP — Double Encoding Testing, Input Validation Cheat Sheet