2026. 03. 19
URL 인코딩이란 — 한글과 특수문자가 %EC처럼 바뀌는 이유
URL에서 한글이 %EC%95%88처럼 변환되는 원리와 퍼센트 인코딩 방식. encodeURI vs encodeURIComponent 차이와 언어별 구현 코드까지.
URL에서 한글이 깨지는 이유
네이버에서 "서울 날씨"를 검색하면 주소창에 %EC%84%9C%EC%9A%B8+%EB%82%A0%EC%94%A8 같은 URL이 나타난다. URL은 ASCII 문자 범위 안에서만 안전하게 전달되도록 설계됐기 때문에, 한글처럼 ASCII에 포함되지 않는 문자는 변환해야 한다.
퍼센트 인코딩의 원리
퍼센트 인코딩은 문자를 UTF-8 바이트로 변환하고, 각 바이트 앞에 %를 붙여 16진수로 표현하는 방식이다.
"안"이라는 글자는 UTF-8에서 3바이트로 표현된다: 0xEC 0x95 0x88 → %EC%95%88
공백 문자는 %20이다. URL에서 +로 표현하기도 하는데, +는 폼 데이터에서 공백을 나타내는 방식이고 순수 URL에서는 %20이 올바른 표현이다.
예약 문자와 비예약 문자
예약 문자: URL 구조에서 특별한 의미를 가진다. 데이터로 사용할 때는 반드시 인코딩해야 한다.
: / ? # [ ] @ ! $ & ' ( ) * + , ; =
비예약 문자: 인코딩하지 않아도 안전한 문자들이다.
A-Z a-z 0-9 - _ . ~
JavaScript에서의 인코딩 함수
encodeURI(url): URL 전체를 인코딩할 때 쓴다. URL 구조에 필요한 문자는 인코딩하지 않는다.
encodeURIComponent(value): URL의 파라미터 값처럼 URL의 일부를 인코딩할 때 쓴다. 예약 문자를 포함해 모든 특수문자를 인코딩한다.
파라미터 값에 encodeURI 대신 encodeURIComponent를 써야 하는 이유: &와 =는 encodeURI에서 인코딩되지 않는데, 파라미터 값 안에 이 문자가 있으면 서버가 파라미터를 잘못 파싱한다.
언어별 URL 인코딩 함수
Python
from urllib.parse import quote, urlencode
quote("서울 날씨") # '%EC%84%9C%EC%9A%B8%20%EB%82%A0%EC%94%A8'
urlencode({"q": "서울 날씨", "lang": "ko"})
PHP
urlencode("서울 날씨"); // 폼 데이터 방식
rawurlencode("서울 날씨"); // RFC 3986 방식
실제로 발생하는 버그 사례
카카오 API나 네이버 API에 한글 검색어를 파라미터로 넘길 때 인코딩을 빠뜨리면 400 Bad Request나 빈 결과가 반환된다. URLSearchParams나 axios의 params 옵션을 쓰면 자동으로 처리된다.
// 직접 연결 — 인코딩 누락 위험
fetch(`/api/search?q=서울 날씨`);
// URLSearchParams 사용 — 자동 인코딩
const params = new URLSearchParams({ q: "서울 날씨" });
fetch(`/api/search?${params}`);