DevToolBoxFREE
BlogAdvertise

URL 인코딩(퍼센트 인코딩) 해설: %20과 %3A의 진짜 의미

10분 읽기by DevToolBox

URL에서 %20, %3A, %2F를 본 적 있나요? 이것들은 퍼센트 인코딩된 문자입니다 — URL이 특수 문자를 안전하게 전달할 수 있게 하는 메커니즘입니다. 이 가이드는 바이트 수준의 동작 원리부터 각 언어의 실용적인 코드 예제까지 설명합니다.

URL 인코더/디코더 도구로 즉시 인코딩 및 디코딩하세요 →

URL 인코딩(퍼센트 인코딩)이란?

URL 인코딩(정식 명칭: 퍼센트 인코딩)은 RFC 3986에서 정의된 URI에서 허용되지 않거나 특별한 의미를 가진 문자를 표현하는 메커니즘입니다.

URL에는 제한된 ASCII 문자만 포함할 수 있습니다. 문자는 예약 문자(/, ?, & 같은 구조적 의미)와 비예약 문자(영숫자, -, _, ., ~)로 나뉩니다.

공백(ASCII 32, 16진수 0x20)은 %20이 됩니다. 콜론(ASCII 58, 16진수 0x3A)은 %3A가 됩니다.

// URL encoding in action
Original:  https://example.com/search?q=hello world&lang=en
Encoded:   https://example.com/search?q=hello%20world&lang=en

// Reserved characters and their encoded forms:
//   space → %20    : → %3A    / → %2F
//   ? → %3F        & → %26    = → %3D
//   # → %23        + → %2B    @ → %40

URL 인코딩 문자 참조 테이블

가장 자주 사용되는 퍼센트 인코딩 문자의 빠른 참조 테이블입니다.

문자인코딩이름 / 용도
(space)%20공백
&%26파라미터 구분자
?%3F쿼리 문자열 시작
/%2F경로 구분자
:%3A콜론(스킴 구분자)
=%3D키-값 구분자
#%23프래그먼트 식별자
+%2B더하기(폼에서 공백)
@%40골뱅이
%%25퍼센트(이스케이프 문자)
!%21느낌표
"%22큰따옴표
<%3C작음 기호
>%3E큼 기호
{%7B왼쪽 중괄호
}%7D오른쪽 중괄호
[%5B왼쪽 대괄호
]%5D오른쪽 대괄호
|%7C파이프
\%5C백슬래시

URL 인코딩 동작 원리 (단계별)

인코딩 과정은 세 단계를 따릅니다: (1) 문자 가져오기, (2) UTF-8 바이트 시퀀스로 변환, (3) 각 바이트를 %XX로 인코딩.

여러 예제를 살펴보겠습니다:

// Step-by-step: How characters become percent-encoded

// Example 1: ASCII character (space)
// Character: " " (space)
// ASCII code: 32 → hex: 0x20
// Encoded:    %20

// Example 2: ASCII character (ampersand)
// Character: "&"
// ASCII code: 38 → hex: 0x26
// Encoded:    %26

// Example 3: Multi-byte UTF-8 (accented letter)
// Character: "é"
// Unicode: U+00E9
// UTF-8 bytes: 0xC3 0xA9 (2 bytes)
// Encoded:     %C3%A9

// Example 4: Multi-byte UTF-8 (Chinese character)
// Character: "中"
// Unicode: U+4E2D
// UTF-8 bytes: 0xE4 0xB8 0xAD (3 bytes)
// Encoded:     %E4%B8%AD

// Example 5: Multi-byte UTF-8 (emoji)
// Character: "🚀"
// Unicode: U+1F680
// UTF-8 bytes: 0xF0 0x9F 0x9A 0x80 (4 bytes)
// Encoded:     %F0%9F%9A%80

최신 프로그래밍 언어는 이를 자동으로 처리합니다. 내장 함수 또는 온라인 도구를 사용하세요.

URL 인코더 도구로 인코딩 & 디코딩 →

JavaScript의 encodeURI vs encodeURIComponent

JavaScript는 두 가지 URL 인코딩 함수를 제공합니다. 잘못된 것을 선택하면 버그가 발생합니다.

encodeURI()는 전체 URI를 인코딩하며 구조적 문자를 보존합니다.

// encodeURI() — preserves URL structure
const url = 'https://example.com/path name?q=hello world';
encodeURI(url);
// → "https://example.com/path%20name?q=hello%20world"
// ✓ :// / ? = are NOT encoded (structure preserved)

encodeURIComponent()는 URI 컴포넌트를 인코딩하며 & = + / 같은 구조적 문자도 인코딩합니다.

// encodeURIComponent() — encodes everything for use as a value
const value = 'price=100&discount=20%';
encodeURIComponent(value);
// → "price%3D100%26discount%3D20%25"
// ✓ = & % ARE encoded (they're data, not structure)

