Swift의 커스텀 타입을 직렬화하기

이 글은 https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types 의 내용을 일부 발췌, 의역한 것입니다.

프로그래밍 분야에서의 많은 작업은 데이터를 디스크에 저장하거나, 네트워크를 통해 전송하거나 API를 호출하기 위해 데이터를 제출하는 등의 일과 관련된다. 이 과정에서 데이터는 전송되는 동안에 적절한 형식으로 인코딩되고 다시 디코딩될 필요가 있다.

Swift의 커스텀 타입을 직렬화하기 더보기

파이썬에서 한글이 깨진다고요? – 파이썬의 한글 입출력과 인코딩에 대해

파이썬의 한글 인코딩에 대해

파이썬의 대화형 인터프리터를 사용하다보면 한글 인코딩의 함정에 빠지기 쉬운데 이를테면 소스를 그대로 해석기로 실행하는 경우에는 인코딩 에러가 안나던 것이, IDLE을 통해서 실행해보면 오류가 난다거나 그 반대의 경우가 있다. 이렇게 이해할 수 없는 상황을 어떻게 해야할까?

몇년 전이라면 그것은 MS의 잘못이거나 파이썬의 잘못이었다. 하지만 윈도에서 한글로 된 데이터를 다뤄야 하는데 파이썬 2를 쓰고 있다면 그것은 매우 높은 확률로 당신의 잘못이다.

파이썬에서 한글이 깨진다고요? – 파이썬의 한글 입출력과 인코딩에 대해 더보기

유니코드 문자열과 문자열 인코딩

컴퓨터는 어떻게 글자를 표현할까

컴퓨터가 처리하는 모든 데이터는 궁극적으로 2진수로 표현되는 숫자값이다. 따라서 컴퓨터가 문자를 처리하도록 하기 위해서는 각각의 글자에 고유한 번호를 부여하여 특정한 숫자값과 특정한 글자를 1:1 로 맵핑하는 것이다. 이러한 문자 맵에서 가장 잘 알려져 있는 것이 아스키(ASCII) 코드이다.

아스키코드는 128개의 알파벳 문자 및 숫자와 문장부호, 몇 가지 괄호와 연산자 문자 그리고 프린터 출력에 필요한 제어 문자등을 정리한 코드 체계이다. 128개의 글자를 포함하고 있기 때문에 (물론 그 중에는 눈에 보이지 않는 글자도 있다.) 이 가지수는 모두 2의 7제곱이며 따라서 1바이트 (8자리) 2진수 값 하나가 문자 하나를 표현하는데 사용될 수 있다. C언어에서는 문자 하나를 표현하는데 char 라는 타입을 쓴다. 사실 이 타입은 아스키코드를 상정한 타입으로 실질적으로는 부호없는 1바이트 정수형이다. 그래서 char 타입끼리는 더하거나 빼는 연산이 가능하다. 실제로 특정한 문자를 대문자로 변환하는 함수는 다음과 같이 작성할 수 있다.

char toUpperCharacter(char lower) {
  char upper = lower;
  if (lower >= 'a' && lower <= 'z'){
    upper = 'A' + (lower - 'a');
  }
  return upper;
}

아스키 코드가 제정된 이후에 추가적인 몇 가지 특수 문자들을 표현하기 위해 확장 아스키코드가 추가로 제정되었고, 128~255사이의 구간에 배정되었다. 이렇게해서 아스키코드를 사용해서 문자를 표현하고 처리하는 것으로 모두들 행복하게 살았으면 좋겠지만….

비라틴 언어의 표현

아스키코드는 1바이트의 정수값을 사용한다고 했다. 여기서 바이트의 크기는 결국 하나의 값의 해상도에 비유된다. 즉 1바이트는 8개의 비트이고 0~255까지 256가지의 값을 표현할 수 있는 셈이다. 아스키코드 전체가 256자로 구성되다보니 1바이트 값 1개면 다른 글자와 혼동되지 않는 독립적인 문자 하나를 표현하기에 부족함이 없다.

