모든 텍스트를 URL 인코딩·디코딩

쿼리 값, 경로 조각, 전체 URL을 퍼센트 인코딩하거나 %XX 시퀀스를 읽을 수 있는 텍스트로 되돌리세요. UTF-8, 폼 방식의 + 공백, 줄 단위 값을 지원하며 어떤 것도 브라우저 밖으로 나가지 않습니다.

텍스트를 URL 인코딩·디코딩하는 방법

  1. 텍스트, 값 또는 URL을 입력 상자에 붙여 넣으세요.
  2. 인코딩 유형을 고르세요. 쿼리 값 하나나 경로 조각 하나라면 컴포넌트를 그대로 두세요. 공백과 비ASCII 문자만 고치면 되는 전체 주소라면 전체 URL을, HTML 폼 전송으로 읽힐 데이터라면 폼을 고르세요.
  3. 인코딩 또는 디코딩을 누르세요. 줄마다 값 하나를 선택해 두면 각 줄이 따로 처리되므로 매개변수나 URL 목록 전체를 한 번에 변환할 수 있습니다.
  4. 결과를 복사하거나 결과를 입력으로 사용을 눌러 다시 실행하세요. 예를 들어 두 번 인코딩된 값을 한 겹 벗길 때 쓸 수 있습니다.

쿼리 문자열이 있는 완전한 URL을 디코딩하면 이 도구는 각 매개변수의 이름과 값도 평문으로 나열합니다. 긴 추적 URL이나 리디렉션 URL을 읽는 가장 빠른 방법입니다.

퍼센트 인코딩이란

URL에는 제한된 ASCII 문자만 들어갈 수 있고, 그중 여럿은 역할이 있습니다. ?는 쿼리를 시작하고, &는 매개변수를 구분하고, #은 프래그먼트를 시작하며, /는 경로 조각을 구분합니다. 나머지 문자가 URL에 들어가는 방법이 퍼센트 인코딩입니다. 각 문자는 UTF-8 바이트로 바뀌고, 각 바이트는 %와 16진수 두 자리로 적힙니다. 공백은 1바이트라서 %20이 되고, é는 2바이트라서 %C3%A9, 😀 같은 이모지는 4바이트라서 %F0%9F%98%80이 됩니다. 디코딩은 이 과정을 거꾸로 되돌립니다.

규칙은 URI 문법을 정의하는 표준인 RFC 3986 2절(영문)에서 나옵니다. 이 문서는 16진수를 대문자로 쓰기(%3a가 아니라 %3A)를 권장하고, 텍스트를 먼저 UTF-8 바이트로 인코딩해야 하며, 구현체는 같은 문자열을 두 번 이상 퍼센트 인코딩하거나 디코딩해서는 안 된다고 경고합니다.

예약 문자와 비예약 문자 (RFC 3986)

RFC 3986은 URL에 들어갈 수 있는 문자를 두 그룹으로 나눕니다.

  • 비예약 문자: 영문자 A–Z a–z, 숫자 0–9, 그리고 - . _ ~. 인코딩이 필요 없고 인코딩하든 안 하든 같은 뜻입니다.
  • 예약 문자: 일반 구분자 : / ? # [ ] @와 하위 구분자 ! $ & ' ( ) * + , ; =. 구조를 나타낼 수 있으므로, URL 문법의 일부가 아니라 내 데이터의 일부일 때는 반드시 퍼센트 인코딩해야 합니다.

그 밖의 모든 문자, 즉 공백, % 자체, 따옴표, 꺾쇠괄호, 모든 비ASCII 문자는 URL에 그대로 쓸 수 없고 항상 인코딩이 필요합니다. 가장 흔한 것은 다음과 같습니다.

문자인코딩중요한 이유
공백%20 (폼 데이터에서는 +)URL에 아예 쓸 수 없음
&%26새 쿼리 매개변수가 시작됨
=%3D매개변수 이름과 값이 갈라짐
?%3F쿼리 문자열이 시작됨
#%23뒤의 모든 내용이 프래그먼트로 잘려 나가며, 프래그먼트는 서버로 전송되지 않음
/%2F경로 조각이 하나 더 생김
+%2B폼 인코딩 쿼리 문자열에서는 공백으로 읽힘
%%25이스케이프의 시작으로 읽힘
: @%3A %40스킴, 자격 증명, 호스트를 구분함
é%C3%A9비ASCII 문자이며 2바이트 UTF-8로 인코딩됨

컴포넌트, 전체 URL, RFC 3986, 폼: 무엇을 쓸까

