Whiz Tools

Base64 인코더/디코더

텍스트를 Base64 인코딩으로 변환하거나 그 반대로 변환합니다

복사

Base64 인코더 및 디코더

소개

Base64는 이진 데이터를 ASCII 문자열 형식으로 표현하는 이진-텍스트 인코딩 방식입니다. 이진 형식으로 저장된 데이터를 텍스트 콘텐츠만 안정적으로 지원하는 채널을 통해 전송할 수 있도록 설계되었습니다. Base64 인코딩은 이진 데이터를 안전하게 텍스트 기반 프로토콜을 통해 전송할 수 있도록 64개의 문자 집합으로 변환합니다(따라서 이름이 붙었습니다).

Base64 문자 집합은 다음으로 구성됩니다:

  • 대문자 A-Z (26자)
  • 소문자 a-z (26자)
  • 숫자 0-9 (10자)
  • 일반적으로 "+"와 "/"인 두 개의 추가 문자 (2자)

이 도구를 사용하면 텍스트를 Base64 형식으로 쉽게 인코딩하거나 Base64 문자열을 원래 텍스트로 디코딩할 수 있습니다. 이는 개발자, IT 전문가 및 텍스트 기반 채널을 통해 안전하게 전송해야 하는 데이터와 작업하는 모든 사람에게 특히 유용합니다.

Base64 인코딩 작동 방식

인코딩 과정

Base64 인코딩은 이진 데이터의 3바이트(24비트) 그룹을 4개의 Base64 문자로 변환하여 작동합니다. 이 과정은 다음 단계로 진행됩니다:

  1. 입력 텍스트를 이진 표현으로 변환합니다(ASCII 또는 UTF-8 인코딩 사용)
  2. 이진 데이터를 24비트(3바이트) 청크로 그룹화합니다
  3. 각 24비트 청크를 4개의 6비트 그룹으로 나눕니다
  4. 각 6비트 그룹을 해당 Base64 문자로 변환합니다

입력 길이가 3으로 나누어 떨어지지 않을 경우, 4:3 비율을 유지하기 위해 "=" 문자를 추가하여 패딩합니다.

수학적 표현

바이트 시퀀스 b1,b2,b3b_1, b_2, b_3에 대해 해당 Base64 문자는 c1,c2,c3,c4c_1, c_2, c_3, c_4로 계산됩니다:

c1=Base64[(b1>>2)]c_1 = \text{Base64}[(b_1 >> 2)]
c2=Base64[((b1&3)<<4)(b2>>4)]c_2 = \text{Base64}[((b_1 \& 3) << 4) | (b_2 >> 4)]
c3=Base64[((b2&15)<<2)(b3>>6)]c_3 = \text{Base64}[((b_2 \& 15) << 2) | (b_3 >> 6)]
c4=Base64[(b3&63)]c_4 = \text{Base64}[(b_3 \& 63)]

여기서 Base64[i]\text{Base64}[i]는 Base64 알파벳의 ii번째 문자를 나타냅니다.

디코딩 과정

Base64 디코딩은 인코딩 과정을 역으로 수행합니다:

  1. 각 Base64 문자를 6비트 값으로 변환합니다
  2. 이러한 6비트 값을 연결합니다
  3. 비트를 8비트 청크(바이트)로 그룹화합니다
  4. 각 바이트를 해당 문자로 변환합니다

패딩

인코딩할 바이트 수가 3으로 나누어 떨어지지 않을 경우 패딩이 적용됩니다:

  • 바이트가 하나 남으면 두 개의 Base64 문자로 변환되고 "=="가 뒤에 추가됩니다
  • 바이트가 두 개 남으면 세 개의 Base64 문자로 변환되고 "="가 뒤에 추가됩니다

예시

텍스트 "Hello"를 Base64로 인코딩해 보겠습니다:

  1. "Hello"의 ASCII 표현: 72 101 108 108 111
  2. 이진 표현: 01001000 01100101 01101100 01101100 01101111
  3. 6비트 청크로 그룹화: 010010 000110 010101 101100 011011 000110 1111
  4. 마지막 청크는 4비트만 있으므로 0으로 패딩합니다: 010010 000110 010101 101100 011011 000110 111100
  5. 십진수로 변환: 18, 6, 21, 44, 27, 6, 60
  6. Base64 알파벳에서 조회: S, G, V, s, b, G, 8
  7. 결과는 "SGVsbG8="입니다