문제는 영어문자를 사용하지 않는 국가들에서도 컴퓨터를 사용하면서, 각 국가의 문자를 표현하는 방법이 필요하게 되었다는 점이다. 예를 들어 일본에서는 확장 아스키 코드 영역에 가타카나 문자를 넣어 쓰는 등의 방법을 사용하거나(히라가나는 둥근 모양이 많아서 당시 기술로는 콘솔에서 표현하기가 어려웠다.) 하는 방법을 썼다. 하지만 이 방법으로는 한자를 표현할 공간은 턱없이 부족했다. 그래서 2바이트 문자를 도입하기 시작했다. 어떤 바이트의 첫 비트가 0이면 해당 바이트는 1바이트짜리 아스키 문자 1개로 해석하고, 1이면 그 뒤 바이트까지 연결해서 확장된 코드에 대응하는 문자로 해석하는 식이다.

중국, 일본, 한국등의 글자가 많이 필요한 국가에서 이 방식을 채택해서 문자를 표현하고자 했고, 그에 따라 각 국가는 자국어의 문자를 표현하기 위한 코드 테이블을 별도로 제정하였다. (물론 이 때 한국은 완성형 한글이나 조합형 한글이냐를 두고 의견이 분분하고 어쩌고…하는 일들이 있었다.)

2바이트는 8+8, 즉 16자리 2진수 값이며 이는 65,536가지 값을 표현할 수 있는 단위가 된다. 한글의 모든 자모 조합이 11,172가지이므로 그러면 모든 조합이 여기에 들어가네? 라고 생각했지만, 현실은 그렇지 않았다. 아스키 코드와의 충돌을 피하기 위해 두 바이트 모두 뒤쪽 절반의 비트만을 사용해야 했고, 그 와중에 제어용 비트들은 건드릴 수 없기 때문에 2바이트를 쓰더라도 실제로 가용한 글자수는 8,836자 밖에 되지 않는데, 우리 나라 역시 한자를 사용하기 때문에 상용한자를 위한 공간도 왕창 배정해야 했기에 실제로 표준 완성형에서 지원가능한 글자는 2350자 밖에 되지 않았다. 물론 이 당시 컴퓨터 성능이나 용량측면에서 어쩔 수 없는 부분도 있지만, 2350자는 표준어만 표기하더라도 부족한 글자였기에 당시에 거센 비판과 반발을 샀다.

어쨌거나 비 영어권에서는 이렇게 멀티바이트 문자처리를 이용해서 자국어를 표현하는 방법들을 만들어 내어서 모두가 행복하게 지낼 수 있을 줄 알았는데, 아직 문제는 여전히 남아있었다. 바로 국가간 정보의 호환이다. 멀티바이트 문자처리는 기본적으로 아스키코드와는 호환되지만, 확장한 영역내의 코드값에는 국가마다 다른 문자가 할당되었다. 따라서 다른 국가에서 사용하는 코드 페이지를 기준으로 생성된 문자열은 다른 국가에서는 올바르게 표현되지 않았다.

이 문제를 해결하기 위해서는 모든 언어에서 사용하는 문자들을 하나의 체계에서 모두 독립적인 코드를 부여할 수 있는, 매우 거대한 코드 테이블이 필요하게 되었고 이를 위해서 모든 문자를 표현할 수 있는 단일 코드 체계를 제정하기 위한 움직임이 일어나기 시작했다. 이것이 바로 유니코드이다.

유니코드는 최초 4바이트 크기로 제정되었다가 이후 6바이트 체계로 확장되었다. 6바이트 크기라는 것은 한 글자를 구분하는 고유 값이 2의 48승(6바이트는 48비트) 범위를 가질 수 있는 크기라는 것이다. 이를 십진수로 확장하면 281,474,976,710,656이며, 이는 지구상에 존재하는 모든 문자를 담고도 남고, 아마 우리 은하계에 존재할 수 있는 모든 문자를 다 포함할 수도 있는 방대한 영역이다.

인코딩

