Web/Web지식

우리가 Base64를 사용하는 이유

Blue___ 2021. 2. 18. 15:18
7L2U65Sp67Cw7Jqw64qUIO2VmeyDnQ==

'코딩배우는 학생'의 Base64로 인코딩한 문자열의 예시이다.

Base64 는 Binary 데이터를 아스키 코드 일부와 일대일로 매칭되는 문자열로 단순 치환되는 인코딩 방식이다.

Base64는 6bit당 2bit의 OverHead의 발생으로 기존 데이터보다 30%이상 길어지게 되며 여기에 Encoding, Decoding의 로직까지 추가되므로 성능에도 영향을 끼칠 수 있다. 이러한 단점에도 Base64를 사용하는 이유는 무엇일까.

 

 

📮Base64를 사용하는 이유

<Base64 Encoding Decoding>

Base64를 사용하는 가장 큰 이유는 Binary 데이터를 텍스트 기반 규격으로 다룰 수 있기 때문이다. JSON과 같은 문자열 기반 데이터 안에 이미지 파일등을 Web에서 필요로 할때 Base64로 인코딩하면 UTF-8과 호환 가능한 문자열을 얻을 수 있다.  끝에 '='과 같은 패딩 기호가 있다면 이는 구분자로써 사용되므로 대부분 Base64로 생각할 수 있다.  

 

기존 ASCII 코드는 시스템간 데이터를 전달하기에 안전하지 않다. 모든 Binary 데이터가 ASCII 코드에 포함되지 않으므로 제대로 읽지 못한다. 반면 Base64는 ASCII 중 제어문자와 일부 특수문자를 제외한 53개의 안전한 출력 문자만 이용하므로 데이터 전달에 더 적합하다.

 

 

📮Base 64 인코딩

Base64는 Binary 데이터를 문자로 변환하는데 영향을 받지 않는 공통 ASCII 코드 영역의 문자로만 이루어진 문자열로 바꾸는 Encoding이다. 문자 그대로 64진법(2^6)을 사용하며 Binary 데이터를 6bit 씩 나누고 해당하는 문자를 위의 색인표에서 맞게 치환하는 과정을 거친다. 6bit cut을 진행함에 있어서 모든 문자열이 3개씩 이쁘게 떨어지면 좋겠지만, 아닌 경우도 왕왕 존재하기 마련이다. 그런 경우를 대비해 padding을 하는데 남는자리에 = 기호를 통해서 채워주는 개념이다. 

 

예를들어 '코딩배우는 학생'을 Base64로 인코딩 하면 '7L2U65Sp67Cw7Jqw64qUIO2VmeyDnQ==' 로 2자리의 빈공간을 알려주게 된다. 

 

padding 문자가 반드시 필요한 것은 아닙니다. JSON이나 HTTP 메세지를 통해 데이터 길이를 명시적으로 구분할 수 있다면 더욱 그렇습니다. 하지만 TCP처럼 Stream형태로 데이터를 주고받는 형태에서는 padding이 유용합니다.

 

📮Base 64 디코딩

 

복원한 데이터를 다룰 때 주의할 점은 복원한 데이터만 보면 타입을 특정지을 수 없다는 점입니다. 따라서 데이터 형태와 함께 명시하는 경우가 많습니다.

{
    "type":"image",
    "data":"df123sdzx03=="
}

 

 

📮끝으로

 

Base64는 XML, JSON, REST API등 문자열 기반 데이터를 주고받는 환경에서 multi-form을 다룰경우 함께 사용된다.

필자의 주 언어인 C#으로 모듈을 구현하면 다음과 같다.

 

public class Base64Test{

	//인코딩
	public static string Base64Encoding(string data) //UTF-8 string
	{   
		try{
			byte[] byteTemp = new byte[data.length];
			byteTemp = System.Text.Encoding.UTF8.GetBytes(data);
			string encodedData = Convert.ToBase64String(byteTemp);
			return byteTemp;
		}
		catch(Exception){
			Console.WriteLine("Error");
		}          	   
	} 
    
	//디코딩
	public static string Base64Decoding(string data) //UTF-8 string
	{   
		try
        {
			System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
			System.Text.Decoder utf8Decode = encoder.GetDecoder();

			byte[] decodeToByte = Convert.FromBase64String(data);
			int charCnt = utf8Decode.GetCharCount(decodeToByte, 0, decodeToByte.Length);
			char[] decodedChar = new char[charCnt];
			utf8Decode.GetChars(decodeToByte, 0, decodeToByte.Length, decodedChar, 0);
			string result = new String(decodedChar);
			return result;
		}
		catch(Exception)
		{
			Console.WriteLine("Error");
		}
    } 
}

 

반응형