입력 길이(5바이트)가 3으로 나누어 떨어지지 않기 때문에 끝에 "=" 패딩이 있는 점에 유의하십시오.

공식

Base64 인코딩 문자열의 길이를 계산하는 일반 공식은 다음과 같습니다:

encoded_length=4×input_length3\text{encoded\_length} = 4 \times \lceil \frac{\text{input\_length}}{3} \rceil

여기서 x\lceil x \rceil는 천장 함수(가장 가까운 정수로 올림)를 나타냅니다.

사용 사례

Base64 인코딩은 다양한 애플리케이션에서 널리 사용됩니다:

  1. 이메일 첨부 파일: MIME(다목적 인터넷 메일 확장)는 이메일에서 이진 첨부 파일을 인코딩하는 데 Base64를 사용합니다.

  2. 데이터 URL: HTML, CSS 또는 JavaScript에서 작은 이미지, 글꼴 또는 기타 리소스를 직접 포함하는 데 data: URL 스킴을 사용합니다.

  3. API 통신: JSON 페이로드 또는 기타 텍스트 기반 API 형식에서 이진 데이터를 안전하게 전송합니다.

  4. 텍스트 형식으로 이진 데이터 저장: 이진 데이터를 XML, JSON 또는 기타 텍스트 기반 형식에 저장해야 할 때.

  5. 인증 시스템: HTTP의 기본 인증은 Base64 인코딩을 사용합니다(보안이 아니라 인코딩을 위한 것입니다).

  6. 암호화: 다양한 암호화 프로토콜 및 시스템의 일부로, 종종 키 또는 인증서를 인코딩하는 데 사용됩니다.

  7. 쿠키 값: 쿠키에 저장할 복잡한 데이터 구조를 인코딩합니다.

대안

Base64는 널리 사용되지만 특정 상황에서는 더 적합한 대안이 있을 수 있습니다:

  1. URL 안전 Base64: "+"와 "/" 대신 "-"와 "_"를 사용하여 URL 인코딩 문제를 피하는 변형입니다. URL에 포함될 데이터에 유용합니다.

  2. Base32: 32자 집합을 사용하여 출력이 더 길어지지만 가독성이 더 좋고 대소문자를 구분하지 않습니다.

  3. 16진수 인코딩: 16진수로 간단하게 변환하여 크기가 두 배로 증가하지만 매우 간단하고 널리 지원됩니다.

  4. 이진 전송: 대용량 파일이나 효율성이 중요한 경우, 적절한 Content-Type 헤더가 있는 HTTP와 같은 직접 이진 전송 프로토콜이 더 바람직합니다.

  5. 압축 + Base64: 대량의 텍스트 데이터를 위해 인코딩하기 전에 압축하면 크기 증가를 완화할 수 있습니다.

  6. JSON/XML 직렬화: 구조화된 데이터의 경우 Base64 인코딩보다 기본 JSON 또는 XML 직렬화를 사용하는 것이 더 적절할 수 있습니다.

역사

Base64 인코딩은 이진 데이터를 텍스트로 전송해야 했던 초기 컴퓨팅 및 통신 시스템에서 그 뿌리를 찾을 수 있습니다.

Base64의 공식 사양은 1987년 RFC 989의 일부로 처음 발표되었으며, 이는 개인 정보 보호 강화 메일(PEM)을 정의했습니다. 이후 RFC 1421(1993) 및 RFC 2045(1996, MIME의 일부)에서 업데이트되었습니다.

"Base64"라는 용어는 인코딩이 이진 데이터를 표현하기 위해 64개의 서로 다른 ASCII 문자를 사용한다는 사실에서 유래되었습니다. 이 64자 선택은 64가 2의 거듭제곱(2^6)이기 때문에 이진과 Base64 간의 변환이 효율적이도록 의도적으로 이루어졌습니다.