유니코드는 여러 종류가 있는 것이 아니라, 국가별로 자국어의 문자를 표현하기 위해 사용하는 코드표에서 코드값이 같은데 국가마다 다른 글자를 표현하게 되는 문제를 방지하기 위해서 그냥 모든 언어의 문자표를 다 합쳐서 정리한 것이라고 보면 된다. 그리고 현대의 대부분의 OS는 내부적으로 이 유니코드를 사용한다. 그런데 인코딩은 왜 필요하며, 어떻게 사용하는 것일까?

인코딩(encoding)이라는 용어부터 살펴보자. 인코딩은 “원래의 raw 데이터를 특정한 규격에 맞게 변환한다”는 뜻이다. 흔히 동영상 데이터를 mp4 등의 포맷으로 압축할 때 인코딩한다는 용어를 쓰는데, 압축포맷에 맞도록 원래의 커다란 동영상 데이터를 정리한다는 의미로 받아들이면 된다. 그렇다면 문자열에서 인코딩은 왜 필요할까? 유니코드를 지원하는 프로그램 혹은 프로그래밍 언어라면 내부적으로는 문자열을 유니코드로 처리하면 된다. 대신에 인코딩은 유니코드 포인트의 연속체인 문자열을 프로그램 외부와 교환하기 위해 어떤 공통된 규격으로 만들기 위해 사용한다. 프로그램 외부에서 문자열을 읽어들이거나 내보낼 때 쓰이는 것이다. 이러한 동작에는 파일에 기록하거나, 네트워크를 통해서 전송하는 등의 동작이 포함된다.

즉 두 개 이상의 프로그램이 텍스트로 된 데이터를 전송하면서 문자가 깨지는 것을 방지하기 위해서는 양측이 모두 인코드/디코드할 수 있는 공통된 규격이 필요하며, 이것은 꼭 유니코드가 아니더라도 필요한 것이다.예를 들어 한 때 많이 쓰이던 EUC-KR은 한글 문자열을 저장/전송하는데 사용하는 규격이다. 비록 이것이 한국어 외의 문자는 제대로 지원하지 못한다 하더라도 한글을 이해하고 표현할 수 있는 문자 체계에서는 어떤 파일이나 데이터가 EUC-KR로 인코딩되었다는 사실을 알고 있고, 이 인코딩을 디코드할 수 있는 코덱이 있다면 해당 데이터를 읽어서 온전한 한글 문자열로 표현할 수 있을 것이다.

인코딩의 선택

뭔가 텍스트를 작성해서 저장할 때에는 가능하면 유니코드의 인코딩인 UTF-8, UTF-16 등을 사용하도록 하자. 아무래도 가장 널리 쓰이기 때문이다. 예전에 많이 쓰이던 EUC-KR의 경우에는 너무 오래된 표준이고, 사실 확장 완성형 한글을 위한 인코딩도 아니기 때문에 2350자밖에 인코딩할 수 없다. EUC-KR이나 CP949등의 인코딩은 코드페이지가 한국어라는 가정이 들어가므로 안전한 인코딩이 될 수 없다. 그렇기 때문에 한국어를 썼다고 한국어 인코딩을 사용해야하는 것이 절대 아니다.

마찬가지로 일본어를 썼다고 EUC-JP나 그외 다른 일본어 인코딩을 쓰는 것도 그리 추천하지 않는다. 가급적이면 유니코드 계열의 인코딩을 사용하자.

프로그램 소스코드의 인코딩

