๐Ÿ”
โ† ๊ฐ€์ด๋“œ ๋ชฉ๋ก์œผ๋กœ

JavaScript์—์„œ Base64 ์ธ์ฝ”๋”ฉ/๋””์ฝ”๋”ฉ: btoa(), atob() ๋ฐ ์œ ๋‹ˆ์ฝ”๋“œ

ยท ํƒœ๊ทธ: javascript, base64, btoa, atob, nodejs, encoding, web-development

JavaScript์—์„œ Base64 ์ธ์ฝ”๋”ฉ ๋ฐ ๋””์ฝ”๋”ฉ

JavaScript๋Š” Base64 ๋ฌธ์ž์—ด์„ ์ธ์ฝ”๋”ฉํ•˜๊ณ  ๋””์ฝ”๋”ฉํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋‚ด์žฅ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋“  Node.js ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•˜๋“ , JSON, HTML, URL๊ณผ ๊ฐ™์€ ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ํ˜•์‹์—์„œ ์ด์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด Base64 ์ž‘์—… ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์—์„œ btoa() ๋ฐ atob() ์‚ฌ์šฉํ•˜๊ธฐ

๋ธŒ๋ผ์šฐ์ € JavaScript์—์„œ Base64๋ฅผ ์œ„ํ•œ ๋‘ ๊ฐ€์ง€ ํ•ต์‹ฌ ํ•จ์ˆ˜๋Š” btoa()์™€ atob()์ž…๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜ ์ด๋ฆ„์€ ์˜ค๋ž˜๋œ ๋ช…๋ช… ๊ทœ์น™์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. btoa๋Š” "binary to ASCII"๋ฅผ, atob์€ "ASCII to binary"๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋“ค์€ ์ˆ˜์‹ญ ๋…„ ๋™์•ˆ ๋ชจ๋“  ์ฃผ์š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง€์›๋˜์–ด ์™”์Šต๋‹ˆ๋‹ค.

btoa()๋กœ ์ธ์ฝ”๋”ฉํ•˜๊ธฐ

const originalString = 'Hello, world!';
const encoded = btoa(originalString);
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ==

atob()๋กœ ๋””์ฝ”๋”ฉํ•˜๊ธฐ

const base64String = 'SGVsbG8sIHdvcmxkIQ==';
const decoded = atob(base64String);
console.log(decoded);
// Output: Hello, world!

๋‘ ํ•จ์ˆ˜ ๋ชจ๋‘ Latin-1 ๋ฌธ์ž(๊ฐ ๋ฌธ์ž๊ฐ€ ๋‹จ์ผ ๋ฐ”์ดํŠธ๋กœ ํ‘œํ˜„๋จ)๋งŒ ํฌํ•จ๋œ ๋ฌธ์ž์—ด์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค์Œ์— ๋‹ค๋ฃฐ ์ค‘์š”ํ•œ ์ œํ•œ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

์œ ๋‹ˆ์ฝ”๋“œ ๋ฐ ๋น„ASCII ๋ฌธ์ž ์ฒ˜๋ฆฌํ•˜๊ธฐ

ํ”ํ•œ ํ•จ์ •: btoa()๋Š” ์ด๋ชจ์ง€, ํ•œ์ž, ์•…์„ผํŠธ ๋ฌธ์ž ๋“ฑ Latin-1 ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๋ฌธ์ž๊ฐ€ ํฌํ•จ๋œ ๋ฌธ์ž์—ด์„ ๋ฐ›์œผ๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

btoa('Hello ไฝ ๅฅฝ');
// Error: The string to be encoded contains characters outside of the Latin-1 range.

์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์—ด์„ ์ธ์ฝ”๋”ฉํ•˜๋ ค๋ฉด ๋จผ์ € ๋ฌธ์ž์—ด์„ ๋ฐ”์ดํŠธ๋กœ ๋ณ€ํ™˜ํ•œ ๋‹ค์Œ ํ•ด๋‹น ๋ฐ”์ดํŠธ๋ฅผ ์ธ์ฝ”๋”ฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ˜„๋Œ€์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์€ TextEncoder ๋ฐ TextDecoder API๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