시간이 지나면서 여러 가지 Base64 변형이 등장했습니다:

  • 표준 Base64: RFC 4648에 정의된 대로 A-Z, a-z, 0-9, +, / 및 =를 패딩으로 사용합니다.
  • URL 안전 Base64: URL 인코딩 문제를 피하기 위해 -와 _를 사용하는 변형입니다.
  • 파일 이름 안전 Base64: 파일 이름에 사용하기 위해 설계된 유사한 변형입니다.
  • IMAP을 위한 수정된 Base64: IMAP 프로토콜에서 사용되는 특수 문자 집합이 다른 변형입니다.

30년이 넘는 시간이 지나도 Base64는 현대 컴퓨팅에서 여전히 중요한 도구로 남아 있으며, 특히 JSON과 같은 텍스트 기반 데이터 형식에 크게 의존하는 웹 애플리케이션과 API의 증가와 함께 더욱 그러합니다.

코드 예제

다양한 프로그래밍 언어에서 Base64 인코딩 및 디코딩의 예는 다음과 같습니다:

// JavaScript Base64 인코딩/디코딩
function encodeToBase64(text) {
  return btoa(text);
}

function decodeFromBase64(base64String) {
  try {
    return atob(base64String);
  } catch (e) {
    throw new Error("유효하지 않은 Base64 문자열");
  }
}

// 예시 사용
const originalText = "Hello, World!";
const encoded = encodeToBase64(originalText);
console.log("인코딩된:", encoded);  // SGVsbG8sIFdvcmxkIQ==

try {
  const decoded = decodeFromBase64(encoded);
  console.log("디코딩된:", decoded);  // Hello, World!
} catch (error) {
  console.error(error.message);
}
# Python Base64 인코딩/디코딩
import base64

def encode_to_base64(text):
    # 문자열을 바이트로 변환한 후 인코딩
    text_bytes = text.encode('utf-8')
    base64_bytes = base64.b64encode(text_bytes)
    return base64_bytes.decode('utf-8')

def decode_from_base64(base64_string):
    try:
        # Base64 문자열을 바이트로 변환한 후 디코딩
        base64_bytes = base64_string.encode('utf-8')
        text_bytes = base64.b64decode(base64_bytes)
        return text_bytes.decode('utf-8')
    except Exception as e:
        raise ValueError(f"유효하지 않은 Base64 문자열: {e}")

# 예시 사용
original_text = "Hello, World!"
encoded = encode_to_base64(original_text)
print(f"인코딩된: {encoded}")  # SGVsbG8sIFdvcmxkIQ==

try:
    decoded = decode_from_base64(encoded)
    print(f"디코딩된: {decoded}")  # Hello, World!
except ValueError as e:
    print(e)