// Correct pattern: build URL piece by piece
const base = 'https://api.example.com/search';
const query = 'Tom & Jerry: The Movie';
const fullUrl = base + '?q=' + encodeURIComponent(query);
// → "https://api.example.com/search?q=Tom%20%26%20Jerry%3A%20The%20Movie"

원칙: 쿼리 파라미터 값에는 항상 encodeURIComponent()를 사용하세요.

// Comparison table — which characters get encoded?
//
// Character  encodeURI()  encodeURIComponent()
// ─────────  ───────────  ────────────────────
// space      %20          %20
// /          /  (kept)    %2F (encoded)
// ?          ?  (kept)    %3F (encoded)
// &          &  (kept)    %26 (encoded)
// =          =  (kept)    %3D (encoded)
// #          #  (kept)    %23 (encoded)
// :          :  (kept)    %3A (encoded)
// +          +  (kept)    %2B (encoded)
// @          @  (kept)    %40 (encoded)
// é          %C3%A9       %C3%A9
// 中         %E4%B8%AD    %E4%B8%AD

각 프로그래밍 언어의 URL 인코딩

주요 언어에는 URL 인코딩 함수가 내장되어 있습니다:

JavaScript

// JavaScript — encodeURIComponent / URLSearchParams
// Encode a query parameter value
encodeURIComponent('hello world&key=val');
// → "hello%20world%26key%3Dval"

// Decode
decodeURIComponent('hello%20world%26key%3Dval');
// → "hello world&key=val"

// URLSearchParams (auto-encodes, uses + for spaces)
const params = new URLSearchParams({ q: 'Tom & Jerry', page: '1' });
params.toString(); // → "q=Tom+%26+Jerry&page=1"

Python

# Python 3 — urllib.parse
from urllib.parse import quote, quote_plus, unquote, urlencode

# Path encoding (spaces → %20)
quote('hello world/file')        # → "hello%20world/file"
quote('hello world/file', safe='')  # → "hello%20world%2Ffile"

# Query value encoding (spaces → +)
quote_plus('hello world&key=val')  # → "hello+world%26key%3Dval"

# Build query string from dict
urlencode({'q': 'Tom & Jerry', 'page': '1'})
# → "q=Tom+%26+Jerry&page=1"

# Decode
unquote('%E4%B8%AD%E6%96%87')  # → "中文"

Java

// Java — URLEncoder (spaces → +)
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

String encoded = URLEncoder.encode(
    "hello world&key=val", StandardCharsets.UTF_8
);
// → "hello+world%26key%3Dval"

String decoded = URLDecoder.decode(encoded, StandardCharsets.UTF_8);
// → "hello world&key=val"

Go

// Go — net/url package
package main
import "net/url"

// Query value encoding (spaces → +)
url.QueryEscape("hello world&key=val")
// → "hello+world%26key%3Dval"

// Path segment encoding (spaces → %20)
url.PathEscape("hello world/file")
// → "hello%20world%2Ffile"

// Build URL safely with url.Values
vals := url.Values{}
vals.Set("q", "Tom & Jerry")
vals.Encode() // → "q=Tom+%26+Jerry"

PHP

<?php
// PHP — urlencode (spaces → +) / rawurlencode (spaces → %20)
urlencode('hello world&key=val');
// → "hello+world%26key%3Dval"

rawurlencode('hello world&key=val');
// → "hello%20world%26key%3Dval"

http_build_query(['q' => 'Tom & Jerry', 'page' => 1]);
// → "q=Tom+%26+Jerry&page=1"

urldecode('hello%20world');  // → "hello world"
?>

Ruby

# Ruby — CGI / URI
require 'cgi'
require 'uri'

CGI.escape('hello world&key=val')
# → "hello+world%26key%3Dval"

URI.encode_www_form('q' => 'Tom & Jerry', 'page' => '1')
# → "q=Tom+%26+Jerry&page=1"

CGI.unescape('hello%20world')  # → "hello world"

흔한 URL 인코딩 실수

1. 이중 인코딩

이미 인코딩된 문자열을 다시 인코딩하면 발생합니다. %20%2520이 됩니다.

// Double encoding — a very common bug
const value = 'hello world';
const encoded = encodeURIComponent(value);  // "hello%20world"

// BUG: encoding again
encodeURIComponent(encoded);
// → "hello%2520world"  (%20 → %25 + 20)
// Server decodes to "%20" (literal) instead of " " (space)

// FIX: encode raw values exactly once

2. 전체 URL 인코딩

전체 URL을 encodeURIComponent()에 전달하면 URL 구조가 깨집니다.

// WRONG: encoding entire URL
encodeURIComponent('https://example.com/api?q=test');
// → "https%3A%2F%2Fexample.com%2Fapi%3Fq%3Dtest"  (broken!)

