URL 인코더·디코더 쉽게 이해하기 — 개념과 원리
URL에는 정해진 일부 ASCII 문자만 쓸 수 있고, 그중 ?, &, = 같은 문자는 주소의 구조를 나타내는 역할을 합니다. 퍼센트 인코딩은 그 밖의 문자나 데이터로 쓰인 예약 문자를 바이트마다 %와 16진수 두 자리로 바꾸는 방식입니다. 이 도구는 쿼리 값이나 URL 전체를 인코딩하고, 퍼센트 인코딩된 문자열을 다시 읽을 수 있는 글자로 디코딩합니다. 한글 같은 비ASCII 문자는 UTF-8 기준으로 처리합니다.
계산 방법
- 구성 요소 인코딩(encodeURIComponent): A~Z, a~z, 0~9와 - _ . ! ~ * ' ( )를 제외한 모든 문자를 UTF-8 바이트로 바꾸고, 각 바이트를 %XX로 씁니다.
- 전체 URL 인코딩(encodeURI): 방식은 같지만 : / ? # & = + ; , @ $ 같은 URL 구조 문자는 그대로 둡니다.
- 디코딩(decodeURIComponent): 먼저 +를 공백으로 바꾼 뒤(HTML 폼 관례), 각 %XX를 바이트로 되돌려 UTF-8로 읽습니다.
원리
RFC 3986은 문자를 인코딩이 필요 없는 비예약 문자와 URL 각 부분을 구분하는 예약 문자로 나눕니다. ?는 쿼리의 시작, &는 매개변수 구분, =는 이름과 값의 연결을 뜻합니다. 값 자체에 &나 =가 들어 있으면 반드시 인코딩해야 하며, 그렇지 않으면 서버가 엉뚱한 곳에서 값을 자릅니다. 어떤 바이트든 %와 16진수 두 자리로 쓸 수 있고, UTF-8은 비ASCII 문자를 여러 바이트로 바꾸므로 어떤 언어의 글자든 URL에 넣을 수 있습니다.
예제 풀이
- 입력값은 name=홍길동&city=Seoul Korea, 모드는 구성 요소 인코딩입니다.
- "name"은 그대로이고 =는 %3D, &는 %26이 됩니다.
- 홍은 UTF-8로 ED 99 8D이므로 %ED%99%8D, 길은 %EA%B8%B8, 동은 %EB%8F%99입니다.
- 공백은 %20이 됩니다.
- 결과는 name%3D%ED%99%8D%EA%B8%B8%EB%8F%99%26city%3DSeoul%20Korea입니다.
문자열 전체를 하나의 값으로 보았기 때문에 =와 &까지 인코딩되었습니다. 실제 쿼리를 만들 때는 name= 뒤에 홍길동만 인코딩해 붙이는 식으로 값만 인코딩하십시오.
결과 해석
한글 한 글자는 %XX 세 묶음이 되므로 인코딩된 한글은 원래 글자 수의 약 9배 길이가 됩니다. 디코딩 결과가 "invalid input"이면 % 하나만 따로 있거나 UTF-8 바이트가 중간에 끊긴 잘못된 문자열입니다.
흔한 실수
- URL 전체를 구성 요소 모드로 인코딩해 ://와 /까지 망가뜨리는 경우
- 두 번 인코딩해 %가 %25로 바뀌는 경우(예: %2520)
- +가 언제나 공백이라고 생각하는 경우(폼 형식 쿼리에서만 그렇습니다)
자주 묻는 질문
공백은 %20과 + 중 무엇으로 써야 하나요?
URL 어디에서나 %20이 맞습니다. +는 HTML 폼 전송 같은 application/x-www-form-urlencoded 데이터에서만 공백을 뜻합니다.
주소창에 한글이 그대로 보이는 이유는 무엇인가요?
브라우저가 읽기 쉽도록 디코딩해서 보여 줄 뿐, 서버에는 퍼센트 인코딩된 UTF-8 형태로 보냅니다.
16진수의 대문자와 소문자는 다른가요?
같습니다. %3d와 %3D는 동일하지만 RFC 3986은 대문자를 권장합니다.
출처: IETF RFC 3986, Uniform Resource Identifier (URI): Generic Syntax · ECMA-262, ECMAScript Language Specification · WHATWG URL Standard