// Java Base64 인코딩/디코딩
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class Base64Example {
    public static String encodeToBase64(String text) {
        byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);
        byte[] encodedBytes = Base64.getEncoder().encode(textBytes);
        return new String(encodedBytes, StandardCharsets.UTF_8);
    }
    
    public static String decodeFromBase64(String base64String) {
        try {
            byte[] base64Bytes = base64String.getBytes(StandardCharsets.UTF_8);
            byte[] decodedBytes = Base64.getDecoder().decode(base64Bytes);
            return new String(decodedBytes, StandardCharsets.UTF_8);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("유효하지 않은 Base64 문자열: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        String originalText = "Hello, World!";
        String encoded = encodeToBase64(originalText);
        System.out.println("인코딩된: " + encoded);  // SGVsbG8sIFdvcmxkIQ==
        
        try {
            String decoded = decodeFromBase64(encoded);
            System.out.println("디코딩된: " + decoded);  // Hello, World!
        } catch (IllegalArgumentException e) {
            System.err.println(e.getMessage());
        }
    }
}
<?php
// PHP Base64 인코딩/디코딩
function encodeToBase64($text) {
    return base64_encode($text);
}

function decodeFromBase64($base64String) {
    $decoded = base64_decode($base64String, true);
    if ($decoded === false) {
        throw new Exception("유효하지 않은 Base64 문자열");
    }
    return $decoded;
}

// 예시 사용
$originalText = "Hello, World!";
$encoded = encodeToBase64($originalText);
echo "인코딩된: " . $encoded . "\n";  // SGVsbG8sIFdvcmxkIQ==

try {
    $decoded = decodeFromBase64($encoded);
    echo "디코딩된: " . $decoded . "\n";  // Hello, World!
} catch (Exception $e) {
    echo "오류: " . $e->getMessage() . "\n";
}
?>
// C# Base64 인코딩/디코딩
using System;
using System.Text;

class Base64Example
{
    public static string EncodeToBase64(string text)
    {
        byte[] textBytes = Encoding.UTF8.GetBytes(text);
        return Convert.ToBase64String(textBytes);
    }
    
    public static string DecodeFromBase64(string base64String)
    {
        try
        {
            byte[] base64Bytes = Convert.FromBase64String(base64String);
            return Encoding.UTF8.GetString(base64Bytes);
        }
        catch (FormatException)
        {
            throw new FormatException("유효하지 않은 Base64 문자열");
        }
    }
    
    static void Main()
    {
        string originalText = "Hello, World!";
        string encoded = EncodeToBase64(originalText);
        Console.WriteLine($"인코딩된: {encoded}");  // SGVsbG8sIFdvcmxkIQ==
        
        try
        {
            string decoded = DecodeFromBase64(encoded);
            Console.WriteLine($"디코딩된: {decoded}");  // Hello, World!
        }
        catch (FormatException e)
        {
            Console.WriteLine($"오류: {e.Message}");
        }
    }
}
# Ruby Base64 인코딩/디코딩
require 'base64'

def encode_to_base64(text)
  Base64.strict_encode64(text)
end

def decode_from_base64(base64_string)
  begin
    Base64.strict_decode64(base64_string)
  rescue ArgumentError => e
    raise "유효하지 않은 Base64 문자열: #{e.message}"
  end
end

# 예시 사용
original_text = "Hello, World!"
encoded = encode_to_base64(original_text)
puts "인코딩된: #{encoded}"  # SGVsbG8sIFdvcmxkIQ==

begin
  decoded = decode_from_base64(encoded)
  puts "디코딩된: #{decoded}"  # Hello, World!
rescue StandardError => e
  puts "오류: #{e.message}"
end
// Go Base64 인코딩/디코딩
package main

import (
    "encoding/base64"
    "fmt"
)

func encodeToBase64(text string) string {
    return base64.StdEncoding.EncodeToString([]byte(text))
}

func decodeFromBase64(base64String string) (string, error) {
    bytes, err := base64.StdEncoding.DecodeString(base64String)
    if err != nil {
        return "", fmt.Errorf("유효하지 않은 Base64 문자열: %v", err)
    }
    return string(bytes), nil
}

func main() {
    originalText := "Hello, World!"
    encoded := encodeToBase64(originalText)
    fmt.Println("인코딩된:", encoded)  // SGVsbG8sIFdvcmxkIQ==
    
    decoded, err := decodeFromBase64(encoded)
    if err != nil {
        fmt.Println("오류:", err)
    } else {
        fmt.Println("디코딩된:", decoded)  // Hello, World!
    }
}
// Swift Base64 인코딩/디코딩
import Foundation

func encodeToBase64(_ text: String) -> String? {
    if let data = text.data(using: .utf8) {
        return data.base64EncodedString()
    }
    return nil
}

func decodeFromBase64(_ base64String: String) -> String? {
    if let data = Data(base64Encoded: base64String) {
        return String(data: data, encoding: .utf8)
    }
    return nil
}

// 예시 사용
let originalText = "Hello, World!"
if let encoded = encodeToBase64(originalText) {
    print("인코딩된: \(encoded)")  // SGVsbG8sIFdvcmxkIQ==
    
    if let decoded = decodeFromBase64(encoded) {
        print("디코딩된: \(decoded)")  // Hello, World!
    } else {
        print("오류: Base64 문자열을 디코딩할 수 없습니다")
    }
} else {
    print("오류: 텍스트를 인코딩할 수 없습니다")
}
' Excel VBA Base64 인코딩/디코딩
' 참고: Microsoft XML, v6.0에 대한 참조가 필요합니다
Function EncodeToBase64(text As String) As String
    Dim xmlObj As Object
    Set xmlObj = CreateObject("MSXML2.DOMDocument")
    
    Dim xmlNode As Object
    Set xmlNode = xmlObj.createElement("b64")
    
    xmlNode.DataType = "bin.base64"
    xmlNode.nodeTypedValue = StrConv(text, vbFromUnicode)
    
    EncodeToBase64 = xmlNode.text
    
    Set xmlNode = Nothing
    Set xmlObj = Nothing
End Function

Function DecodeFromBase64(base64String As String) As String
    On Error GoTo ErrorHandler
    
    Dim xmlObj As Object
    Set xmlObj = CreateObject("MSXML2.DOMDocument")
    
    Dim xmlNode As Object
    Set xmlNode = xmlObj.createElement("b64")
    
    xmlNode.DataType = "bin.base64"
    xmlNode.text = base64String
    
    DecodeFromBase64 = StrConv(xmlNode.nodeTypedValue, vbUnicode)
    
    Set xmlNode = Nothing
    Set xmlObj = Nothing
    Exit Function
    
ErrorHandler:
    DecodeFromBase64 = "오류: 유효하지 않은 Base64 문자열"
End Function

' 워크시트에서 사용:
' =EncodeToBase64("Hello, World!")
' =DecodeFromBase64("SGVsbG8sIFdvcmxkIQ==")
# R Base64 인코딩/디코딩
# 'base64enc' 패키지가 필요합니다
# install.packages("base64enc")
library(base64enc)

encode_to_base64 <- function(text) {
  # 텍스트를 원시 바이트로 변환한 후 인코딩
  text_raw <- charToRaw(text)
  base64_encoded <- base64encode(text_raw)
  return(rawToChar(base64_encoded))
}

decode_from_base64 <- function(base64_string) {
  tryCatch({
    # Base64 문자열을 원시로 변환한 후 디코딩
    base64_raw <- charToRaw(base64_string)
    decoded_raw <- base64decode(base64_raw)
    return(rawToChar(decoded_raw))
  }, error = function(e) {
    stop(paste("유효하지 않은 Base64 문자열:", e$message))
  })
}

# 예시 사용
original_text <- "Hello, World!"
encoded <- encode_to_base64(original_text)
cat("인코딩된:", encoded, "\n")  # SGVsbG8sIFdvcmxkIQ==

tryCatch({
  decoded <- decode_from_base64(encoded)
  cat("디코딩된:", decoded, "\n")  # Hello, World!
}, error = function(e) {
  cat("오류:", e$message, "\n")
})
% MATLAB Base64 인코딩/디코딩
function demo_base64()
    originalText = 'Hello, World!';
    
    % 인코딩
    encoded = encode_to_base64(originalText);
    fprintf('인코딩된: %s\n', encoded);  % SGVsbG8sIFdvcmxkIQ==
    
    % 디코딩
    try
        decoded = decode_from_base64(encoded);
        fprintf('디코딩된: %s\n', decoded);  % Hello, World!
    catch e
        fprintf('오류: %s\n', e.message);
    end
end

function encoded = encode_to_base64(text)
    % 텍스트를 uint8 배열로 변환한 후 인코딩
    bytes = uint8(text);
    encoded = base64encode(bytes);
end

function decoded = decode_from_base64(base64String)
    try
        % Base64 문자열을 uint8 배열로 디코딩
        bytes = base64decode(base64String);
        decoded = char(bytes);
    catch
        error('유효하지 않은 Base64 문자열');
    end
end
// C Base64 인코딩/디코딩 OpenSSL 사용
#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <stdint.h>

char* encode_to_base64(const char* input) {
    BIO *bio, *b64;
    BUF_MEM *bufferPtr;
    
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new(BIO_s_mem());
    bio = BIO_push(b64, bio);
    
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
    BIO_write(bio, input, strlen(input));
    BIO_flush(bio);
    BIO_get_mem_ptr(bio, &bufferPtr);
    
    char* result = (char*)malloc(bufferPtr->length + 1);
    memcpy(result, bufferPtr->data, bufferPtr->length);
    result[bufferPtr->length] = '\0';
    
    BIO_free_all(bio);
    
    return result;
}

char* decode_from_base64(const char* input) {
    BIO *bio, *b64;
    size_t length = strlen(input);
    char* buffer = (char*)malloc(length);
    
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new_mem_buf(input, -1);
    bio = BIO_push(b64, bio);
    
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
    int decoded_length = BIO_read(bio, buffer, length);
    
    if (decoded_length <= 0) {
        free(buffer);
        BIO_free_all(bio);
        return NULL; // 유효하지 않은 Base64 입력
    }
    
    buffer[decoded_length] = '\0';
    
    BIO_free_all(bio);
    
    return buffer;
}

int main() {
    const char* original_text = "Hello, World!";
    
    char* encoded = encode_to_base64(original_text);
    printf("인코딩된: %s\n", encoded);  // SGVsbG8sIFdvcmxkIQ==
    
    char* decoded = decode_from_base64(encoded);
    if (decoded) {
        printf("디코딩된: %s\n", decoded);  // Hello, World!
        free(decoded);
    } else {
        printf("오류: 유효하지 않은 Base64 문자열\n");
    }
    
    free(encoded);
    
    return 0;
}
// Rust Base64 인코딩/디코딩
use base64::{encode, decode};
use std::str;

fn encode_to_base64(text: &str) -> String {
    encode(text)
}

fn decode_from_base64(base64_string: &str) -> Result<String, String> {
    match decode(base64_string) {
        Ok(bytes) => {
            match str::from_utf8(&bytes) {
                Ok(text) => Ok(text.to_string()),
                Err(e) => Err(format!("유효하지 않은 UTF-8 시퀀스: {}", e))
            }
        },
        Err(e) => Err(format!("유효하지 않은 Base64 문자열: {}", e))
    }
}

fn main() {
    let original_text = "Hello, World!";
    let encoded = encode_to_base64(original_text);
    println!("인코딩된: {}", encoded);  // SGVsbG8sIFdvcmxkIQ==
    
    match decode_from_base64(&encoded) {
        Ok(decoded) => println!("디코딩된: {}", decoded),  // Hello, World!
        Err(e) => println!("오류: {}", e)
    }
}

엣지 케이스 및 고려 사항

Base64 인코딩 및 디코딩 작업을 수행할 때 다음과 같은 중요한 고려 사항을 염두에 두십시오:

  1. 유니코드 및 비 ASCII 문자: 비 ASCII 문자가 포함된 텍스트를 인코딩할 때는 Base64 인코딩 전에 적절한 문자 인코딩(일반적으로 UTF-8)을 보장해야 합니다.

  2. 패딩: 표준 Base64는 출력 길이가 4의 배수가 되도록 "=" 문자를 사용하여 패딩합니다. 일부 구현은 패딩을 생략할 수 있지만, 이는 호환성 문제를 일으킬 수 있습니다.

  3. 줄 바꿈: 전통적인 Base64 구현은 가독성을 위해 줄 바꿈(일반적으로 76자마다)을 삽입하지만, 현대 애플리케이션은 종종 이를 생략합니다.

  4. URL 안전 Base64: 표준 Base64는 "+" 및 "/" 문자를 사용하는데, 이는 URL에서 특별한 의미를 가집니다. URL 맥락에서는 "-" 및 "_"를 사용하는 URL 안전 Base64를 사용해야 합니다.

  5. 공백: 디코딩 시 일부 구현은 관대하게 공백을 무시하지만, 다른 구현은 정확한 입력을 요구합니다.

  6. 크기 증가: Base64 인코딩은 데이터 크기를 약 33% 증가시킵니다(3바이트 입력당 4바이트 출력).

  7. 성능: Base64 인코딩/디코딩은 매우 큰 데이터에 대해 계산 집약적일 수 있습니다. 대용량 파일의 경우 스트리밍 접근 방식을 고려하십시오.

참고 문헌

  1. RFC 4648 - Base16, Base32 및 Base64 데이터 인코딩
  2. RFC 2045 - MIME 파트 1: 인터넷 메시지 본문의 형식
  3. MDN 웹 문서: Base64 인코딩 및 디코딩
  4. Base64 - 위키백과
  5. MIME - 위키백과
Feedback