url encoding web percent-encoding

URL 인코더 및 디코더: 웹 주소를 안전하고 즉각적으로 처리하세요

URL을 빠르고 안전하게 인코딩 및 디코딩하세요. 웹에서 안전하게 전송하기 위해 특수 문자를 퍼센트 인코딩 형식으로 변환합니다.

URL에 인코딩이 필요한 이유

URL은 문자로 구성되어 있지만, 모든 문자를 직접 "안전하게" 사용할 수 있는 것은 아닙니다. URL은 인터넷을 통해 다양한 시스템을 거쳐 전송되는데, 이 시스템들은 특정 문자를 특별한 의미로 해석할 수 있습니다. 예를 들어 ?는 쿼리 문자열, &는 파라미터 구분자, #는 프래그먼트 식별자로 사용됩니다. 또한 중국어나 아랍어 같은 비ASCII 문자도 있으며, 오래된 HTTP 인프라에서는 일부 문자가 깨질 수 있습니다.

URL 인코딩(공식 명칭: 퍼센트 인코딩)은 안전하지 않은 문자를 %와 해당 문자의 바이트 값을 나타내는 두 자리 16진수로 대체하여 이 문제를 해결합니다.

공백 (0x20) → %20
골뱅이 기호 (0x40) → %40
슬래시 (0x2F) → %2F

RFC 표준

URL 인코딩은 RFC 3986(Uniform Resource Identifiers)에 정의되어 있습니다. 이 표준에 따르면:

비예약 문자 — 인코딩 없이 URL 어디서나 안전하게 사용할 수 있는 문자:

  • A–Z, a–z, 0–9
  • -, _, ., ~

예약 문자 — URI에서 특별한 의미를 가지며, 데이터로 사용할 때는 퍼센트 인코딩해야 하는 문자:

  • : / ? # [ ] @ ! $ & ' ( ) * + , ; =

그 외 모든 문자——공백, 비ASCII 문자, ", <, >, {, } 등——은 퍼센트 인코딩해야 합니다.


퍼센트 인코딩 실습

공백 인코딩

공백 문자(U+0020)는 %20으로 인코딩됩니다. 쿼리 문자열에서는 %20 대신 +를 사용하는 경우도 있습니다. 이는 HTML 폼 URL 인코딩(application/x-www-form-urlencoded) 표준에서 유래한 것으로, 공백을 +로 인코딩합니다. 두 가지는 서로 다릅니다:

  • %20 — RFC 3986 퍼센트 인코딩(경로, 헤더의 공백)
  • + — HTML 폼 인코딩(쿼리 문자열의 공백)

디코딩 시에는 어떤 방식이 적용되는지 반드시 파악하여 버그를 방지하세요.

비ASCII 문자

비ASCII 문자는 먼저 UTF-8로 인코딩된 후, 각 바이트가 퍼센트 인코딩됩니다:

한자 中 (U+4E2D)
UTF-8 바이트: 0xE4 0xB8 0xAD
퍼센트 인코딩: %E4%B8%AD

한국어 단어 안녕도 동일한 방식으로 UTF-8 바이트로 변환된 후 퍼센트 인코딩됩니다.


JavaScript 인코딩 함수

JavaScript는 URL 인코딩을 위한 여러 내장 함수를 제공합니다:

encodeURI()

