Base64 URL ์์ ์ธ์ฝ๋ฉ: ์ ์์ ์ค์์ฑ
Base64 URL ์์ ์ธ์ฝ๋ฉ์ด๋?
Base64 URL ์์ ์ธ์ฝ๋ฉ(Base64url์ด๋ผ๊ณ ๋ ํจ)์ URL๊ณผ ํ์ผ ์ด๋ฆ์์ ํน๋ณํ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ ๋ฌธ์๋ค์ ์์ ํ ๋์ฒด ๋ฌธ์๋ก ๋ฐ๊พผ ํ์ค Base64์ ๋ณํ์
๋๋ค. ํ์ค Base64๋ 64์ ์ํ๋ฒณ์ ์ผ๋ถ๋ก +์ /๋ฅผ ์ฌ์ฉํ๊ณ ํจ๋ฉ์ผ๋ก =๋ฅผ ์ฌ์ฉํ๋๋ฐ, ์ด ์ธ ๋ฌธ์ ๋ชจ๋ URL, ์ฟผ๋ฆฌ ๋ฌธ์์ด, ํ์ผ ๊ฒฝ๋ก์์ ๋ฌธ์ ๊ฐ ๋ฉ๋๋ค.
Base64url์ ๋ ๊ฐ์ง ๊ฐ๋จํ ์นํ์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค:
| ํ์ค Base64 | URL ์์ Base64 |
|-----------------|-----------------|
| + (๋ํ๊ธฐ) | - (๋นผ๊ธฐ) |
| / (์ฌ๋์) | _ (๋ฐ์ค) |
| = (ํจ๋ฉ) | ์๋ต (์ผ๋ฐ์ ) |
ํ์ค Base64๊ฐ URL์ ๊นจ๋จ๋ฆฌ๋ ์ด์
+๋ /๊ฐ ํฌํจ๋ Base64 ์ธ์ฝ๋ฉ ๋ฌธ์์ด์ด URL์ ๋ํ๋๋ฉด, ๋ธ๋ผ์ฐ์ ์ ์๋ฒ์ ๋์์ด ์์ธก ๋ถ๊ฐ๋ฅํด์ง๋๋ค.
+ ๋ฌธ์
URL ์ฟผ๋ฆฌ ๋ฌธ์์ด์์ + ๋ฌธ์๋ ๊ณต๋ฐฑ์ผ๋ก ํด์๋ฉ๋๋ค. ์ด ๋์์ application/x-www-form-urlencoded ๋ช
์ธ์์ ๋น๋กฏ๋๋ฉฐ, ๋์ฝ๋ฉ๋ ๋ฐ์ดํฐ์ ์์์น ๋ชปํ ๊ณต๋ฐฑ์ด ์๊ธฐ๊ฒ ํฉ๋๋ค.
์๋ฅผ ๋ค์ด, Pj4+Pz8/Pw==์ ๊ฐ์ Base64 ๋ฌธ์์ด์๋ + ๋ฌธ์๊ฐ ํฌํจ๋์ด ์์ต๋๋ค. ์ด๊ฒ์ด URL ๋งค๊ฐ๋ณ์ ?token=Pj4+Pz8/Pw==์ ๋ํ๋๋ฉด, ์๋ฒ๋ ?token=Pj4 Pz8/Pw==๋ก ์ธ์ํฉ๋๋ค โ +๊ฐ ๊ณต๋ฐฑ์ด ๋ฉ๋๋ค.
/ ๋ฌธ์
URL ๊ฒฝ๋ก์์ / ๋ฌธ์๋ ๊ฒฝ๋ก ๊ตฌ๋ถ์์
๋๋ค. ab/CD+Ef==์ ๊ฐ์ Base64 ๋ฌธ์์ด์๋ /๊ฐ ํฌํจ๋์ด ์์ด ๋๋ ํฐ๋ฆฌ ๋ ๋ฒจ๋ก ํด์๋ฉ๋๋ค. ์ด๊ฒ์ด URL ์ธ๊ทธ๋จผํธ์ ๋ํ๋๋ฉด ํด๋ผ์ด์ธํธ์ ์๋ฒ ๋ชจ๋ ๊ตฌ์กฐ๋ฅผ ์๋ชป ํด์ํ ์ ์์ต๋๋ค.
= ๋ฌธ์
= ๋ฌธ์๋ ์ฟผ๋ฆฌ ๋ฌธ์์ด์์ ํค-๊ฐ ์์ ์ฌ์ฉ๋ฉ๋๋ค. ?data=SGVsbG8=์ ๋ง์ง๋ง =์ ๋ชจํธํ ์ ์์ต๋๋ค โ =์ด Base64 ํจ๋ฉ์ ์ผ๋ถ์ธ๊ฐ์, ์๋๋ฉด ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์ ๊ตฌ๋ฌธ์ธ๊ฐ์?
ํผ์ผํธ ์ธ์ฝ๋ฉ์ผ๋ก ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ง๋ง(+๋ %2B๋ก, /๋ %2F๋ก), ๋ฌธ์์ด ๊ธธ์ด๊ฐ ๋์ด๋๊ณ ๋๋ฒ๊น
์ด ๋ ์ด๋ ค์์ง๋๋ค. Base64url์ด ๋ ๊น๋ํ ํด๊ฒฐ์ฑ
์
๋๋ค.
Base64url์ ์๋ ๋ฐฉ์
Base64url์ RFC 4648 ์น์ 5์ ๊ณต์์ ์ผ๋ก ์ ์๋์ด ์์ต๋๋ค. ํ์ค Base64์ ์ ํํ ๋์ผํ ์๊ณ ๋ฆฌ์ฆ(3๋ฐ์ดํธ๊ฐ 4๋ฌธ์๊ฐ ๋จ)์ ์ฌ์ฉํ์ง๋ง, ์ํ๋ฒณ์ 62๋ฒ๊ณผ 63๋ฒ ์์น์์ ํ ๋ฌธ์์ฉ ์นํํฉ๋๋ค:
- ์ํ๋ฒณ ์ธ๋ฑ์ค 62:
+โ-(๋นผ๊ธฐ) - ์ํ๋ฒณ ์ธ๋ฑ์ค 63:
/โ_(๋ฐ์ค)
ํจ๋ฉ(=)์ ์ผ๋ฐ์ ์ผ๋ก ์ ๊ฑฐ๋๋๋ฐ, ๋์ฝ๋ฉ ์ ๋ฌธ์์ด ๊ธธ์ด๋ก๋ถํฐ ์ถ๋ก ํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. Base64url ๋ฌธ์์ด์ ์ถ๊ฐ ์ด์ค์ผ์ดํ ์์ด ํญ์ ์ ํจํ URL ๊ตฌ์ฑ ์์์
๋๋ค.
๋ณํ ์ ํ
๋ค์์ ๋์ผํ ์ด์ง ๋ฐ์ดํฐ๊ฐ ๋ ํ์์์ ์ด๋ป๊ฒ ๋ณด์ด๋์ง ๋ณด์ฌ์ค๋๋ค:
ํ์ค: Pj4+Pz8/Pw==
URL ์์ : Pj4-Pz8_Pw
Base64url์ด ์ฌ์ฉ๋๋ ๊ณณ
JSON Web Token (JWT)
JWT๋ Base64url์ ๊ฐ์ฅ ๋ํ์ ์ธ ์ฌ์ฉ์ฒ์ ๋๋ค. ๋ชจ๋ JWT๋ ํค๋, ํ์ด๋ก๋, ์๋ช ์ ์ธ ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋๋ฉฐ, ๊ฐ๊ฐ URL ์์ Base64๋ก ์ธ์ฝ๋ฉ๋๊ณ ์ ์ผ๋ก ๊ตฌ๋ถ๋ฉ๋๋ค:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNqP0m2iTgCjD0
๋์์ ๋ฐ์ค์ด ๋ณด์ด๊ณ ๋ํ๊ธฐ ๊ธฐํธ๋ ์ฌ๋์๊ฐ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. JWT๊ฐ ํ์ค Base64๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ๋ฐฉ์์ธ URL ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ ๋ ํ ํฐ์ด ๊นจ์ง ๊ฒ์ ๋๋ค.
OAuth ๋ฐ OpenID Connect
OAuth 2.0๊ณผ OpenID Connect ๋ชจ๋ ์ก์ธ์ค ํ ํฐ๊ณผ ID ํ ํฐ์ JWT๋ฅผ ์ฌ์ฉํ๋ฏ๋ก, Base64url ์ธ์ฝ๋ฉ์ ํ๋ ์ธ์ฆ์ ๊ธฐ๋ณธ์ ๋๋ค. ์ธ์ฆ ์ฝ๋ ํ๋ก์ฐ, ์์์ ํ๋ก์ฐ, ํด๋ผ์ด์ธํธ ์๊ฒฉ ์ฆ๋ช ํ๋ก์ฐ ๋ชจ๋ Base64url์ ์ฌ์ฉํ๋ ํ ํฐ์ ์ ์กํฉ๋๋ค.
์น API ๋ฐ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์
๋ง์ REST ๋ฐ GraphQL API๊ฐ ํ์ด์ง๋ค์ด์ ์ปค์, ํํฐ ๋๋ ์ธ์ฝ๋ฉ๋ ํ์ด๋ก๋๋ฅผ ์ํด ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์์ Base64 ์ธ์ฝ๋ฉ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํฉ๋๋ค. Base64url์ ์ด๋ฌํ ๋งค๊ฐ๋ณ์๊ฐ ์ถ๊ฐ URL ์ธ์ฝ๋ฉ ์์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋๋ก ๋ณด์ฅํฉ๋๋ค.
์ค์ ์ฌ๋ก โ API ์ปค์ ํ์ด์ง๋ค์ด์ :
GET /api/users?cursor=MjAyNC0wMS0xNVQxMDozMDowMFo
GitHub์ API๋ ๋๋ ๊ฒฐ๊ณผ ์งํฉ์ ํ์ด์ง๋ค์ด์ ํ ๋ ์ด์ ์ ํํ ๋์ผํ ํจํด์ ์ฌ์ฉํฉ๋๋ค.
ํ์ผ ์ด๋ฆ ๋ฐ ํ์ผ ์ ์ฅ์
Base64url ๋ฌธ์์ด์ ๊ฒฝ๋ก ๊ตฌ๋ถ์(/)๋ฅผ ํฌํจํ์ง ์๊ณ , ํ์ผ ์์คํ
์ ํผ๋์ค๋ฝ๊ฒ ํ๋ ํน์ ๋ฌธ์๋ ์์ผ๋ฉฐ, Windows์์ ์ ํจํ์ง ์์ ๋ฌธ์(:, *, ? ๋ฑ)๋ ํฌํจํ์ง ์์ผ๋ฏ๋ก ์์ ํ ํ์ผ ์ด๋ฆ์ด ๋ฉ๋๋ค.
์ฝํ ์ธ ์ ์ก ๋คํธ์ํฌ ๋ฐ ์บ์ ํค
CDN๊ณผ ์บ์ฑ ๊ณ์ธต์ ์ข
์ข
Base64url๋ก ์ธ์ฝ๋ฉ๋ ๊ฐ์ ์บ์ ํค๋ก ์ฌ์ฉํฉ๋๋ค. /๊ฐ ํฌํจ๋ ํ์ค Base64๋ ์บ์ ๋ค์์คํ์ด์ค์ ๊ฐ์ง ๋๋ ํฐ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด ๋ชจํธํ ํค๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
ํ์ค Base64์ Base64url ๊ฐ ๋ณํ
๋ ๋ณํ ๊ฐ ๋ณํ์ ์ด๋ค ์ธ์ด์์๋ ๊ฐ๋จํฉ๋๋ค:
JavaScript
// Standard Base64 to URL-safe Base64
function base64ToBase64url(base64) {
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
// URL-safe Base64 to Standard Base64
function base64urlToBase64(base64url) {
let result = base64url.replace(/-/g, '+').replace(/_/g, '/');
// Restore padding
while (result.length % 4) {
result += '=';
}
return result;
}
Node.js
Node.js๋ ๋ฒ์ 15.7.0๋ถํฐ ๋ค์ดํฐ๋ธ Base64url ์ง์์ ์ ๊ณตํฉ๋๋ค:
// Encode to Base64url
const encodedUrl = Buffer.from('Hello, world!').toString('base64url');
console.log(encodedUrl);
// Output: SGVsbG8sIHdvcmxkIQ
// Decode from Base64url
const decoded = Buffer.from(encodedUrl, 'base64url').toString('utf-8');
console.log(decoded);
// Output: Hello, world!
Python
import base64
# Encode to Base64url
encoded = base64.urlsafe_b64encode(b"Hello, world!")
print(encoded.decode())
# Output: SGVsbG8sIHdvcmxkIQ==
# Decode from Base64url
decoded = base64.urlsafe_b64decode(encoded)
print(decoded.decode())
# Output: Hello, world!
ํ์ค Base64 vs Base64url ์ฌ์ฉ ์๊ธฐ
ํ์ค Base64๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ:
- ์ด๋ฉ์ผ ์ฒจ๋ถ ํ์ผ ์ธ์ฝ๋ฉ (MIME ํ์ค์์ ์๊ตฌ)
- HTML/CSS ์๋ฒ ๋ฉ์ฉ ๋ฐ์ดํฐ URL ์์ฑ
- URL ์์ ์ฑ์ด ์ค์ํ์ง ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ ์ ์ฅ
- ํ์ค Base64๋ฅผ ๊ธฐ๋ํ๋ ๋ ๊ฑฐ์ ์์คํ ๊ณผ์ ์ํธ ์์ฉ
Base64url์ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ:
- JWT ํ ํฐ ์์ฑ ๋๋ ํ์ฑ
- URL ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ ๊ฒฝ๋ก ์ธ๊ทธ๋จผํธ์ ์ธ์ฝ๋ฉ๋ ๋ฐ์ดํฐ ์ ๋ฌ
- ์ด์ง ๋ฐ์ดํฐ๋ก๋ถํฐ ํ์ผ ์ด๋ฆ ์์ฑ
- ์บ์ ํค๋ ์๋ณ์ ์์ฑ
- OAuth ํ ํฐ ๋๋ OpenID Connect ์์
์จ๋ผ์ธ์ผ๋ก Base64 URL ์์ ์ธ์ฝ๋ฉ ์ฒดํํ๊ธฐ
๋ฌด๋ฃ ์จ๋ผ์ธ Base64 ์ธ์ฝ๋ ๋ฐ ๋์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ ํ์ค Base64์ URL ์์ Base64 ํ์ ๊ฐ์ ๋ณํํ์ธ์. ๋ฐ์ดํฐ๋ฅผ ๋ถ์ฌ๋ฃ๊ณ ์ํ๋ ๋ณํ์ ์ ํํ๋ฉด ์ฆ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.