인코딩
1. 영어 단어 encoding
코드화, 암호화를 의미한다. 한자어 표현으로 부호화(符號化)라고도 말한다. 반대말은 디코딩(decoding, 복호화).
문자가 깨졌을 때, 음악이나 동영상을 휴대기기에 넣으려 할 때 종종 마주하게 되는 단어이다.
컴퓨터에서 인코딩은 동영상이나 문자 인코딩 뿐 아니라 사람이 인지할 수 있는 형태의 데이터를 약속된 규칙에 의해 컴퓨터가 사용하는 0과 1로 변환하는 과정을 통틀어 일컫는다. 이 경우 샘플링이라고도 하며, 디지털 문서에 잘 설명되어 있다. 관습적으로 압축을 하지 않은 RAW 데이터를 샘플링 데이터, 압축 등으로 인해 알고리즘을 모르면 읽을 수 없는 데이터를 인코딩된 데이터로 나눠 쓰는 듯 하나 꼭 그렇다는건 아니라는 것은 알아두자.
2. 문자 인코딩
2.1. 개요
문자 코드를 전산기기 안에서 0, 1로 저장하는 방식.
많은 사람들이 문자 코드와 문자 인코딩을 잘 구분하지 못하지만, 이 둘은 "부호화"라는 관점에서 같지만 "개념"은 엄연히 다르다. 1바이트 인코딩 시절에는 구별 실익이 그리 크지 않았지만, 다국어지원 및 유니코드 체계하에서 2바이트 이상의 인코딩이 필요해지고, 효율성과 호환성에 따라 다양한 인코딩 방법이 등장하면서 이 둘을 잘 구분해야 할 필요가 생겼다.
문자 코드는 문서를 전자화하기 위해, 각 문자와 추상적인 숫자 사이를 짝지어 놓은 것이다. 이와 반대로, 인코딩은 이 숫자를 실제의 전산기기 안에서 저장, 처리하기 위해 만들어진 숫자의 표현 형식이다. 예컨대 '가', '나', '다' 라는 문자를 각각 추상적인 숫자 1, 2, 3에 짝지어놓은 것이 문자 코드이며, 인코딩은 이 숫자를 01, 02, 03 하는 식으로 쓰는 형식에 해당된다. 예시의 인코딩 상으로는 컴퓨터에서 100개 이상의 문자를 쓸 수 없을 것이므로, 이 제한을 없애려면 인코딩을 바꿔서 001, 002, 003 하는 식으로 써야 할 것이다. 그러나 여기서 인코딩은 바뀌었지만 문자 코드가 바뀐 건 아니다.
2.2. ASCII
초창기의 컴퓨터는 사람과 기계어로만 소통을 했었고, 당연히 사용 과정에 상당한 애로사항을 겪었다. 그래서 어셈블리어 등의 사람이 쓰는 문자를 사용할 필요성이 생겼기 때문에, 라틴 문자와 숫자, 몇몇 특수문자를 128개($$2^7$$)의 코드값에 1:1 대응시키는 법을 고안했고, 이것이 바로 최초의 문자 코드라고 할 수 있는 ASCII(American Standard Code for Information Interchange)다.
아스키는 $$2^7$$ 곧 7비트로 이루어졌고, 1바이트 단위로 통신할 때 나머지 1비트는 패리티 코드로 쓰게 되어 있었다. 아스키는 이름에서 나오듯이 근본적으로 정보 교환을 위한 규격이었고, 통신 에러를 감지하기 위한 체크섬이 필요했기 때문이었다. 그러나 이런 간단한 체크섬은 얼마든지 회피할 수 있는 에러들이 발생할 수 있었고, 그래서 이런 패리티 코드는 곧 쓰이지 않게 되었다. 컴퓨터가 8비트=1바이트를 사용하게 되자 대부분의 컴퓨터 업체들은 아스키코드의 7비트 맨 앞에 0비트를 써서 8비트를 채운 인코딩을 쓰게 되었다.
ASCII의 이름에서 볼 수 있듯 미국에서 만들어졌는데, 미국에서 쓰이는 영어를 쓰기 적합한 형태로 만들어졌다. 영어에서 쓰이는 라틴 문자는 diacritics가 없다시피 하기 때문에[1] 넣기가 쉬웠던 것.
하지만 당장 라틴 문자를 공유하는 유럽쪽언어[2] 와, 한자, 한글, 가나, 아랍어따위의, 영어를 제외한 나머지 언어나 글자는 사용할 수 없었다. 그래서 8비트 아스키부호화에서 비어있는 127뒤의 빈 자리를 다양한 글자로 채워넣는 부호화들이 등장했는데, 표준이 아니었으므로 회사마다 모두 다른 글자를 할당했고, 또 각국이 자국어표기를 위해 이 공간을 활용하면서 표준화의 지옥문이 열렸다.
2.3. MBCS 춘추전국시대의 한글 인코딩
여덟번째 비트 자리를 활용하게 되면서 이른바 헬게이트가 열려버렸다. 국경을 벗어나면 코드가 깨져버린다는 것이다. 예컨대 미국에서 제작된 대부분의 SW에서 확장아스키 127 이후의 영역은 프로그램 테두리 등을 그리기 위한 선문자에 할당되었는데[3] , 완성형 한글이 로드된 DOS에서 그 프로그램을 로드하면 이 테두리가 모두 깨진 한글로 표현되었다.
[image]
이렇게. [4]
영어 이외의 언어를 위해서는 국가별로 인코딩 표준을 만들어야 했고, 그 중 대표적인 것이 한국의 완성형과 조합형. 하지만 이것도 한계가 있었고, 한 문서에 여러 언어를 써야 하는 상황(외국어 학습용 교재 등)에서는 그야말로 답이 없었다.
그래서, 이 문제를 해결하기 위해 모든 문자 체계를 한데 몰아넣은 인코딩, 유니코드가 탄생하게 되었다.
2.4. 유니코드 발족 이후의 역사
2.4.1. UCS-2
2 Byte - Universal Character Set. 최초의 유니코드 인코딩인 "고정 2바이트 문자 인코딩".
1980년대부터 7비트 아스키코드의 한계를 벗어나면서 좀더 많은 문자를 표현할 수 있는 멀티바이트 인코딩에 대한 요구가 늘어나며 유니코드 위원회가 발족되었다. 최초의 유니코드 초안에 포함된 문자들은 2^16개(65536개)를 넘지 않았으므로 이진수 16자릿수=2바이트를 써서 인코딩을 하면 모든 문자를 쓸 수 있었다.
그러나 유니코드에 점점 더 많은 문자와 기호들이 추가되자 65536개를 넘어서서 2바이트 안에 다 담을 수 없는 사태가 발생했다.[5] 그래서 IEEE에서 고정 4바이트(32비트)를 사용하는 UCS-4 인코딩을 제안하였다. 그러나 유니코드 콘소시엄을 구성하는 대부분의 회사들은 이미 2바이트 기반 기술에 너무 많은 투자를 해놓은 상태였던 데다가, 대부분의 라틴문자가 8비트 안에 들어가고,세상에서 주로 사용되는 문자 거의 대부분[6] 이 2바이트 이내에 들어가는 상황에서 한 글자당 4바이트 인코딩은 지나친 용량의 낭비라는 점이 문제가 되어 거의 채택되지 않았다.
2.4.2. UTF-16
16-bit Unicode Transformation Format.
고정 길이의 한계를 해결하기 위해 가변 길이 인코딩 기법인 UTF-16이 등장하였는데, 이는 기본적으로는 UCS-2와 같지만, 2바이트를 넘어서는 문자에 대해서는 4바이트로 표현하는 것이다. 이를 위해 0xFFFF[7] 를 넘는 값을 가지는 유니코드는 코드값에서 0x10000을 뺀 뒤 20비트로 표현하여 이것을 10비트씩 쪼개어, 각 10비트값에 각각 0xD800[8] 과 0xDC00[9] 을 더해서 2개의 16비트(총32비트)로 인코딩하는 것이다.
이렇게 하여 일반적인 상황(대부분의 한글, 한자, 일본어 등을 포함한 기본 다국어 평면)에서는 기존의 UCS-2 16비트 인코딩과 호환을 유지하면서도 16비트를 넘어서는 문자를 가변 길이 인코딩으로 표현가능하게 되었다.
다만, UCS-2와 UTF-16는 (코드값이 동일함에도 불구하고) 기본 아스키 코드로 작성된 문서와는 호환되지 않았고, 설상가상으로 컴퓨터 시스템에 따라 1Word 내에서 byte의 순서를 처리하는 방식이 모두 달랐기 때문에(엔디안 문제) 호환성에 문제가 있었다.[10] 엔디안 문제 때문에 BOM(Byte Order Mark)를 달아서 빅/리틀 엔디안을 구분하게 되어 있지만 시스템에 따라 달지 않는 경우도 있는 등 [11] (그리고 리틀 엔디안을 사용하는 시스템에서는 BOM이 안 붙은 파일을 디폴트로 리틀 엔디안으로 읽고, 글자가 깨지는 경우가 허다하다) ......혼파망. 오죽하면 인터넷에서의 정보교환에는 '유니코드'(원래 ucs-2라고 써야 맞겠지만 이런 식으로 부정확하게 언급된다.[12] ) 내지는 UTF-16을 아예 쓰지 말라는 권고하는 글을 심심찮게 볼 수 있다. PHP에서 이걸 PHP6의 차세대 기본 인코딩으로 밀었다가 여론의 뭇매를 얻어맞아 프로젝트 자체가 좌초되고 PHP5에서 바로 PHP7로 건너뛰기도 했다.
2.4.3. UTF-8
8-bit Unicode Transformation Format.
UTF-8은 최소 1바이트, 최대 6바이트를 사용하는 가변 인코딩이다. ASCII와 호환되는 문자 전송의 사실상 표준으로서, 자세한 사항은 문서 참조.
2.5. 관련 항목
3. 문자열 인코딩
문자열을 별도의 방식으로 치환하는 인코딩. 엄밀히 말하면 상위의 문자 인코딩과는 다른 개념이며 문장의 코드화에 가깝다.
문자입력/전송시, 읽지 않는 문자나 기존 예약된 문자가 따로 있어 사용할 수 없는 문자가 있을 때, 이를 회피하기 위해서 돌려 인코딩을 하는 경우가 많다.
또한 표현하는 한도를 넘은 문자열을 집어넣고자 할 때 따로 약속된 코드로 인코딩을 하기도 한다.
심지어는 문자가 아닌 정보를 문자처럼 기록하고자 할 때 별도의 인코딩을 하기도 한다.
보통 URL이나, HTML같은 웹 관련 텍스트에서 종종 마주할 수 있다.
3.1. URL 관련
- URL escape code (퍼센트 인코딩): URL에 공백(스페이스바)를 사용할 수 없는 등의 이유로 별도의 코드를 부여한 URL 기입 방식. 서버에 저장된 첨부파일명을 URL로 표현하기 위해 퍼센트인코딩이 된 파일명으로 바꾸기 때문에, 서버에서 다운로드 된 파일명에 %20, +, %5B 등의 텍스트가 붙어 나오는 경우로 많이 접한다.
- 퓨니코드 (국제화 도메인 네임용): URL에 다국어문자(ASCII와 다른 유니코드 문자)를 표기하기 위해 만들어진 인코딩. http://xn\ aaaaaaa 류의 주소가 이에 해당한다.
3.2. 마크업 언어 관련
마크업에 사용된 기 예약된 문자가 있기 때문에, 이를 회피하여 문자열을 작성해야 하는 이슈가 있다.
다만, 이 경우 인코딩이라기 보다는 "문법"에 더 가깝게 받아들여진다.
예를 하나 들자면, NBSP가 있는데, HTML에서 공백(스페이스바)를 읽지 않아 등의 문자로 치환하여 작성해야 한다.
HTML, XML, 마크다운(=위키) 등의 문서를 작성할 때 신경써야 한다.
3.3. 바이너리 관련
- BASE64: 바이너리(e.g. 이미지) 데이터를 문자 코드에 영향을 받지 않는 공통 ASCII 문자로 표현하기 위해 만들어진 인코딩. 쉽게 말해 이미지를 지원하지 않는 댓글창에 문자열로 이미지를 우겨넣기 위해 사용한다. (...라기 보다는 DB에 이미지 썸네일을 저장하기 위해 사용한다.)[14]
- : 이미지를 문자로 표현하지만, BASE64와는 다르다(...)
4. 동영상 인코딩
4.1. 개요
동영상을 저장하는 방식. 문자 인코딩이 부호화와 관련이 깊다면, 동영상 인코딩은 압축 및 알고리즘과 관련이 깊다.
재생기기가 읽을 수 있는 파일로 변환하고자 할 때(skm, k3g), 동영상의 용량을 줄이고자 할 때(mp4) 필요하다.
4.2. 코덱
코덱은 코딩과 디코딩의 줄임말로서 동영상 인코딩 알고리즘 종류를 지칭한다. H.264 외 여러 종류가 있다.
이하 자세하고 전문적인 서술은 코덱 참고.
4.3. 동영상 인코더
동영상 인코더는 동영상의 코덱을 바꿔 저장하는 프로그램이다.
인코딩은 일종의 압축과정이며, 그 과정이 꽤나 버겁기 때문에 컴퓨터 자원을 많이 소모한다. 그 자원 (CPU, GPU)를 효율적으로 굴리기 위해서 CUDA, OpenCL같은 기술이 들어가며, 어떤 인코더를 쓰느냐에 따라 인코딩 속도는 물론 화질이 갈리기도 한다.
이하 자세하고 전문적인 서술은 동영상 인코더 참고.
[1] résumé, naïve와 같이 diacritics가 있는 영어 단어가 있기는 하지만, 죄다 프랑스어 직수입 어휘이며 그나마도 이런 단어는 몇 없기 때문에 사실상 diacritics를 쓰지 않는 언어라고 봐도 무방하다. diacritics를 쓰지 않는 또다른 언어는 바로 라틴 문자라는 이름의 유래가 된 라틴어.[2] 이런 언어는 글자부호(Diacritic, 디아크리틱)를 많이 쓴다. 같은 문자에서 유래하면서도 글자어딘가에 부호를 더하면, 같은 알파벳인것같으면서 글자부호가 다르면 아예 다른 뜻이거나 글자가 된다. [3] 당시는 GUI환경을 위한 기반이 제대로 갖춰지지 않아서 문자 기반 환경에 선문자를 출력해서 테두리나 표 등을 그렸다.[4] 한자로 된 부분은 袴(바지 고) 자이다. 일본어로는 하카마로 읽는 것으로 알려진 한자이다.[5] 유니코드 항목에서도 알 수 있지만 현재까지 할당된 문자들은 최대 4바이트까지 쓰이고 있다.[6] 기본 다국어 평면, BMP.[7] 이진수 1111 1111 1111 1111, 즉 16비트로 표현할 수 있는 최대 숫자.[8] 1101 10 00 0000 0000[9] 1101 11 00 0000 0000, 참고로 가변길이 인코딩에 사용되는 이 두 유니코드값은 유니코드표에서는 이 용도로 쓰기 위해 비워두었다.[10] 예컨대 '갑'이라는 한글은 16비트로 표현하면 0xAC11인데, 빅 엔디안에서는 앞 바이트인 AC를 메모리의 첫 주소에, 뒤 바이트인 11을 다음 주소에 할당하지만, 리틀 엔디안에서는 순서가 반대이다. 리틀 엔디안이 언뜻 보기에는 비직관적으로 보이지만 8비트와의 하위호환성은 좋다. 리틀 엔디안을 사용하는 대표적인 사례로는 인텔 x86이 있는데, 그 인텔 시스템에 올라앉아 있는 자바 가상머신에서는 빅 엔디안을 사용한다...[11] 윈도우 XP 등의 메모장에서 텍스트를 unicode(빅 엔디안)형식으로 저장하면 BOM을 꼭꼭 붙이지만, 빅 엔디안을 사용하는 많은 시스템은 BOM을 아예 달지 않는다. [12] 윈도우 기본 메모장#s-2에서 저장할 때 인코딩 선택 메뉴에서 ucs-2를 '유니코드'라고 써놨기 때문. 결국 19H1에서 UTF-16으로 변경되었다.[13] 서로 다른 OS에서의 결합 문자를 다루는 방식, 모아쓰기와 풀어쓰기의 "정규화" 방식을 다룬 테이블. 맥에서 압축한 파일명이 윈도우에서 풀어쓰기 되는 현상의 원인이다.[14] 그런데 이 용도를 위한 BLOB 타입의 컬럼이 따로 있고 바이너리를 16진수로 변환하는 함수를 쓰면 되기 때문에 BASE64를 쓰기에는 효율이 떨어진다.