전체 URI를 인코딩합니다——URL 구조를 유지하면서 전체 URL을 인코딩하도록 설계되었습니다. URI 구문의 일부인 문자(; , / ? : @ & = + $ #)는 인코딩하지 않습니다.

encodeURI("https://example.com/search?q=hello world&lang=한국어")
// "https://example.com/search?q=hello%20world&lang=%ED%95%9C%EA%B5%AD%EC%96%B4"

encodeURIComponent()

URI 컴포넌트를 인코딩합니다——쿼리 파라미터 값 같은 개별 값을 인코딩하도록 설계되었습니다. A–Z a–z 0–9 - _ . ! ~ * ' ( ) 외의 모든 것을 인코딩합니다.

encodeURIComponent("hello world & more")
// "hello%20world%20%26%20more"

encodeURIComponent("https://example.com")
// "https%3A%2F%2Fexample.com"

어떤 것을 사용해야 할까요

시나리오 함수
전체 URL 인코딩 encodeURI()
쿼리 파라미터 값 인코딩 encodeURIComponent()
경로 세그먼트 인코딩 encodeURIComponent()
다른 URL에 포함할 URL 인코딩 encodeURIComponent()

대응하는 디코딩 함수

decodeURI(encodedURI)
decodeURIComponent(encodedComponent)

더 이상 사용되지 않는 escape()unescape() 함수는 절대 사용하지 마세요——비ASCII 문자를 다르게 처리하여 잘못된 결과를 만들어냅니다.


흔한 함정과 주의사항

이중 인코딩

이미 인코딩된 문자열을 다시 인코딩하는 것은 흔한 버그입니다:

encodeURIComponent(encodeURIComponent("hello world"))
// "hello%2520world"
// %25는 %의 인코딩이므로 %20이 %2520이 됩니다

인코딩하기 전에 값이 이미 인코딩되어 있는지 반드시 확인하세요.

+%20 함정

+를 공백으로 사용하는 쿼리 문자열을 decodeURIComponent로 디코딩하면, +는 공백으로 디코딩되지 않습니다——먼저 +%20으로 교체하거나 URLSearchParams API를 사용해야 합니다:

new URLSearchParams("q=hello+world").get("q")
// "hello world" ✓

decodeURIComponent("hello+world")
// "hello+world" ✗ — 여전히 리터럴 더하기 기호

프래그먼트 식별자

URL의 # 문자는 프래그먼트 식별자(페이지 내 앵커)의 시작을 나타냅니다. 데이터에 #가 포함된 경우 %23으로 인코딩해야 합니다. 그렇지 않으면 브라우저는 그 이후의 모든 것을 프래그먼트로 처리합니다.

국제화 도메인 이름(IDN)

비ASCII 문자를 포함한 도메인 이름(예: bücher.de)은 퍼센트 인코딩이 아닌 Punycode 인코딩을 사용합니다. 브라우저는 IDN을 내부적으로 Punycode로 변환합니다: bücher.dexn--bcher-kva.de.


URL 구조 참조

RFC 3986에 따르면 URL은 다음 컴포넌트로 구성됩니다:

scheme://userinfo@host:port/path?query#fragment
컴포넌트 예시 인코딩 규칙
Scheme https 문자, 숫자, +, -, .
Host example.com 도메인 레이블 + 점
Port 8080 숫자만
Path /search/results %XX로 인코딩(비예약 문자 + :@!$&'()*+,;= 제외)
Query q=hello+world 폼 데이터에서 공백은 +, 일반적으로는 %20
Fragment #section-2 서버로 전송되지 않음; 브라우저 전용

서버 측 고려사항

URL 정규화

서버는 처리 전에 URL을 정규화해야 합니다——예를 들어 %41(A로 디코딩)과 A를 동일하게 처리합니다. 그러나 일부 문자는 인코딩된 상태와 인코딩되지 않은 상태에서 다른 의미를 가집니다: 경로의 /%2F——보안상의 이유(경로 탐색 방지)로 많은 웹 서버는 이 둘을 다르게 처리합니다.

URL 파라미터를 통한 SQL 인젝션

URL 디코딩 후에도 URL 파라미터를 데이터베이스 쿼리에 사용하기 전에 반드시 살균하고 검증하세요. URL 인코딩은 보안 경계가 아닙니다.


도구 및 API

브라우저의 URL API

최신 브라우저와 Node.js는 URL을 구조화된 방식으로 다루기 위한 URL API를 제공합니다:

const url = new URL("https://example.com/search?q=hello world&page=1");
console.log(url.searchParams.get("q")); // "hello world" (자동 디코딩)

url.searchParams.set("q", "new value & special");
console.log(url.href);
// https://example.com/search?q=new+value+%26+special&page=1

URL API는 인코딩/디코딩을 투명하게 처리하므로, 일반적으로 encodeURIComponent를 수동으로 호출하는 것보다 권장되는 방식입니다.


요약

URL 인코딩은 모든 웹 개발자가 매일 접하는 기본 개념으로, 대부분 자신도 모르게 사용하고 있습니다. 기억해야 할 핵심 사항:

  1. 퍼센트 인코딩(%XX)은 URI에서 안전하지 않은 문자를 인코딩하는 표준 메커니즘입니다.
  2. 개별 값에는 encodeURIComponent()를, 전체 URL에는 encodeURI()를 사용하세요.
  3. 쿼리 문자열에서 +%20의 차이를 인식하세요.
  4. 이중 인코딩을 피하세요——인코딩하기 전에 문자열이 이미 인코딩되어 있는지 확인하세요.
  5. 프로그래밍 방식으로 URL을 다룰 때는 현대적인 URLURLSearchParams API를 우선 사용하세요.