블로그 글 링크를 카카오톡으로 보내려고 주소창에서 복사했더니, %ED%95%9C%EA%B8%80 같은 문자가 잔뜩 붙어 나왔다. 원래는 한글이 포함된 깔끔한 URL이었는데, 어디서부터 이렇게 바뀐 건지 모르겠다.
URL에 한글을 쓸 수 없는 이유
URL은 기본적으로 ASCII 문자만 허용된다. 영문 알파벳, 숫자, 일부 특수문자(-, _, ., ~)만 그대로 쓸 수 있고, 그 외의 문자는 퍼센트 인코딩(Percent-encoding)이라는 방식으로 변환된다.
한글 "한"을 예로 들면, UTF-8로 인코딩하면 3바이트(ED 95 9C)가 되고, 각 바이트 앞에 %를 붙여서 %ED%95%9C이 된다. 브라우저 주소창에서는 한글로 보여주지만, 실제로 서버에 전송되는 값은 이 인코딩된 문자열이다.
인코딩과 디코딩의 차이
- 인코딩 (Encoding)
- 한글, 공백, 특수문자를 %XX 형식으로 변환. 예: "검색어" →
%EA%B2%80%EC%83%89%EC%96%B4 - 디코딩 (Decoding)
- %XX 형식을 원래 문자로 복원. 예:
%EA%B2%80%EC%83%89%EC%96%B4→ "검색어"
주의 API 요청을 보낼 때 파라미터에 한글이 포함되면 반드시 인코딩해야 한다. 인코딩 없이 보내면 서버에서 깨진 문자로 인식해서 400 Bad Request 에러가 난다.
깨진 URL 원래대로 되돌리기
받은 링크가 %로 도배되어 있어서 어떤 내용인지 알 수 없다면, 디코딩을 하면 된다. 반대로 한글 URL을 API나 이메일 링크에 넣어야 할 때는 인코딩이 필요하다.
복사한 URL을 URL 인코딩 변환 도구에 붙여넣으면 즉시 원문이 보인다. 인코딩 모드로 전환하면 반대 작업도 가능하고, encodeURIComponent 옵션을 켜면 콜론(:)이나 슬래시(/) 같은 URL 구조 문자까지 전부 변환해준다. 쿼리 파라미터 값만 인코딩할 때 필요한 옵션이다.
개발할 때 주의할 점
- 이중 인코딩 금지: 이미 인코딩된 문자열을 다시 인코딩하면
%25ED처럼 %까지 인코딩된다. 디코딩해도 원본이 안 나온다. - encodeURI vs encodeURIComponent: 전체 URL을 인코딩할 때는
encodeURI, 파라미터 값만 인코딩할 때는encodeURIComponent를 쓴다. - 서버 인코딩 불일치: 서버가 EUC-KR을 쓰는데 UTF-8로 인코딩하면 한글이 깨진다. 서버 인코딩을 먼저 확인해야 한다.
URL이 깨져 보이는 건 고장이 아니라 정상적인 인코딩 결과다. 원문을 확인하고 싶을 때 디코딩, 안전하게 전송하고 싶을 때 인코딩. 이 구분만 알면 된다.