Backends PHP

웹개발자를 위한 문자 인코딩 기초 #1 – ASCII 코드

문자 인코딩의 등장과 ASCII 코드

컴퓨터는 문자를 이진수로 바꾸어서 저장하거나 처리합니다. 이 때 어떤 이진수 숫자가 어떤 문자로 바꾸어어야 하는지는 미리 정해놓은 규칙들이 있습니다. 이것을 문자 인코딩이라고 합니다.

가장 대표적인 문자 인코딩에는 흔히 “아스키 코드”라고 부르는 ASCII(American Standard Code for Information Interchange)가 있습니다. ASCII 코드는 1967년에 처음 제정된 유서깊은 인코딩 방식으로, 미국에서 영문, 숫자, 특수문자들을 위하여 고안한 방식입니다.

ASCII 코드는 본래 7비트로 되어 있습니다. 그러나 현대의 컴퓨터는 1바이트(=8비트)를 기준으로 정보를 처리하기 때문에, 현재는 ASCII 코드 가장 앞 비트에 0을 넣어 8비트로 만들어 사용합니다. 이렇게 만들어진 8비트의 ASCII 코드를 ISO 8859 방식이라고 하는데, 보통 ASCII 코드라고 하면 바로 이 ISO 8859 방식을 말합니다. 16진수로 보면 0x00~0x7F까지 총 128개의 값을 문자를 위해 사용하는 셈이 됩니다. (숫자 앞에 붙은 0x는 10진수 숫자와 혼동하지 않기 위해서 16진수 숫자 앞에 붙여주는 기호같은 것입니다.)

 

ASCII Table을 통해 확인하는 숫자와 문자 간의 관계

각 숫자가 ASCII 코드로 어떤 문자에 대응하는지를 정리한 표를 ASCII Table이라고 부릅니다. ASCII Table이 있으면 우리는 어떤 문자들을 16진수나 10진수 값으로 바꾸는 것이 가능하고, 그 반대도 가능합니다. 이를테면 “Yes!”라는 문장을 ASCII 코드로 표현하기 위해서는, 한 글자 한 글자를 ASCII Table에서 찾아 어떤 숫자인지 찾아주면 됩니다.

ASCII Code 예제

먼저 대문자 Y를 ASCII Table에서 찾아보면, Y는 ASCII 코드에서 0x59에 해당합니다. 다음으로 소문자 e를 ASCII Table에서 찾아보면 0x65가 됩니다. 같은 요령으로 마지막 글자인 느낌표까지 다 찾고 나면, 위 그림과 같이 “0x59 0x65 0x73 0x21″이라는 16진수 숫자쌍 한 줄을 얻게 됩니다. 이것이 바로 “Yes!”를 ASCII 코드로 나타냈을 때의 값이 됩니다!

이것은 반대도 가능합니다. 예를 들어서 16진수로 “0x43 0x61 0x74 0x21″라고 쓰인 문자열을 ASCII 코드로 풀어보고자 한다면, ASCII Table에서 각각의 16진수 숫자가 어떤 글자인지 확인해보면 됩니다. 실제로 풀어보면 0x43은 대문자 “C”, 0x61은 소문자 “a”, 0x74는 소문자 “t”, 마지막으로 0x21은 특수문자인 느낌표가 되어, “Cat!”가 됩니다.

$str = "\x43\x61\x74\x21";
echo $str;		// Cat!

정말로 그러한지는 위의 PHP에서 코드에서 쉽게 확인할 수 있습니다. “\x”는 문자열이나 정규표현식 등에서 16진수를 표시하기 위해 사용되는 기호로, 예를 들면 \x41은 16진수 0x41을 의미합니다 \x를 이용하여 우리가 알고 싶었던 16진수 값을 문자열로 만들고 출력해보면, ASCII Table에서 찾았던 “Cat!”라는 문자열이 그대로 나오는 것을 볼 수 있습니다.

 

ASCII 문자열과 정규표현식

preg_match('/^[A-Za-z]+$/', $str);

ASCII 문자열에 대한 정규표현식에서 가장 유명한 예제는 아마도 위의 코드일 것입니다. 모두 잘 아시는 바대로 이 코드는 주어진 문자열이 대소문자 알파벳으로만 이루어져 있는지를 검사하는 정규표현식입니다. 그런데 때때로 신입 개발자 분들은 종종 위 코드를 보고 혹시 아래와 같은 정규표현식도 가능하지 않을까하는 의문을 가지곤 합니다.

preg_match('/^[A-z]+$/', $str)

앞서 설명한 ASCII 코드에 관한 기반지식이 있다면, 위 정규표현식이 잘못된 이유를 간단하게 설명할 수 있습니다. 위의 정규표현식을 아래처럼 16진수로 풀어서 써보면 되기 때문입니다.

preg_match('/^[\x41-\x7A]+$/', $str);

위 코드를 잘 살펴보면, 사실 A와 z 문자를 ASCII Table에서 찾아 16진수로 바꾸어놓기만 한 것을 깨달을 수 있습니다. 이렇게 놓고 보면 좀더 정규표현식의 의미가 명확해집니다. 이것은 사실 주어진 문자열이 0x41부터 0x7A 사이의 문자들로만 이루어져 있는지를 검사하는 정규표현식인 것입니다.

ASCII Table을 실제로 찾아보면 대문자 알파벳이 0x41에서 A로 시작하여 0x5A에서 Z로 끝나는 것을 확인할 수 있습니다. 이후 소문자 알파벳은 0x61에 가서야 a로 시작하고 0x7A에서 z로 끝나게 됩니다. 그리고 0x5A와 0x61 사이에는 각괄호와 언더바, 역슬래시와 같은 특수문자가 일부 포함되어 있지요. 따라서 [A-z]라는 정규표현식을 사용할 경우, 대소문자 알파벳 뿐만 아니라 위에서 보았던 특수문자 일부도 검사대상에 포함되어버릴 것입니다. 우리가 원하는 결과를 얻을 수 없겠지요.

preg_match('/^[a-zA-Z0-9]+$/', $str);
preg_match('/^[\x61-\x7A\x41-\x5A\x30-\x39]+$/', $str);

여기까지를 잘 이해하셨다면, 위의 두 정규표현식이 같다는 사실도 쉽게 이해하실 수 있을 것입니다. 대소문자 알파벳과 숫자 만을 허용하기 위해 흔히 사용되는 정규표현식으로, 회원정보 화면 등에서 자주 사용되지요.

앞으로 소개할 한글 및 특수문자들에 관한 인코딩들은 2~3바이트가 한 묶음이 되어 비교적 복잡한 규칙을 가지고 있습니다. 그러나 이상의 설명을 잘 이해하고 계시다면, 2편과 3편에 이어지는 한글 및 특수문자 처리 역시 쉽게 이해할 수 있을 것입니다.

2 thoughts on “웹개발자를 위한 문자 인코딩 기초 #1 – ASCII 코드”

  1. 0x가 왜 붙는지 궁금해서 검색해도 안나왔는데 덕분에 감사합니다~

    1. Applatte님, 도움이 되셨다니 다행입니다. “0x”의 경우, 16진수 앞에 붙이는 접두어입니다. 8진수에는 “0”이 접두사로 붙는 경우가 많습니다. 기회되실 때 찾아보시면 좋으실 것 같습니다.

Leave a Reply

Your email address will not be published. Required fields are marked *