function unicodeToBase64(str) {
  const bytes = new TextEncoder().encode(str);
  const binaryString = String.fromCharCode(...bytes);
  return btoa(binaryString);
}

function base64ToUnicode(base64) {
  const binaryString = atob(base64);
  const bytes = Uint8Array.from(binaryString, (c) => c.charCodeAt(0));
  return new TextDecoder().decode(bytes);
}

// Usage
const encoded = unicodeToBase64('Hello ไฝ ๅฅฝ ๐Ÿš€');
console.log(encoded);
// Output: SGVsbG8g5L2g5aW9IPCfj4A=

const decoded = base64ToUnicode(encoded);
console.log(decoded);
// Output: Hello ไฝ ๅฅฝ ๐Ÿš€

๊ตฌ์‹ ๊ธฐ๋ฒ•์œผ๋กœ encodeURIComponent์™€ decodeURIComponent๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, TextEncoder/TextDecoder ์ ‘๊ทผ ๋ฐฉ์‹์ด ๋” ๊ฒฌ๊ณ ํ•˜๋ฉฐ ๊ถŒ์žฅ๋˜๋Š” ํ˜„๋Œ€์ ์ธ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

์ด์ง„ ๋ฐ์ดํ„ฐ(ArrayBuffer) ์ธ์ฝ”๋”ฉํ•˜๊ธฐ

ํŒŒ์ผ, ์ด๋ฏธ์ง€, ๋˜๋Š” fetch๋‚˜ FileReader์™€ ๊ฐ™์€ API์—์„œ ๊ฐ€์ ธ์˜จ ์›์‹œ ์ด์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ArrayBuffer ๋˜๋Š” Uint8Array๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ Base64๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

function arrayBufferToBase64(buffer) {
  const bytes = new Uint8Array(buffer);
  let binaryString = '';
  for (let i = 0; i < bytes.length; i++) {
    binaryString += String.fromCharCode(bytes[i]);
  }
  return btoa(binaryString);
}

function base64ToArrayBuffer(base64) {
  const binaryString = atob(base64);
  const bytes = new Uint8Array(binaryString.length);
  for (let i = 0; i < binaryString.length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return bytes.buffer;
}

๋ธŒ๋ผ์šฐ์ €์—์„œ ํŒŒ์ผ์„ Base64๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ

๋‹ค์Œ์€ FileReader๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ํŒŒ์ผ์„ Base64 ๋ฐ์ดํ„ฐ URL๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์™„์ „ํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค:

function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = () => reject(new Error('Failed to read file'));
    reader.readAsDataURL(file);
  });
}

// Usage with a file input
document.querySelector('input[type="file"]').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  try {
    const dataUrl = await fileToBase64(file);
    console.log(dataUrl); // data:image/png;base64,iVBORw0KGgo...
  } catch (err) {
    console.error('Conversion failed:', err);
  }
});

Node.js์—์„œ Base64 ์‚ฌ์šฉํ•˜๊ธฐ

Node.js๋Š” Base64 ์ž‘์—…์„ ์œ„ํ•œ Buffer ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ btoa/atob๋ณด๋‹ค ๋” ์œ ์—ฐํ•ฉ๋‹ˆ๋‹ค. Buffer ํด๋ž˜์Šค๋Š” ์œ ๋‹ˆ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•œ ์ธ์ฝ”๋”ฉ ๋ฐ ๋””์ฝ”๋”ฉ์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ์ธ์ฝ”๋”ฉ ํ˜•์‹์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์ธ์ฝ”๋”ฉ ๋ฐ ๋””์ฝ”๋”ฉ

// Encode a string to Base64
const encoded = Buffer.from('Hello, world!').toString('base64');
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ==

// Decode a Base64 string back to text
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded);
// Output: Hello, world!

Node.js์—์„œ ์œ ๋‹ˆ์ฝ”๋“œ ์ง€์›

