네이버 블로그 글 링크를 카카오톡으로 보냈더니, 주소가 %ED%95%9C%EA%B8%80 같은 코드 덩어리로 바뀌어 있다. 상대방이 "이거 이상한 사이트 아냐?"라고 되물어올 때의 당혹감. URL에 한글이 들어가면 생기는 전형적인 현상이다.
왜 한글 URL이 깨져 보이는가
URL은 원래 영문 알파벳, 숫자, 일부 특수문자만 허용한다. RFC 3986이라는 국제 표준에서 그렇게 정했다. 한글, 일본어, 중국어 같은 비영문 문자가 URL에 들어가면, 브라우저가 자동으로 UTF-8 기준 퍼센트 인코딩(Percent-encoding)을 적용한다.
한글 → UTF-8 바이트 변환 → 퍼센트(%) + 16진수로 표현
예: "가" → 0xEA 0xB0 0x80 → %EA%B0%80
주소창에서는 한글로 보이지만, 실제 HTTP 요청에는 인코딩된 값이 전달된다. 복사-붙여넣기 할 때 인코딩된 상태 그대로 나오는 것뿐이다.
인코딩해야 하는 문자, 안 해도 되는 문자
| 구분 | 문자 | 인코딩 필요 |
|---|---|---|
| 영문 대소문자 | A-Z, a-z | 불필요 |
| 숫자 | 0-9 | 불필요 |
| 비예약 특수문자 | - _ . ~ | 불필요 |
| 예약 문자 | : / ? # & = @ | 문맥에 따라 필요 |
| 한글, 한자, 이모지 | 가, 漢, 😀 | 필수 |
| 공백 | (스페이스) | 필수 (%20 또는 +) |
인코딩과 디코딩의 차이
- 인코딩(Encoding)
- 한글이나 특수문자를 %XX 형태로 변환하는 것. 서버에 데이터를 보내거나 URL 파라미터를 만들 때 필요하다. 예: "검색어" →
%EA%B2%80%EC%83%89%EC%96%B4 - 디코딩(Decoding)
- %XX 코드를 원래 문자로 되돌리는 것. 깨진 URL을 사람이 읽을 수 있게 복원할 때 쓴다. 예:
%EA%B2%80%EC%83%89%EC%96%B4→ "검색어"
encodeURI와 encodeURIComponent 차이
자바스크립트에서 URL 인코딩을 할 때 이 두 함수를 혼동하는 경우가 많다.
| 함수 | 보존하는 문자 | 용도 |
|---|---|---|
encodeURI | : / ? # & = @ 등 URL 구조 문자 | 전체 URL 인코딩 |
encodeURIComponent | 영문, 숫자, - _ . ~ 만 | 쿼리 파라미터 값 인코딩 |
주의 쿼리스트링의 값 부분에encodeURI를 쓰면 &나 = 같은 구분자가 그대로 남아서 파라미터가 꼬일 수 있다. 값만 인코딩할 때는 반드시encodeURIComponent를 써야 한다.
깨진 URL 원래대로 되돌리기
카톡이나 메신저에서 받은 URL이 %로 도배되어 있으면, 어디로 연결되는 건지 확인조차 어렵다. 이럴 때 URL 인코딩 변환기에 해당 주소를 붙여넣고 디코딩을 누르면 원래 한글 주소가 바로 복원된다. 반대로 API 호출이나 HTML에서 한글 파라미터를 넘겨야 하는 상황이라면 인코딩 기능을 쓰면 된다.
URL 인코딩은 원리를 알면 간단한데, 직접 변환하려면 UTF-8 바이트 단위로 계산해야 해서 번거롭다. 한두 글자는 외워서 될 수도 있지만, 문장 단위로 넘어가면 도구 없이는 실수가 나온다.