URL 단축기(URL Shortener)는 긴 URL을 짧은 별칭으로 변환하고 리다이렉트하는 서비스다. 시스템 설계 인터뷰의 대표적 문제다.
요구사항 분석
기능 요구사항:
- URL 단축: longUrl → short.ly/abc123
- 리다이렉트: short.ly/abc123 → 원본 URL (301/302)
- 커스텀 단축키: short.ly/mylink
- URL 만료 기간 설정
비기능 요구사항:
- QPS: 쓰기 100/s, 읽기 10,000/s (읽기 많음)
- 가용성: 99.9%
- 단축 URL 최소 5년 보관
- 지연시간: <100ms
용량 계획:
- 하루 쓰기: 100 × 86400 = 8.6M개
- 5년 총량: 8.6M × 365 × 5 ≈ 15.7B개
- 레코드당 500B → 총 저장소: ~7.85TB
단축 키 생성 방법
python
import hashlib
import base64
import string
import random
# 방법 1: MD5 해시 앞 7글자 (충돌 가능)
def hash_based(long_url: str) -> str:
h = hashlib.md5(long_url.encode()).hexdigest()
return base64.urlsafe_b64encode(bytes.fromhex(h[:8]))[:7].decode()
# 방법 2: 전용 ID 생성기 (추천)
CHARS = string.ascii_letters + string.digits # 62진수
def encode_base62(num: int) -> str:
result = []
while num > 0:
result.append(CHARS[num % 62])
num //= 62
return ''.join(reversed(result)).zfill(7)
# 7자리 Base62 = 62^7 ≈ 3.5조 개 가능
# 방법 3: 카운터 기반 (Snowflake ID 사용)
# 분산 환경에서 충돌 없는 ID 생성
시스템 아키텍처
클라이언트
↓
Load Balancer
↓
API 서버 클러스터
├── POST /api/shorten → ID 생성 → DB/Cache 저장
└── GET /{shortKey} → Cache 조회 → 301 리다이렉트
캐싱 전략 (Redis):
- 읽기 80% → Cache Hit (Pareto 법칙)
- TTL: 24시간
- LRU 정책
DB 설계:
CREATE TABLE urls (
id BIGINT PRIMARY KEY, -- Snowflake ID
short_key VARCHAR(7) UNIQUE,
long_url TEXT NOT NULL,
created_at TIMESTAMP,
expires_at TIMESTAMP,
user_id BIGINT
);
CREATE INDEX idx_short_key ON urls(short_key);
301 vs 302 리다이렉트
301 (영구 이동):
- 브라우저가 결과 캐시
- 서버 부하 감소
- 분석 추적 어려움
302 (임시 이동):
- 매번 서버 거침
- 클릭 추적 가능
- 서버 부하 증가
관련 문서