같은 입력도 결과가 들어갈 곳에 따라 다르게 인코딩됩니다. 입력 Tom & Jerry's (2024)/ü의 경우는 다음과 같습니다.

  • 컴포넌트는 Tom%20%26%20Jerry's%20(2024)%2F%C3%BC를 만듭니다. 영문자, 숫자, - _ . ! ~ * ' ( )를 제외한 모든 것을 인코딩하는 JavaScript의 encodeURIComponent입니다. 쿼리 값 하나, 경로 조각 하나, 또는 리디렉션 대상처럼 다른 URL의 매개변수 안에 넣을 URL에 쓰세요.
  • 엄격한 RFC 3986은 Tom%20%26%20Jerry%27s%20%282024%29%2F%C3%BC를 만듭니다. encodeURIComponent는 그대로 두지만 RFC 3986이 하위 구분자로 예약한 ! ' ( ) *도 추가로 인코딩합니다. 엄격한 파서나 요청 서명 방식이 RFC 집합 그대로를 요구할 때 쓰세요.
  • 폼은 Tom+%26+Jerry%27s+%282024%29%2F%C3%BC를 만듭니다. WHATWG URL 표준의 application/x-www-form-urlencoded 형식(영문)을 따릅니다. 영문자, 숫자, * - . _만 그대로 두고 공백은 +가 됩니다. HTML 폼과 URLSearchParams가 보내는 형식입니다.
  • 전체 URL은 Tom%20&%20Jerry's%20(2024)/%C3%BC를 만듭니다. encodeURI로, ; / ? : @ & = + $ , #이 완전한 URL 안에서 이미 제 역할을 하고 있다고 가정하고 그대로 둡니다. 공백이나 비ASCII 텍스트가 들어 있는 전체 주소를 정리할 때만 쓰세요. 값에는 절대 쓰지 마세요. 값 안의 &가 조용히 새 매개변수를 시작시킵니다.

%20 또는 +: URL의 공백

두 가지 관례가 나란히 존재합니다. RFC 3986의 URL 문법에서 공백은 언제나 %20이고 +는 그냥 더하기 기호입니다. 브라우저가 GET으로 폼을 전송할 때 쓰는 폼 인코딩 형식에서는 공백이 +로 적히고, 이 형식의 WHATWG 파서는 퍼센트 디코딩 전에 모든 +를 공백으로 바꿉니다. 그래서 ?q=a+b는 폼 데이터 파서에게 «a b»를 뜻하지만, 경로의 /a+b는 «a+b»를 뜻합니다.

디코더에 +를 공백으로 처리 옵션이 있는 이유입니다. 폼, 검색창, 대부분의 분석 도구가 만든 쿼리 문자열에는 선택하세요. 경로나 name+tag@example.com 같은 이메일 주소처럼 더하기 기호가 실제 문자인 값에는 선택하지 마세요. 이 주소는 name%2Btag%40example.com으로 인코딩됩니다.

코드로는 어떻게 하나

  • JavaScript: 값에는 encodeURIComponent()와 decodeURIComponent(), 전체 URL에는 encodeURI(), + 공백을 쓰는 폼 방식 쿼리 문자열에는 URLSearchParams를 씁니다(MDN, 영문 참고).
  • Python: urllib.parse.quote()는 기본적으로 /를 인코딩하지 않고 공백을 %20으로 적어 경로에 알맞고, quote_plus()는 /를 인코딩하고 공백을 +로 적어 폼 값에 알맞습니다(Python 문서, 영문 참고).
  • PHP: rawurlencode()는 RFC 3986을 따라 공백을 %20으로 적고, urlencode()는 공백을 +로 적습니다(PHP 매뉴얼, 영문 참고).

흔한 URL 인코딩 문제

이중 인코딩: %20 대신 %2520

URL에 %2520, %253A 같은 것이 들어 있다면, 이미 인코딩된 문자열을 다시 인코딩한 것입니다. %25는 인코딩된 퍼센트 기호입니다. 한 번 디코딩하고 결과를 확인하세요. 디코딩 결과에 여전히 퍼센트 시퀀스가 남아 있으면 이 도구가 경고하며, 결과를 입력으로 사용으로 다음 겹을 디코딩할 수 있습니다. 코드에서의 해결책은 URL을 만드는 시점에 각 값을 정확히 한 번만 인코딩하는 것입니다.

«Malformed URI sequence» 오류

엄격한 디코더는 16진수 두 자리가 뒤따르지 않는 %와 올바른 UTF-8이 아닌 바이트 시퀀스를 거부합니다. 이 디코더는 대신 관대합니다. 유효한 시퀀스는 모두 디코딩하고, 홀로 남은 %는 그대로 두며, 잘못된 바이트는 대체 문자 �로 바꾸고, 그렇게 했다고 알려 줍니다. 그래서 아무것도 얻지 못하는 대신 깨진 지점을 찾을 수 있습니다.

