URL 디코딩·인코딩 사용법
- 디코딩: 주소창이나 로그에서 복사한 URL, 또는
%ED%95%9C%EA%B8%80같은 퍼센트 인코딩 텍스트를 붙여 넣으면 읽을 수 있는 한글이 바로 나옵니다. - 전체 URL이면 프로토콜, 호스트(한글 도메인은 유니코드 형태도), 경로, 프래그먼트와 함께 쿼리 매개변수가 하나씩 디코딩된 표로 나옵니다.
- ‘+를 공백으로 읽기’는 쿼리 문자열과 폼 데이터에서는 켜 두세요. 거기서는 +가 공백을 뜻합니다. 다른 텍스트에서는 끄면 +가 그대로 남습니다.
- 인코딩: 인코딩을 고르고 텍스트를 입력한 뒤 방식을 고릅니다. 쿼리 값 하나를 넣을 때는 보통 URL 일부를 씁니다.
- 결과 옆의 복사를 누르면 끝입니다. 잘못된 % 코드가 있으면 몇 번째 글자인지 알려 줍니다.
한글 주소가 %EC…로 바뀌는 이유
URL에는 영문, 숫자와 몇 가지 기호만 쓸 수 있고, 그중 /, ?, &, =, #는 주소의 구조를 나누는 역할을 합니다. 그 밖의 문자는 바이트 단위로 % 기호와 16진수 두 자리로 적습니다. 이것이 RFC 3986에 정의된 퍼센트 인코딩입니다. 공백은 바이트 32, 16진수로 20이라 %20이 됩니다.
한글은 먼저 UTF-8 바이트로 바뀝니다. 현대 한글 음절은 UTF-8에서 한 글자가 3바이트이므로 퍼센트 코드 세 개, 곧 아홉 글자가 됩니다. ‘한’은 %ED%95%9C, ‘한글’은 %ED%95%9C%EA%B8%80입니다. 그래서 한글 URL은 첫 글자가 대부분 %EA부터 %ED 사이로 시작합니다. 브라우저 주소창은 이것을 다시 한글로 보여 주지만, 주소를 복사해 메신저나 문서에 붙여 넣으면 인코딩된 형태로 바뀌는 경우가 많아 길고 알아보기 힘든 링크가 됩니다. 이 도구에 붙여 넣으면 원래 한글로 돌아옵니다.
URL 디코딩하면 한글이 깨지는 경우: EUC-KR(CP949)
오래된 국내 게시판, 쇼핑몰, 공공기관 시스템 중에는 지금도 한글을 UTF-8이 아닌 EUC-KR(윈도우의 CP949, MS949)로 인코딩하는 곳이 있습니다. EUC-KR에서는 한 글자가 2바이트라 ‘한글’이 %C7%D1%B1%DB처럼 여섯 글자씩 됩니다. 이 바이트를 UTF-8로만 읽는 디코더는 물음표가 든 마름모(�)나 엉뚱한 글자를 보여 주는데, 이것이 흔히 말하는 ‘URL 디코딩 한글 깨짐’입니다.
| 인코딩 | ‘한글’의 URL 표기 | 한 글자 |
|---|---|---|
| UTF-8 (오늘날의 표준) | %ED%95%9C%EA%B8%80 | 3바이트, 9글자 |
| EUC-KR / CP949 (옛 국내 시스템) | %C7%D1%B1%DB | 2바이트, 6글자 |
이 도구는 먼저 UTF-8로 읽어 보고, 올바른 UTF-8이 아니면 EUC-KR(CP949)로 다시 읽은 뒤 결과의 문자 인코딩 줄에 그 사실을 표시합니다. %C7%D1%B1%DB를 넣으면 “한글”와 함께 EUC-KR(CP949)이 나옵니다. 두 인코딩은 같은 바이트를 동시에 올바르게 해석하는 일이 거의 없어 이 순서로 판별해도 틀리는 일이 드뭅니다. 반대로 서버에 EUC-KR 형식으로 보내야 한다면, 이 도구의 인코딩은 언제나 UTF-8이므로 Java의 URLEncoder.encode(s, "MS949")나 Python의 urllib.parse.quote(s, encoding='cp949')처럼 코드에서 인코딩을 지정하세요.
예시로 보기
입력란의 예시는 쇼핑몰 검색 결과 링크입니다: https://www.example.com/%EC%87%BC%ED%95%91/search?q=%EB%AC%B4%EC%84%A0+%EC%9D%B4%EC%96%B4%ED%8F%B0&cat=%EC%A0%84%EC%9E%90%EC%A0%9C%ED%92%88&page=2#reviews. 한 겹으로 인코딩된 퍼센트 코드 33개가 들어 있고, 디코딩하면 다음과 같습니다.
https://www.example.com/쇼핑/search?q=무선 이어폰&cat=전자제품&page=2#reviews
호스트는 www.example.com, 경로는 /쇼핑/search입니다. 쿼리 매개변수 표에는 q = “무선 이어폰”, cat = “전자제품”, page = “2”의 3개가 나옵니다. 검색어 ‘무선 이어폰’은 한글 다섯 글자가 15바이트, 퍼센트 코드 15개가 되고, 가운데 공백은 폼 방식대로 +로 적혀 있습니다. ‘전자제품’은 네 글자라 코드 12개, 경로의 ‘쇼핑’은 6개로 모두 33개입니다. #reviews 부분(프래그먼트)은 서버로 전송되지 않고 브라우저 안에서만 쓰입니다.
encodeURIComponent, encodeURI, 폼 인코딩의 차이
네 가지 인코딩 방식은 어떤 문자를 그대로 두느냐가 다릅니다. 아래 표는 이 도구의 코드로 각 문자를 실제로 인코딩한 결과입니다.
| 문자 | URL 일부 | URL 전체 | 폼 데이터 | 엄격한 RFC 3986 | |
|---|---|---|---|---|---|
| 공백 | %20 | %20 | + | %20 |
& | 앰퍼샌드 | %26 | & | %26 | %26 |
+ | 더하기 | %2B | + | %2B | %2B |
/ | 슬래시 | %2F | / | %2F | %2F |
= | 등호 | %3D | = | %3D | %3D |
? | 물음표 | %3F | ? | %3F | %3F |
# | 샵 | %23 | # | %23 | %23 |
! | 느낌표 | ! | ! | %21 | %21 |
한 | 한글 한 글자 | %ED%95%9C | %ED%95%9C | %ED%95%9C | %ED%95%9C |
😀 | 이모지 | %F0%9F%98%80 | %F0%9F%98%80 | %F0%9F%98%80 | %F0%9F%98%80 |
- URL 일부는 JavaScript의
encodeURIComponent입니다. URL에서 의미가 있는 문자를 모두 인코딩하므로 쿼리 값 하나, 경로 한 조각, 다른 URL 안에 넣는 URL 전체에 알맞습니다. - URL 전체는
encodeURI로,; , / ? : @ & = + $ #를 그대로 두어 주소가 계속 동작합니다. 링크에 섞인 한글과 공백을 정리할 때 쓰고,&가 들어갈 수 있는 값 하나에는 쓰지 마세요. - 폼 데이터는 브라우저가 폼을 보낼 때의 방식(
application/x-www-form-urlencoded)으로, 공백을+로 씁니다. Java의URLEncoder.encode(s, StandardCharsets.UTF_8)도 이 방식이라 공백이+가 됩니다. - 엄격한 RFC 3986은 encodeURIComponent에
! ' ( ) *까지 인코딩한 것으로, OAuth 서명이나 일부 API가 요구합니다.
+와 %20, 그리고 이중 인코딩
공백은 쿼리 문자열에서만 +로도 쓸 수 있습니다. 경로에서는 +가 그냥 더하기 기호이고, 쿼리 값 안의 진짜 더하기 기호는 %2B로 보내야 합니다. 그래서 C%2B%2B는 “C++”로 디코딩됩니다.
이미 인코딩된 텍스트를 한 번 더 인코딩하면 %가 %25로 바뀌어 %20이 %2520이 됩니다. 리다이렉트 링크나 광고·추적 매개변수처럼 URL이 두 시스템을 거칠 때 자주 생깁니다. 디코더는 퍼센트 코드가 남아 있는 동안 계속 풀고 몇 겹이었는지 알려 줍니다. %25ED%2595%259C는 2겹이며 “한”이 됩니다. 한 겹씩 확인하려면 옵션을 끄세요.
한글 도메인(국제화 도메인)
한글이나 다른 문자로 된 도메인은 Punycode(RFC 3492)라는 ASCII 형태로 전송되며 xn--로 시작합니다. 예를 들어 한국.kr은 xn--3e0b707e.kr입니다. 어느 쪽을 붙여 넣어도 결과에 브라우저가 실제로 보내는 형태와 유니코드 형태가 함께 나옵니다. Punycode는 퍼센트 인코딩이 아니므로 도메인을 % 코드로 쓰는 일은 없습니다.
팁과 주의점
- 쿼리 값은 하나씩 인코딩한 다음
&와=로 이으세요. 완성된 쿼리 문자열 전체를 encodeURIComponent로 인코딩하면 구분 기호까지 인코딩됩니다. - 퍼센트 인코딩은 암호화가 아닙니다. 누구나 디코딩할 수 있으니 비밀번호나 토큰을 URL에 넣어 공유하지 마세요.
- URL 안의 토큰이
eyJ로 시작하면 JWT 디코딩으로, 그 밖의 Base64는 Base64 디코딩으로 풀어 보세요. 로그에서 URL만 골라내려면 정규식 테스트가 편합니다.
디코딩과 인코딩은 모두 브라우저 안에서 이루어집니다. 붙여 넣은 URL은 업로드되거나 저장되지 않으며, 페이지를 새로 고치면 사라집니다. 링크에는 로그인 세션이나 개인정보가 들어 있는 경우가 많으니 중요한 점입니다.
자주 묻는 질문
URL의 %20은 무슨 뜻인가요?
인코딩된 공백입니다. 20은 공백 문자의 16진수 값입니다. 한글은 한 글자가 %EC%95%88처럼 코드 세 개가 되며, URL을 여기에 붙여 넣으면 모두 읽을 수 있는 글자로 돌아옵니다.
URL을 디코딩했는데 한글이 깨져요.
원래 주소가 UTF-8이 아니라 EUC-KR(CP949)로 인코딩된 경우입니다. 한 글자가 %C7%D1처럼 코드 두 개라면 거의 확실합니다. 이 도구는 UTF-8로 읽히지 않으면 EUC-KR로 다시 읽으므로 그대로 붙여 넣으면 됩니다.
URL에 %2520이 들어 있는 이유는 무엇인가요?
두 번 인코딩되었기 때문입니다. 처음에 공백이 %20이 되고, 두 번째에 % 자체가 %25가 되었습니다. 디코더가 겹을 모두 찾아 풉니다.
encodeURI와 encodeURIComponent는 무엇이 다른가요?
encodeURI는 URL 전체를 인코딩하면서 / ? & = #처럼 구조를 만드는 문자는 그대로 둡니다. encodeURIComponent는 쿼리 값이나 경로 한 조각을 인코딩하며 그 문자들까지 인코딩해, 주변 URL을 망가뜨리지 않게 합니다.
붙여 넣은 URL이 어딘가로 전송되나요?
아니요. 브라우저의 JavaScript로 디코딩하고 인코딩하며, 서버로 아무것도 보내지 않고 입력한 내용을 저장하지도 않습니다.
최종 수정일: 2026년 10월 16일