๋ธŒ๋ผ์šฐ์ €์˜ btoa()์™€ ๋‹ฌ๋ฆฌ, Node.js Buffer๋Š” ์œ ๋‹ˆ์ฝ”๋“œ๋ฅผ ์›ํ™œํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค:

const encoded = Buffer.from('Hello ไฝ ๅฅฝ ๐Ÿš€').toString('base64');
console.log(encoded);
// Output: SGVsbG8g5L2g5aW9IPCfj4A=

const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded);
// Output: Hello ไฝ ๅฅฝ ๐Ÿš€

ํŒŒ์ผ์„ ์ฝ์–ด Base64๋กœ ์ธ์ฝ”๋”ฉํ•˜๊ธฐ

const fs = require('fs');

// Read a file and encode it to Base64
const buffer = fs.readFileSync('image.png');
const base64 = buffer.toString('base64');
const dataUrl = `data:image/png;base64,${base64}`;

Node.js์—์„œ Base64url ์ธ์ฝ”๋”ฉ

Node.js 15.7.0 ์ด์ƒ์—์„œ๋Š” ๋„ค์ดํ‹ฐ๋ธŒ Base64url ์ธ์ฝ”๋”ฉ์„ ์ง€์›ํ•˜๋ฉฐ, ์ด๋Š” +๋ฅผ -๋กœ, /๋ฅผ _๋กœ ๋Œ€์ฒดํ•˜๊ณ  ํŒจ๋”ฉ์„ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค:

const encoded = Buffer.from('Hello, world!').toString('base64url');
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ (no padding)

const decoded = Buffer.from(encoded, 'base64url').toString('utf-8');
console.log(decoded);
// Output: Hello, world!

์„ฑ๋Šฅ ๊ณ ๋ ค ์‚ฌํ•ญ

๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์˜ ๊ฒฝ์šฐ ๋ฐ˜๋ณต์ ์ธ Base64 ์ž‘์—…์ด ๋А๋ ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ๋ช‡ ๊ฐ€์ง€ ํŒ์ž…๋‹ˆ๋‹ค:

  • ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์—ด์—๋Š” ์ˆ˜๋™ ๋ณ€ํ™˜๋ณด๋‹ค TextEncoder/TextDecoder๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”
  • Node.js์—์„œ๋Š” Buffer.from()์ด ๊ณ ๋„๋กœ ์ตœ์ ํ™”๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ์ˆ˜๋™ ๊ตฌํ˜„๋ณด๋‹ค ์„ ํ˜ธํ•˜์„ธ์š”
  • ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๋Œ€์šฉ๋Ÿ‰ ํŒŒ์ผ์„ Base64๋กœ ๋ณ€ํ™˜ํ•˜์ง€ ๋งˆ์„ธ์š”(์ŠคํŠธ๋ฆฌ๋ฐ ๊ณ ๋ ค)
  • ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์…‹์˜ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ €์—์„œ Blob๊ณผ FileReader๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ์ฐจ๋‹จ์„ ๋ฐฉ์ง€ํ•˜์„ธ์š”

์˜จ๋ผ์ธ์œผ๋กœ Base64 ์ธ์ฝ”๋”ฉ ์ฒดํ—˜ํ•˜๊ธฐ

์ฝ”๋”ฉ ์—†์ด ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ฐ”๋กœ ์ธ์ฝ”๋”ฉ๊ณผ ๋””์ฝ”๋”ฉ์„ ์‹คํ—˜ํ•ด ๋ณด์„ธ์š”. ๋ฌด๋ฃŒ ์˜จ๋ผ์ธ Base64 ์ธ์ฝ”๋” ๋ฐ ๋””์ฝ”๋”๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ํ…์ŠคํŠธ๋ฅผ ๋ถ™์—ฌ๋„ฃ๊ฑฐ๋‚˜ ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ์ฆ‰์‹œ Base64 ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

JavaScript์—์„œ Base64 ์ธ์ฝ”๋”ฉ/๋””์ฝ”๋”ฉ: btoa(), atob() ๋ฐ ์œ ๋‹ˆ์ฝ”๋“œ - CoolTool