#이나 &에서 잘리는 값

매개변수가 잘려서 도착한다면 값에 인코딩되지 않은 #이나 &가 들어 있었던 것이며, 대개 URL을 문자열 이어 붙이기나 전체 URL 인코딩으로 만들었기 때문입니다. 값은 컴포넌트 모드로 인코딩하세요.

전체 URL을 인코딩하면 URL이 깨짐

완전한 URL을 컴포넌트 모드로 돌리면 https://가 https%3A%2F%2F가 됩니다. URL이 다른 URL 안의 매개변수 값일 때만 맞는 결과입니다. 그렇지 않다면 끼워 넣는 부분만 인코딩하거나 전체 URL 모드를 쓰세요.

관련 URL 도구

캠페인 링크는 UTM 빌더로 완성하고, 추적 매개변수는 URL 정리기로 제거하고, 링크가 거치는 모든 경로는 리디렉션 검사기로 확인하세요. 스크립트를 클릭 한 번으로 실행되는 브라우저 북마크로 만들려면 북마클릿 메이커가 퍼센트 인코딩을 대신해 줍니다. 작업하면서 RFC 같은 참고 페이지를 저장한다면 Marqly가 검색 가능한 하나의 라이브러리에 모아 줍니다. 개발자를 위한 Marqly(영문)를 참고하세요.

자주 묻는 질문

URL 인코딩은 무엇을 하나요?

URL 안에서 안전하지 않거나 특별한 의미가 있는 문자를 UTF-8 바이트마다 퍼센트 기호와 16진수 두 자리로 바꿉니다. 공백은 %20, &는 %26, é는 %C3%A9가 됩니다. 덕분에 어떤 텍스트도 URL 자체의 구조로 오해받지 않고 URL 안에 실려 갈 수 있습니다.

encodeURI와 encodeURIComponent는 무엇이 다른가요?

encodeURIComponent는 영문자, 숫자, - _ . ! ~ * ' ( )를 제외한 모든 문자를 인코딩하므로 쿼리 값 하나나 경로 조각 하나에 알맞습니다. encodeURI는 이미 구조를 갖춘 완전한 URL을 넘긴다고 가정하여 ; / ? : @ & = + $ , # 도 그대로 둡니다. 값에는 컴포넌트 모드를, 전체 주소에만 전체 URL 모드를 쓰세요.

공백은 %20과 + 중 무엇이어야 하나요?

쓰이는 자리에 따라 둘 다 맞습니다. %20은 URL 어디서나 동작합니다. +가 공백을 뜻하는 곳은 폼 인코딩 쿼리 문자열(application/x-www-form-urlencoded)뿐이며, HTML 폼과 URLSearchParams가 이 형식을 만듭니다. 경로에서 +는 글자 그대로의 더하기 기호입니다. 폼에서 나온 쿼리 문자열을 디코딩할 때는 «디코딩할 때 +를 공백으로 처리»를 선택하세요.

URL에 %2520이 들어 있는 이유는 무엇인가요?

두 번 인코딩되었기 때문입니다. 첫 번째 단계에서 공백이 %20이 되었고, 두 번째 단계에서 % 자체가 %25로 인코딩되어 %2520이 되었습니다. RFC 3986은 같은 문자열을 두 번 이상 인코딩하거나 디코딩해서는 안 된다고 규정합니다. 한 번 디코딩해서 %20이 돌아오는지 확인한 뒤 다시 디코딩하세요.

여러 URL을 한꺼번에 인코딩하거나 디코딩할 수 있나요?

네. 한 줄에 값 하나씩 붙여 넣고 «줄마다 값 하나»를 선택한 상태로 두세요. 각 줄이 따로 처리되므로 줄바꿈이 %0A로 바뀌지 않고 그대로 유지됩니다.

어떤 문자를 인코딩해야 하나요?

값의 일부일 때(URL 구조의 일부가 아닐 때)는 RFC 3986의 비예약 문자 집합(영문자, 숫자, 하이픈, 마침표, 밑줄, 물결표) 밖의 모든 문자를 인코딩해야 합니다. 공백, 비ASCII 문자, %, ? # & = / : @ + 같은 예약 구분자가 여기에 해당합니다.

입력한 텍스트가 업로드되나요?

아니요. 인코딩, 디코딩, 쿼리 문자열 분석은 모두 브라우저의 내장 JavaScript 함수로 실행되며 서버로 전송되는 것은 없습니다.

← 무료 도구

홈 · Marqly