현대의 많은 프로그램 소스 코드 컴파일러 혹은 해석기들은 유니코드를 지원하며, 소스코드가 UTF-8로 인코딩되어 있을 것이라 가정한다. 애플이 사용하는 Clang이 그렇고, 파이썬도 3.x 부터는 그러하다. (그러니까, 파이썬3를 쓰는 사람들은 utf8로 소스를 저장하는 이상, #-*-coding:utf8을 쓰지 않아도 된다.) 대부분의 프로그래머는 아스키코드 범위 내의 문자를 써서 소스를 작성하기 때문에 이 부분에서 크리티컬한 문제가 생기지는 않는 편인데, 주석이나 소스 내에 하드 코딩된 문자열에서 한글이나 한자, 일본어 같은 문자를 쓴다면 소스 코드를 저장할 때 인코딩에 대해 주의를 기울일 필요가 있고, 가능하면 인코딩을 선택할 수 있거나, 최소한 UTF-8을 사용해서 저장하는 소스코드 편집기를 사용해야 할 것이다.

 

20010607 :: 리눅스에서 아이폰 동영상 인코딩하기 (ffmpeg) – 예고편

아이폰으로 동영상을 볼 생각

저 보다 먼저 아이폰을 산 지인들의 이야기를 들어보면 다들 “16기가로는 좀 부족해요”라는 의견이 압도적이었습니다. 그래서 저도 32기가짜리를 샀습니다만… 80여개의 어플을 설치하고 100곡이 넘는 음악과 예닐곱편의 팟캐스트 동영상을 넣어 다니지만 고작 3기가 가량 썼을 뿐이더군요. 흠… 동영상을 넣어다니면서 볼 생각은 못했습니다. 가뜩이나 배터리 사정도 넉넉치 않은 아이폰에… 굳이 동영상을 이동하면서 볼 이유는 없을 것 같았거든요. 근데 최근에 드라마 ‘개인의 취향’을 너무 재밌게 봤는데, 이 녀석을 아이폰에 넣어 다녀 보고 싶었습니다. 아이폰용으로 동영상을 인코딩하는 방법은 H.264 / AAC 코덱을 사용하여 mpeg4 비디오로 인코딩을 하면 된다고 합니다. 다음 팟 인코더나 유마일 인코더 같은 무료 인코더는 예전 경험으로 화질이 매우 안습이었기 때문에, 다른 해법을 조금 더 찾아보기로 하였습니다.

아 이폰에 딱맞는 인코더, handbrake

그 러다 알게된 것이 handbrake라는 인코딩 프로그램입니다. 프랑스에서 만들었다고 하는데 아이폰에 적합한 설정을 자동으로 해준다는 훌륭한 프로그램이더군요. 그래서 설치해보려 하였지만, 윈도 환경에서는 .NET 프레임워크를 설치해야 하고 우분투 환경에서는 새 버전의 GNOME과 호환성 문제가 있어서 그냥은 설치가 안된다고 합니다. (저장소에서 일일빌드를 받아서 설치하면 된다고 하는데, 키 인증이 계속 실패해서 포기했습니다.)

결국 믿을 건 ffmpeg

역시 믿을 건 ffmpeg 밖에 없는 것 같습니다. 그런데 문제는 h.264비디오나 aac 오디오를 처리할 수 있는 코덱이 없다는 것입니다. 조금 알아보니 h264는 x264라는 이름으로 공개 코덱이 있다고 하는군요. aac 같은 경우에는 faac라는 이름으로 존재합니다. 그리고 이러한 코덱들을 설치하기 위해서는 몇 가지 준비가 필요하다고 합니다. 제한된 코덱이나 유틸리티들을 사용해야 하는데, (주로 특정 국가에서 저작권 등의 문제로 기본적으로 설치되지 않은 녀석들이라고 합니다.) 그래서 다음 명령어를 통해 제한된 요소들을 추가로 설치해 줍니다.

$ sudo apt-get install ubuntu-restritct-extras[1. $는 프롬프트 표시입니다. 실제 키보드로 입력하지 않습니다]

그리고 그 외의 음악 파일이나 영상 파일의 인코딩을 위해서는 다음 명령을 통해 제한된 일부 코덱을 추가로 설치할 수 있습니다.

$ sudo apt-get install libavcodec-extra-52

그런데, 이렇게 하더라도 AAC 인코더가 실질적으로 지원되지는 않는 문제가 있습니다. 그래서 또 구글링에 구글링… 대부분의 답변은 이 것들을 싹 밀어버리고 ffmpeg을 새로 컴파일해야 한다고 하는군요. (아 귀찮아 ㅠ_ㅠ)

이후 부분에 내용을 빼지 않으면 포스팅이 저장이 되지 않아, 굳이 예고편으로 먼저 발행합니다. 자세한 이야기는 다음편에….