문자열 인코딩이란 무엇인가?
컴퓨터에는 문자열 자체를 저장할 수 없다. 컴퓨터에는 숫자가 저장되며, 출력될 때 문자열로 변환될 뿐이다. 즉, 우리가 만약 'a'라는 문자를 저장하면 컴퓨터에는 'a'가 저장되는 것이 아닌 61이라는 16진수 숫자가 저장된다.(10진수로는 97이다).
저장된 2자리 16진수 숫자는 출력될 때 다시 문자열로 변환된다.
이를 확인하기 위해서 Kotlin으로 아래 코드를 실행하면 "ASCII value of a is 97" 이라는 결과가 나온다.
fun main(){
println("ASCII value of a is ${'a'.code}")
}
ASCII 인코딩 방식
처음 컴퓨터가 발명되었을 때는 영어권 국가에서만 언어가 사용되었기 때문에 문자열을 저장할 수 있는 공간이 128개 있는 7비트 크기의 ASCII 인코딩 방식이 개발되었다. ASCII는 American Standard Code for Information Interchange의 약자로 말 그대로 영어만을 위한 인코딩 방식이었다. 그 당시 128개 정도면 영어 알파벳과 각종 제어문자를 저장하는데 충분하였기 때문에 문제가 없었다. 하지만 컴퓨터가 전 세계로 퍼지면서 128개 공간으로는 모든 문자를 표현하기에 충분하지 않게 되었다. 시간이 지난 이후에는 ASCII가 7비트에서 1비트가 확장되어 8비트(256개 공간) 으로 확장되었지만, 여전히 전 세계의 문자열을 표현하기에 충분하지 않은 공간이었다.
*ASCII 테이블에서 어떤 숫자가 어떤 문자를 표현하는지는 아래에서 확인할 수 있다.
ASCII의 한계와 유니코드의 등장
ASCII가 표현할 수 있는 공간이 너무 적자, 전 세계의 문자열을 포함하기 위해 등장한 것이 바로 유니코드(Unicode)이다. 유니코드는 모든 언어와 문자를 하나의 통합된 문자 집합으로 표현하는 것을 목표로 하며, 유니코드는 문자에 고유한 코드 포인트(Unicode code point)라는 숫자를 할당하여 문자를 식별한다. 또한 모든 언어를 4바이트로 표현하는 것은 매우 비효율적이므로, 기존 아스키에서 지원되던 문자에 한해 1바이트를 사용할 수 있도록 하는 가변 길이 인코딩 방식을 사용해 효율성 또한 유지하였다.
유니코드의 인코딩 방식
유니코드에는 다양한 인코딩 방식이 존재한다. UTF-8, UTF-16, UTF-32 가 대표적이다. 가장 많이 사용되는 UTF-8의 특징은 다음과 같다.
UTF-8의 특징
가변 길이 인코딩을 통한 최적화
UTF-8은 가변 길이 인코딩을 사용해 문자를 표현한다. ASCII 문자는 1바이트로 인코딩되고, 추가적인 문자는 2바이트에서 4바이트까지 가변적으로 인코딩된다.
ASCII와의 호환성
UTF-8은 ASCII 인코딩을 호환한다. 즉, UTF-8에서 ASCII 문자는 동일한 바이트 값으로 표현된다. 이를 통해 ASCII 문자열은 UTF-8로 변환할 때 전혀 문제가 없다.
인터넷의 기본 인코딩 방식
앞서 말한 호환성 때문에 웹에서는 UTF-8 인코딩이 널리 사용되며, 대부분의 웹 페이지와 API에서의 기본 인코딩 방식이다.
인코딩 방식 이해의 중요성
모든 프로그래밍 파일들도 문자열들이 인코딩된다. 이 때문에 문자열에 대한 인코딩을 잘못 만지게 되면 문자가 깨질 수 있다. 이를 방지하기 위해 많은 회사들에서는 주석에 한국어를 쓰지 않도록 가이드한다. 또한 특정 문자열에 ASCII로 인코딩 되어 있다면 프로그램을 짤 때, 256개의 문자열에 대한 부분만 고려하면 된다. 이를 통해 더욱 효율적으로 프로그램을 짤 수 있다.
자 이제 마지막으로 언어별로 ASCII 코드를 어떻게 확인하는지 한 번 확인해보자.
언어별 ASCII 코드 확인법
Kotlin
println("ASCII value of a is ${'a'.code}")
Java
int asciiValue = (int) 'a';
System.out.println("ASCII value of a is " + asciiValue);
Python
ch = 'A'
ascii_value = ord(ch)
print("ASCII value of", ch, "is", ascii_value)
JavaScript
var ch = 'a';
var asciiValue = ch.charCodeAt(0);
console.log("ASCII value of", ch, "is", asciiValue);
C#
char ch = 'a';
int asciiValue = (int) ch;
Console.WriteLine("ASCII value of " + ch + " is " + asciiValue);