// CORRECT: encode only the parameter value
'https://example.com/api?q=' + encodeURIComponent('test value');
// → "https://example.com/api?q=test%20value"

3. 공백: + vs %20

HTML 폼은 +, RFC 3986은 %20을 사용합니다. API에는 %20을 권장합니다.

// Space encoding: + vs %20
// HTML form submission (application/x-www-form-urlencoded):
//   "hello world" → "hello+world"

// RFC 3986 (URI standard):
//   "hello world" → "hello%20world"

// JavaScript functions:
encodeURIComponent('hello world');  // → "hello%20world" (RFC 3986)
new URLSearchParams({q: 'hello world'}).toString(); // → "q=hello+world" (form)

4. 쿼리 파라미터 값 미인코딩

사용자 입력값을 인코딩하지 않으면 보안 위험이 있고 URL이 깨집니다.

// Missing encoding breaks URLs
const search = 'Tom & Jerry';

// WRONG: unencoded & splits the value
'/search?q=' + search;
// → "/search?q=Tom & Jerry"
// Server sees: q="Tom " and Jerry="" (two params!)

// CORRECT: encode the value
'/search?q=' + encodeURIComponent(search);
// → "/search?q=Tom%20%26%20Jerry"
// Server sees: q="Tom & Jerry" (one param)

URL 인코딩 모범 사례

사용자 입력은 반드시 인코딩한 후 쿼리 문자열이나 경로 세그먼트에 삽입하세요.

수동 치환 대신 라이브러리 함수를 사용하세요.

특수 문자로 테스트: & = ? / # + % 및 비ASCII 문자.

바이너리 데이터에는 URL 안전 Base64를 사용하세요.

// Best practice: use URL / URLSearchParams API
const url = new URL('https://api.example.com/search');
url.searchParams.set('q', 'Tom & Jerry: The Movie');
url.searchParams.set('lang', 'en');
url.toString();
// → "https://api.example.com/search?q=Tom+%26+Jerry%3A+The+Movie&lang=en"
// All encoding handled automatically!

// URL-safe Base64 (avoids + and / in URLs)
// Standard:  "SGVsbG8gV29ybGQ=" (may contain + / =)
// URL-safe:  "SGVsbG8gV29ybGQ"  (uses - _ instead)

Base64 Encoder →URL Parser →

자주 묻는 질문

왜 공백이 %20으로 인코딩되나요?

공백의 ASCII 코드는 32이고, 16진수로는 0x20입니다. 퍼센트 인코딩은 바이트를 % + 16진수 값으로 표현합니다.

+와 %20의 차이는?

%20은 RFC 3986에서 유래. +는 폼 형식에서 유래. %20이 더 범용적입니다.

전체 URL을 인코딩해야 하나요?

아니요. 개별 컴포넌트만 인코딩하세요. 구조적 문자는 인코딩하지 마세요.

encodeURI와 encodeURIComponent의 차이는?

encodeURI()는 구조적 문자를 보존. encodeURIComponent()는 그것들도 인코딩. 파라미터 값에는 encodeURIComponent()를 사용.

URL 인코딩된 문자열을 디코딩하려면?

JavaScript: decodeURIComponent(). Python: urllib.parse.unquote(). PHP: urldecode().

URL 인코딩은 모든 개발자가 이해해야 할 기본적인 웹 개념입니다. 이 가이드를 북마크하여 활용하세요.

URL 인코더/디코더 도구를 사용해보세요 →

도움이 되었나요?

Stay Updated

Get weekly dev tips and new tool announcements.

No spam. Unsubscribe anytime.

Partner Picks

Sponsor this article

Place your product next to this developer topic with tracked clicks.

Ask about article sponsorship

Related Articles

URL 인코딩 특수문자: 완전한 참조 테이블 & 예제

URL 퍼센트 인코딩 완전 참조. 모든 특수문자 조회표, encodeURIComponent vs encodeURI 사용법.

URL 인코딩 & 디코딩 완전 가이드: 퍼센트 인코딩 해설

무료 온라인 URL 인코더/디코더. JavaScript, Python, Bash, PHP 코드 예제와 퍼센트 인코딩 원리.

ASCII vs Unicode vs UTF-8 인코딩 설명

ASCII, Unicode, UTF-8의 차이를 이해하세요. 문자 인코딩 작동 원리, UTF-8이 웹을 지배하는 이유, 인코딩 문제 해결법.

URL 인코더 디코더 온라인 가이드: 퍼센트 인코딩, RFC 3986, 모범 사례

URL 인코딩(퍼센트 인코딩) 완전 가이드. RFC 3986 예약 및 비예약 문자, encodeURIComponent vs encodeURI, Python urllib.parse, Java URLEncoder, 일반 인코딩 문자, 폼 인코딩, API 쿼리 매개변수, 이중 인코딩 디버깅.

This site uses cookies for analytics and to display ads. By continuing to browse, you agree. Privacy Policy