URL 인코딩 / 디코딩

URL에서 안전하게 사용할 수 있도록 텍스트를 퍼센트 인코딩하거나, 인코딩된 URL을 다시 읽기 쉬운 텍스트로 디코딩합니다 — 양방향 지원, 입력하는 즉시 실시간으로 변환됩니다.

조회수 1,052회

작동 원리

URL은 좁은 문자 집합만 안전하게 담을 수 있습니다: 문자, 숫자, 그리고 네 가지 "예약되지 않은"(unreserved) 기호인 - _ . ~입니다. 그 외의 모든 문자는 %XX 형태의 세 문자로 다시 쓰입니다. 여기서 XX는 해당 문자의 바이트 값을 16진수로 나타낸 것이며, 이것이 바로 RFC 3986 퍼센트 인코딩입니다. URL의 구조를 이루는 문자들(? # / : @ & =, "예약된"(reserved) 집합)도 구분자가 아니라 값 안에 나타날 때는 인코딩됩니다. 그렇지 않으면 쿼리 값 안의 순수한 &가 다음 매개변수의 시작으로 읽히기 때문입니다.

ASCII가 아닌 텍스트는 문자 단위가 아니라 바이트 단위로 인코딩됩니다: 이 도구는 먼저 문자열을 UTF-8로 변환한 다음, 그 결과로 나온 각 바이트를 16진수로 인코딩합니다. 터키어 문자 "ç"는 UTF-8에서 두 바이트(0xC3 0xA7)이므로, 하나의 코드가 아니라 두 개의 퍼센트 블록인 %C3%A7가 됩니다. 구체적인 예로, İstanbul çayı & simit를 인코딩하면 %C4%B0stanbul%20%C3%A7ay%C4%B1%20%26%20simit가 됩니다. 공백이 %20이 되고, 예약 문자인 &%26이 되며, 악센트가 붙은 각 문자가 자신만의 다중 바이트 시퀀스로 확장되는 것을 확인할 수 있습니다.

실무에서는 요청을 직접 조립할 때 이 구분이 가장 중요해집니다: 누군가 보내준 쿼리 값이 포함된 웹훅 URL을 붙여넣거나, 마케팅 이메일의 추적 매개변수를 디코딩하거나, 인코딩되지 않은 원시 &#가 값 안에 섞여 들어가 데이터가 아닌 구분자로 읽히는 바람에 API 호출이 실패하는 이유를 알아내야 할 때입니다. 값을 먼저 인코딩한 다음 그 결과를 URL 템플릿에 대입하면 바로 이런 종류의 버그를 피할 수 있습니다.

알아두어야 할 사항

  • %20인가 +인가: RFC 3986 퍼센트 인코딩은 공백에 항상 %20을 사용합니다. + 방식은 다른, 더 오래된 표준인 application/x-www-form-urlencoded에 속하며, 이는 HTML 폼이 데이터를 전송할 때 사용하는 형식입니다 — 그리고 이 특정 본문 형식 안에서만 적용되며, 경로나 올바르게 퍼센트 인코딩된 쿼리 값 안에서는 절대 적용되지 않습니다. 둘을 혼동하는 것은 흔한 버그의 원인입니다: 폼 인코딩을 기대하는 서버는 퍼센트 인코딩된 문자열 안의 뜬금없는 +를 공백이 아니라 문자 그대로의 더하기 기호로 읽습니다.
  • URL 전체가 아니라 하나의 구성 요소만 인코딩하세요: 이 도구는 하나의 쿼리 값이나 경로 세그먼트를 위해 만들어졌습니다. https://를 포함한 전체 주소를 인코더에 통과시키면 URL을 유효하게 만드는 슬래시와 콜론까지 이스케이프되어 URL이 완전히 깨집니다.
  • 브라우저와 동일한 엔진: 브라우저 내장 함수인 encodeURIComponent/decodeURIComponent를 호출하므로, 결과는 실제 브라우저나 자바스크립트 fetch 호출이 만들어내는 것과 정확히 일치합니다 — 근사치가 아닙니다.
  • 왕복 변환은 손실이 없습니다: 문자열을 인코딩한 다음 그 결과를 디코딩하면 항상 정확히 원본 바이트로 돌아오므로, 결과를 디코딩해 원본 텍스트와 비교하는 방식으로 수작업 인코딩 결과를 손쉽게 검증할 수 있습니다.
  • 어떤 데이터도 브라우저를 벗어나지 않습니다: 인코딩과 디코딩은 전적으로 클라이언트 측에서 즉시 실행되며, 업로드가 전혀 없습니다.

자주 묻는 질문

공백이 왜 +가 아니라 %20이 되나요?

퍼센트 인코딩(RFC 3986)은 공백에 %20을 사용합니다. + 방식은 폼 본문에 쓰이는 오래된 application/x-www-form-urlencoded 형식에 한정된 것이지, 일반적인 URL 인코딩 방식이 아닙니다. 이 도구는 표준 %20 형식을 사용합니다 — 둘을 혼동하는 것은 쿼리 문자열을 직접 만들 때 흔히 발생하는 버그의 원인입니다.

URL 전체를 인코딩하나요, 아니면 일부만 인코딩하나요?

이 도구는 하나의 구성 요소(쿼리 값이나 경로 세그먼트)를 인코딩하도록 설계되었습니다 — "https://"를 포함한 URL 전체를 인코딩하면 슬래시까지 이스케이프되어 URL이 깨지므로, 필요한 부분만 인코딩한 다음 그 결과를 나머지 주소에 다시 붙여넣으세요.

터키어나 악센트가 붙은 문자는 왜 하나 이상의 %XX 블록으로 변환되나요?

인코딩은 눈에 보이는 문자가 아니라 바이트 단위로 작동하기 때문입니다. UTF-8은 터키어 ç, ğ, ı, ş나 이모지 같은 대부분의 비ASCII 문자를 2~4바이트로 표현하며, 각 바이트는 자신만의 %XX 쌍을 가집니다. 그래서 "ç"는 %C3%A7(두 블록)이 되고, 이모지는 인코딩되면 여덟 자 이상으로 확장될 수 있습니다.

예약 문자와 비예약 문자의 차이는 무엇인가요?

비예약 문자(문자, 숫자, - _ . ~)는 항상 안전하며 인코딩할 필요가 전혀 없습니다. 예약 문자(? # / : @ & = 등)는 URL 안에서 구조적인 의미를 갖습니다 — 경로와 쿼리를 구분하거나 한 매개변수를 다음 매개변수와 구분합니다 — 그래서 구분자 역할을 할 때가 아니라 값 안의 리터럴 데이터로 나타날 때만 인코딩됩니다.

제 텍스트가 어딘가로 전송되나요?

아니요 — 인코딩과 디코딩은 브라우저 안에서 즉시 이루어지며, 어떤 것도 서버로 업로드되지 않습니다.

댓글

아직 댓글이 없습니다 — 첫 댓글을 남겨보세요!

비슷한 도구