URL 의 해부 — 주소창의 한 줄 읽기
URL 의 해부 — 주소창의 한 줄 읽기
브라우저 주소창의 한 줄은 보기보다 정밀한 구조를 가집니다. 어떤 자원에 어떻게 접근할지를 표현하는 작은 문법. 이 글은 URL 의 각 부분 · 인코딩 규칙 · URL 과 URI 와 URN 의 차이 · 절대 / 상대 경로 · 데이터 URL 과 blob URL.
1. URL 에 대한 이야기
URL 은 Uniform Resource Locator 의 줄임말. 1994 년 Tim Berners-Lee 의 RFC 1738 이 첫 정의이고, 1998 년 RFC 2396 에서 URI 라는 더 큰 우산 안에. 현재 SSOT 는 2005 년의 RFC 3986 (URI Generic Syntax). 브라우저 측 명세는 WHATWG 의 URL Standard.
URI 는 Uniform Resource Identifier 의 줄임말로, 자원을 식별하는 모든 문자열의 우산. URL (위치 기반 식별) 과 URN (Uniform Resource Name, 이름 기반 식별, 예: urn:isbn:0451450523) 이 그 아래. 일상에서는 URL 과 URI 를 거의 같은 뜻으로.
2. 전체 구조
scheme userinfo host port path query fragment
│ │ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼ ▼
https://user:pass@example.com:8443/path/to/page?q=hello&p=2#section-3
각 부분의 의미:
| 부분 | 예 | 설명 |
|---|---|---|
| scheme | https · http · ftp · mailto · file · data · blob · ws · tel |
사용할 프로토콜 |
| userinfo | user:pass |
인증 정보. 평문이라 거의 안 씀, 일부 브라우저 차단 |
| host | example.com · 192.168.1.1 · [::1] |
서버 주소 (도메인 또는 IP) |
| port | 8443 |
서버 포트. 생략 시 scheme 기본값 (http=80, https=443) |
| path | /path/to/page |
자원의 경로 |
| query | q=hello&p=2 |
? 뒤. 키=값 형태가 관습 |
| fragment | section-3 |
# 뒤. 서버로 보내지지 않음, 브라우저 내부 앵커 · SPA 라우팅 |
3. scheme 의 갈래
- http · https — 웹의 본진. https 는 TLS 암호화.
- ftp · sftp — 파일 전송. 모던 브라우저는 ftp 지원을 차례로 제거.
- mailto —
mailto:hi@example.com?subject=hello메일 클라이언트 호출. - tel · sms — 모바일에서 전화 · 문자 앱 호출.
- file — 로컬 파일.
file:///C:/Users/...또는file:///Users/.... - data — 인라인 데이터.
data:image/png;base64,iVBORw0KGgo.... - blob — 브라우저 내부 객체 URL.
URL.createObjectURL(blob)의 결과. - ws · wss — WebSocket.
- javascript — 보안 위험 때문에 권장 안 됨.
4. 퍼센트 인코딩
URL 에는 안전 문자 집합 외의 글자가 들어갈 수 없음. 한글 · 공백 · 특수문자는 % 와 두 자리 16 진수로:
공백 → %20
한글 '가' → %EA%B0%80 (UTF-8 0xEA 0xB0 0x80)
?, =, & 같은 구분자가 값으로 들어갈 때도 인코딩
JS 에서 사용하는 함수:
encodeURIComponent("값 = 1 & 또=2"); // "%EA%B0%92%20%3D%201%20%26%20%EB%98%90%3D2"
encodeURI("https://example.com/한글"); // 스킴·구분자는 보존
encodeURIComponent 가 더 엄격. 쿼리 값 한 토큰을 만들 때는 이쪽이 안전.
5. 쿼리 스트링
?key=value&other=2 형태. 한 키에 여러 값을 보낼 때는 ?tag=a&tag=b 와 ?tag[]=a&tag[]=b 와 ?tag=a,b 가 모두 쓰여 표준이 합의돼 있지 않음. 서버 프레임워크마다 해석이 갈림. 직접 만들 때는 URLSearchParams:
const sp = new URLSearchParams();
sp.set("q", "hello");
sp.append("tag", "a");
sp.append("tag", "b");
sp.toString(); // "q=hello&tag=a&tag=b"
6. fragment
# 뒤는 서버에 전송되지 않음. 그래서 단일 페이지 앱 (SPA) 의 초창기 라우팅이 fragment 를 썼음 (/#/about). 모던 SPA 는 History API (pushState) 로 진짜 path 를 다룸.
7. 절대 vs 상대 URL
- 절대 —
https://example.com/about - 프로토콜 상대 —
//example.com/about(현재 페이지의 scheme 을 따름) - 루트 상대 —
/about(현재 origin 의 루트 기준) - 상대 —
about또는../about(현재 path 기준)
상대 URL 의 기준은 문서의 base URL, <base href="..."> 로 바꿀 수 있음.
8. data URL · blob URL
<img src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'.../>" />
작은 이미지 · SVG 를 외부 요청 없이 인라인. 파일 크기가 늘고 캐시가 안 됨.
const blob = new Blob([buffer], { type: "image/png" });
const url = URL.createObjectURL(blob);
// 사용 후
URL.revokeObjectURL(url);
blob: URL 은 브라우저 메모리 안의 객체를 가리킴. 같은 페이지 안에서만 의미.
9. URL 외의 식별 방식
- URN —
urn:isbn:9780132350884. 위치가 아닌 이름. - DID (Decentralized Identifier) —
did:web:example.com. 분산 ID. - CID (IPFS Content Identifier) — 콘텐츠 해시 기반 주소.
- OID (Object Identifier) —
1.2.840.113549.1.1.11. 표준에서 자주 보는 식별.
10. 자주 쓰는 모양
JS 의 URL 클래스가 파싱 · 조립을 표준화:
const u = new URL("https://example.com:8443/api/users?id=42#top");
u.protocol; // "https:"
u.hostname; // "example.com"
u.port; // "8443"
u.pathname; // "/api/users"
u.searchParams.get("id"); // "42"
u.hash; // "#top"
// 조립
const built = new URL("/users", "https://example.com");
built.searchParams.set("page", "2");
built.toString(); // "https://example.com/users?page=2"
명령줄에서 인코딩 확인:
# Python (Windows · macOS 공통)
python -c "from urllib.parse import quote; print(quote('가나다'))"
# Node
node -e "console.log(encodeURIComponent('가나다'))"
11. 자주 걸리는 자리
한글 도메인은 IDN (RFC 3490) 으로 punycode 화 — 한국.kr 는 실제로 xn--3e0b707e.kr. 인증서 · 이메일 검증에서 헷갈림.
+ 가 쿼리 값에서 공백으로 해석되는 자리 (application/x-www-form-urlencoded) 와 그대로 + 인 자리. URLSearchParams 는 + 를 공백으로 해석.
https://example.com 과 https://example.com/ — 서버에 따라 같거나 다른 자원. path 가 빈 문자열이냐 슬래시 한 글자냐의 차이.
대소문자 — scheme 과 host 는 대소문자 무시, path 와 query 는 보존 (서버 정책에 따라 다름).
fragment 는 서버에 안 가지만 브라우저 히스토리 · Referer 에는 남을 수 있음.
하고픈 말
URL 의 한 줄은 scheme · host · port · path · query · fragment 여섯 자리의 약속. URL 클래스 + URLSearchParams 의 표준 도구를 쓰면 인코딩 · 쿼리 다중 값 · 상대 경로의 함정에서 자유로워집니다. 한글 도메인 · + 해석 · 슬래시 차이 같은 미세한 자리만 의식하면 일상 사용에 큰 마찰이 없는 자리.
Next
- internet-how-it-works
- browser-devtools
RFC 3986 URI Generic Syntax · WHATWG URL Standard · RFC 3490 IDN · MDN URL · MDN URLSearchParams · URL Decoder/Encoder · Punycode 변환기 를 참고합니다.