Base64가 Base62보다 효율적이지만, 사용 환경에 따라 Base64의 특수문자(+, /, =)가 문제를 일으킬 수 있어 Base62를 사용합니다.
| 이름 | 영문 표기 | 사용 문자 |
|---|---|---|
| 10진수 | decimal, base 10 | 0-9 |
| 8진수 | octet digits, base 8 | 0-7 |
| 16진수 | hexadecimal, base 16 | 0-9, A-F |
| 62진수 | base 62 | 0-9, A-Z, a-z |
| 64진수 | base 64 | 0-9, A-Z, a-z, +, /, = |
Binary (256진법) > Base64 (64진법) > Base62 (62진법) > Base36 > Base26 > Base10
| 인코딩 방식 | 사용 가능 문자 수 | 한 글자당 표현 비트 | 상대적 효율 |
|---|---|---|---|
| Binary | 256 | 8 bits | 최고 |
| Base64 | 64 | 6 bits | 높음 |
| Base62 | 62 | ~5.95 bits | 중간 |
| Base36 | 36 | ~5.17 bits | 보통 |
| Base10 | 10 | ~3.32 bits | 낮음 |
Base64가 Base62보다 정보량이 더 적습니다 (더 효율적입니다).
그렇다면 왜 Base62를 사용할까요?
Base64는 다음 문자를 사용합니다:
A-Z, a-z, 0-9(62개) ✓+✗ (URL에서 공백으로 해석될 수 있음)/✗ (경로 구분자와 충돌)=✗ (쿼리스트링 key=value 구분자와 충돌)
http://example.com/api?key=abc+/=&query=xyz+/=
해석 문제:
key=abc+/=에서=가 어디까지가 value인지 모호함+가 공백으로 해석될 수 있음/가 경로로 해석될 수 있음
// Base64로 인코딩된 데이터를 URL에 포함
const data = btoa("Hello World"); // "SGVsbG8gV29ybGQ="
// URL에 포함하면 문제 발생 가능
http://example.com/api?token=SGVsbG8gV29ybGQ=
↑ = 문자가 쿼리스트링 파싱 오류 유발
많은 파일 시스템과 웹 서버에서 특정 문자를 제한합니다:
# 문제가 될 수 있는 Base64 문자들
/tmp/file+name.txt # + 문자
/tmp/path/to/file.txt # / 문자 (경로 구분자)
file=name.txt # = 문자1990년대 이전:
- 대부분의 이메일 시스템은 7-bit ASCII만 안전하게 전송 가능
- 8-bit 데이터 (이미지, 비ASCII 문자)는 전송 불가 또는 깨짐
문제 상황:
한글 (EUC-KR, 8-bit)
→ 이메일 시스템 (7-bit ASCII만 허용)
→ ✗ 전송 실패 또는 데이터 손실
해결책:
8-bit 데이터
→ Base64 인코딩 (6-bit 청크로 분할, ASCII 문자로 표현)
→ 7-bit 안전 문자열
→ 이메일 전송 ✓
→ Base64 디코딩
→ 원본 복원 ✓
입력: "Man" (3 bytes = 24 bits)
M a n
01001101 01100001 01101110
6-bit 청크로 분할:
010011 010110 000101 101110
Base64 인덱스로 변환:
19 22 5 46
Base64 문자:
T W F u
결과: "TWFu"
Base64는 3바이트를 4문자로 변환하므로, 입력이 3의 배수가 아니면 padding이 필요:
"Man" (3 bytes) → "TWFu" (padding 없음)
"Ma" (2 bytes) → "TWE=" (padding 1개)
"M" (1 byte) → "TQ==" (padding 2개)
Base64의 문제 문자를 대체:
| 원본 Base64 | URL-safe Base64 |
|---|---|
+ |
- |
/ |
_ |
= |
생략 또는 . |
예시:
// 일반 Base64
"Hello+World/Test="
// URL-safe Base64
"Hello-World_Test" // padding 제거특수문자를 아예 사용하지 않음:
사용 문자: 0-9, A-Z, a-z (62개)
장점:
- URL, 파일명, 경로 어디서나 안전
- 추가 인코딩 불필요
- 사람이 읽고 입력하기 쉬움
단점:
- Base64보다 ~3% 정도 길이가 김
| 인코딩 | 사용 문자 | 용도 |
|---|---|---|
| Base36 | 0-9, A-Z | 대소문자 구분 불필요한 환경 |
| Base32 | A-Z, 2-7 | 사람이 입력해야 하는 코드 (Google Authenticator) |
| Base16 (Hex) | 0-9, A-F | 디버깅, 색상 코드 |
✓ 이메일 첨부파일 (MIME encoding)
Content-Type: image/png
Content-Transfer-Encoding: base64
iVBORw0KGgoAAAANSUhEUgAAAAUA...
✓ JSON/XML 내부 바이너리 데이터
{
"image": "data:image/png;base64,iVBORw0KGgoAAAA..."
}✓ HTTP Authorization 헤더
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=✓ 데이터베이스에 바이너리 저장 (텍스트 컬럼에)
✓ URL 단축 서비스 (bit.ly, goo.gl 등)
https://bit.ly/3kX9fG2
↑ Base62 인코딩된 ID
✓ YouTube 영상 ID
https://youtube.com/watch?v=dQw4w9WgXcQ
↑ Base64 유사 (특수문자 제외)
✓ 파일명 생성
# 안전한 파일명
upload_kX9fG2mNpQ.jpg
# 문제 있는 파일명 (Base64)
upload_kX9+G2/NpQ=.jpg # +, /, = 문자 포함✓ REST API 리소스 ID
GET /api/users/7Bx9mK2pQ
POST /api/posts/nZ8kL4wX
✓ 쿠키 값
Set-Cookie: session=aB3dE5fG7hJ9kL; Path=/✓ JWT (JSON Web Token)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
↑ header (base64url) ↑ payload (base64url) ↑ signature (base64url)
✓ OAuth2 state 파라미터
https://oauth.example.com/authorize?state=xyzABC123-_
// ✗ 잘못된 방법: Base64 직접 사용
const data = { userId: 123, role: 'admin' };
const base64 = btoa(JSON.stringify(data));
// 결과: "eyJ1c2VySWQiOjEyMywicm9sZSI6ImFkbWluIn0="
const url = `https://api.com/verify?token=${base64}`;
// 문제: = 문자 때문에 URL 파싱 오류 가능
// ✓ 올바른 방법 1: URL-safe Base64
const urlSafeBase64 = base64
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
const url = `https://api.com/verify?token=${urlSafeBase64}`;
// ✓ 올바른 방법 2: Base62 라이브러리 사용
const base62 = encodeBase62(data); // 특수문자 없음
const url = `https://api.com/verify?token=${base62}`;import base62
# 데이터베이스 auto-increment ID를 Base62로 인코딩
def create_short_url(db_id):
short_code = base62.encode(db_id) # 1234567 → "2BiV"
return f"https://short.url/{short_code}"
# 복원
def get_original_id(short_code):
return base62.decode(short_code) # "2BiV" → 1234567
# 예시
create_short_url(1000000) # https://short.url/4C92
create_short_url(9999999) # https://short.url/2Bizimport base62
import uuid
# ✗ Base64 사용 (문제 있음)
def generate_filename_bad():
unique_id = base64.b64encode(uuid.uuid4().bytes).decode()
return f"upload_{unique_id}.jpg"
# 결과: upload_kX9+G2/NpQ==.jpg (특수문자 포함)
# ✓ Base62 사용 (안전)
def generate_filename_good():
unique_num = uuid.uuid4().int
unique_id = base62.encode(unique_num)
return f"upload_{unique_id}.jpg"
# 결과: upload_7Bx9mK2pQ.jpg (영문자+숫자만)원본 데이터: 1000 bytes (무작위 바이너리)
| 인코딩 방식 | 결과 길이 | 증가율 |
|---|---|---|
| 원본 (Binary) | 1000 bytes | - |
| Base64 | 1336 bytes | +33.6% |
| Base62 | 1375 bytes | +37.5% |
| Base36 | 1620 bytes | +62.0% |
| Base16 (Hex) | 2000 bytes | +100% |
결론: Base62는 Base64보다 약 3% 더 길지만, 안전성을 고려하면 합리적인 트레이드오프입니다.
-
Base64가 Base62보다 효율적이다 (정보량 3% 적음)
-
하지만 Base64의 특수문자 (
+,/,=)가 문제를 일으킨다:- URL 쿼리스트링에서 충돌
- 파일명/경로에서 제약
- 추가 인코딩 필요
-
Base64의 원래 목적:
- 이메일에서 8-bit 데이터를 7-bit ASCII로 안전하게 전송
- RFC 1341 표준
-
사용 가이드:
- URL/파일명: Base62 또는 URL-safe Base64
- 이메일/JSON: Base64
- 사람이 입력: Base32, Base36
- 짧은 URL: Base62
-
필요에 따라 다양한 Base 인코딩을 선택할 수 있다:
- Base36, Base32, Base26, Base16 등
- 환경의 제약사항에 맞춰 선택
- RFC 1341: MIME (Multipurpose Internet Mail Extensions) - Base64 인코딩 정의
- RFC 4648: The Base16, Base32, and Base64 Data Encodings
- RFC 4648 Section 5: Base64url (URL-safe Base64)
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
0-9 : 0123456789 (10개)
A-Z : ABCDEFGHIJKLMNOPQRSTUVWXYZ (26개)
a-z : abcdefghijklmnopqrstuvwxyz (26개)
총 62개 (특수문자 없음)