문자집합과 문자 인코딩 구조

문자집합(character set)은 이름 그대로 문자의 집합이다. ASCII, ISO-8859-1, UCS(Unicode의 문자집합) 등이 문자집합이다. ASCII는 127개, ISO-8859-1는 191개, 가장 최신의 UCS(Unicode 6.2)는 110,182개 문자의 집합으로 정의된다. UCS에 포함되는 문자의 갯수는 Unicode의 버전이 올라가면서 점점 증가하고 있다. 각 문자들은 번호가 매겨진다.

컴퓨터로 이 문자집합을 다루기 위해서는, 각 집합에 속한 문자들을 특정 길이의 정수(코드값)로 표현할 수 있어야 한다. 한 문자집합의 문자들을 코드값 표현하는 방법은 한 가지가 아니다. 예를 들어 UCS의 경우 UTF-8, UTF-16, UTF-32 등으로 표현할 수 있다. 문자 하나를 UTF-8은 8~32 비트, UTF-16은 16*n비트, UTF-32는 32비트 크기의 코드값으로 표현한다. (( 좀 더 엄격하게 표현하자면, 문자에 대응하는 unicode code point를 code unit sequence로 변환한다. )) 이러한 표현방식들을 문자 인코딩 형태(character encoding form)라고 부른다.
이 코드값들로 이루어진 텍스트 데이터를 디스크에 저장하거나 네트워크로 전송하려면 옥텟의 시퀀스로 변환해주어야 한다. UTF-8 같은 경우 아무것도 안 해주어도 되지만, UTF-16 같은 경우엔 엔디안 처리가 필요하다. 이러한 변환방법들을 문자 인코딩 구조(character encoding scheme)라고 부른다.

그러나 컴퓨터 산업에서는 이 개념들을 정확히 잘 구분해서 사용하고 있지 못하다. 예를 들어 MIME의 charset은 마치 문자집합의 줄임말처럼 보이지만 전혀 그렇지 않다. 책 HTTP: The Definitive Guide에 따르면, MIME의 charset은 문자 인코딩 구조(character encoding scheme)와 부호화된 문자 집합(coded character set, 앞에서 말한 문자집합을 좀 더 엄밀하게 정의한 개념)의 의미가 결합된 개념으로 쓰이고 있다. (( HTTP: The Definitive Guide, p377 “Charset Is Poorly Named” )) 따라서 us-ascii, iso-8859-1, utf-8 등이 모두 charset 속성의 값이 될 수 있다. MIME이 이러다보니 HTTP에서도 terminology의 호환을 위해 charset을 MIME에서와 같은 잘못된 의미로 사용하고 있으며, 이 사실에 대해 명시하고 있다. (( RFC 2616 3.4. Character Sets ))

Advertisements

메일주소와 비밀번호만으로 SMTP 설정방법 알아내기

이메일 발송을 위해 메일 에이전트에 SMTP를 설정하려면 알야아 하는 것이 많다. 대략 다음과 같다.

  • 호스트네임
  • 포트번호
  • 사용자이름
  • 비밀번호
  • SSL/TLS 사용여부

하지만 일반 메일 사용자들이 알고 있는 것은 자신의 메일주소와 비밀번호뿐이다. 이것만 가지고 간단히 메일 발송 설정을 하도록 할 수는 없을까?

어느정도 가능하다. you@gmail.com이라는 메일주소에서 SMTP 설정을 알아내는 예를 들어보겠다.

메일주소의 구성

RFC 5322 Section-3.4.1에 따르면 메일주소는 다음과 같이 local-port와 domain으로 구성된다.

addr-spec       =   local-part "@" domain

따라서 you@gmail.com 이란 메일주소에서는 you가 local-port이고 mail.com이 domain이 된다.

설정 알아내기

대개 사용자 이름은 메일주소이거나 local-port이다. 둘 다 상관없이 사용자이름으로 정상 인식하는 경우도 있다. 여기선 메일주소를 사용자 이름으로 간주하겠다.

RFC 6186은 DNS의 SRV 레코드를 이용해 이메일 서버에 대한 정보를 얻어내는 방법을 제시한다. (( SMTP 뿐 아니라 IMAP과 POP3도 가능하다. )) 이 예에서와 같이, 메일주소에서 domain을 얻어낼 수 있으므로, dnslookup을 이용해 SRV 레코드를 읽어 SMTP 서버의 호스트네임과 포트번호를 알아낼 수 있다.

다음은 gmail.com 도메인에 Email Submission에 대한 질의를 보내 응답을 얻은 예이다.

$ nslookup -type=srv _submission._tcp.gmail.com
server:     127.0.0.1
Address:    127.0.0.1#53

Non-authoritative answer:
_submission._tcp.gmail.com  service = 5 0 587 smtp.gmail.com.

위의 결과에서, SMTP 서버의 호스트네임은 smtp.gmail.com이고, 포트번호는 587임을 알 수 있다. 포트번호가 587이라는 것에서 TLS를 사용할 것이라고 추측할 수 있다.

따라서 you@gmail.com의 SMTP 설정은 다음과 같다.

  1. 호스트네임: smtp.gmail.com (dnslookup으로 알아냄)
  2. 포트번호: 587 (dnslookup으로 알아냄)
  3. 사용자이름: you@gmail.com (대개 메일주소와 같다)
  4. SSL/TLS 사용여부: TLS 사용 (포트번호 587에서 추측함)

이 방법의 한계 / 혹은 좀 더 알아봐야 할 것

  • DNS의 SRV 레코드를 통해 SMTP 서버에 대한 정보를 얻어낼 수 있는 경우가 흔치 않다. 사실 gmail.com외엔 모두 실패했다.
  • 사실 포트번호만으로는 TLS를 사용하는지의 여부를 결정하기 어렵다. 이 문제의 해결을 위해 TLSA 레코드를 이용하는 방법에 대한 제안이 있다. fanf-dane-mua-00 드래프트를 보라.
  • 사용자이름은 그냥 메일주소인 경우가 많지만 항상 그런지는 확신할 수 없다.

SMTP 설정에서 SSL과 TLS의 차이

메일 클라이언트를 설정할 때, 메일 발송을 위해서 POP3 혹은 SMTP 설정을 하게 된다. SMTP 설정의 경우, 보안 설정을 SSL로 하는 경우도 있고 TLS로 하는 경우도 있다.

SSL과 TLS는 무엇이 다른가? SSL이냐 TLS냐를 잘못 선택하면 메일 발송 기능이 동작하지 않는 것으로 보아서 둘이 서로 다른 것 같지만 사실 둘은 한 줄기다. SSL 3.0이 버전이 올라가면서 TLS 1.0이 된 것이다. 다시 말해 SSL은 TLS의 옛날 이름이라고 봐도 크게 틀리지 않다. (( 이 둘의 차이는 파이어버드와 파이어폭스의 차이 만큼밖에 없다, 라고 하려다가 파이어버드의 인지도는 파이어폭스의 백분의 일도 안되는 것 같아 그만두었다. ))

SMTP로 메일을 발송할 때 SSL이냐 TLS냐에 따라 달라지는 것은 딱 한가지다. SSL로 통신하는 경우에는 처음부터 암호화된 통신을 하게 되나, TLS의 경우엔 처음엔 암호화되지 않은 hello 메시지를 전달하는 것에서 시작한다. 이 메시지를 주고 응답을 받아 상호간 암호화된 통신이 가능함을 확인한 뒤에서야 비로소 암호화된 통신을 시작한다. 이 시점부터는 SSL이나 TLS나 같다. 자세한 설명은 이 글을 보라.

대부분의 메일 서비스라면 두 가지 다 지원할 것이다. 그런데 메일 에이전트나 메일 발송 라이브러리가 TLS를 제대로 지원하지 않는 경우가 있다. 혹시 TLS로 해서 안된다면 SSL로 바꿔보자. 포트번호도 물론 바꿔줘야 한다. TLS를 사용하는 경우는 보통 587이고 SSL이라면 465일 것이다.

vim에 능숙해지는 법

vim은 익숙해지기 어려운 에디터로 정평이 나 있다. 단축키를 외우지 않고서는 글자 하나도 입력할 수 없기 때문이다.

내가 vim을 배운 방법

나는 2007년 9월부터 vim을 쓰기 시작해서, 2008년 봄 쯤 부터는 능숙하게 사용할 수 있게 되었다. 내가 vim을 익힌 방법은, 그냥 배운 것을 적는 것 뿐이다.

  1. 단축키나 기능을 익혔다면 적어둔다.
  2. vim을 쓰다가 모르는 기능이 있다면 우선 적어둔 것에서 찾아본다. 없다면 찾아보고 적는다.
  3. 완전히 외운 것은 지운다.

완전히 외워서 지우게 된 명령어의 갯수가 15개를 넘어서면 별 불편없이 vim을 사용할 수 있을 것이다(몇달 걸린다).

부연설명

  • 외운 것을 지우는 이유는, 다음번에 찾는 시간을 줄이기 위함이다. 적은 것이 10-20개라면 그 중에서 하나 찾는데 별로 시간이 들지 않지만 30-40개쯤 되면 찾기도 피곤해진다.
  • 지우는 것에 대해 너무 망설이지 말자. 혹시 외웠다고 생각했는데 까먹었다면 그냥 다시 구글링해서 적어넣으면 된다. 그래도 걱정이 된다면 언제라도 지운 것을 복원할 수 있도록 이 메모를 git 등으로 버전관리하는 방법을 추천한다.
  • 적을 필요 없이 매번 구글링하면 되지 않나 하는 생각이 들 수도 있는데, 구글링을 통해 찾은 글을 해석해서 적용 가능한 해결책을 찾아내는 것 보다는 직접 적은 것을 보는 것이 시간면에서 효율적이다. 또한 나는 익힌 것을 적는 행위와, 나중에 그것을 보면서 적었을 때의 상황을 연상하는 행위가 학습효과를 높일 것이라고 믿고 있다.

이 방법에 대해 더 자세하게 잘 설명한 글이 있어 링크한다: vi 배우기 — “컨닝 페이퍼” 기법

vim과 쉘을 연동하여 사용하기

vim은 그 자체로도 상당히 강력하지만, 쉘과 함께 사용함으로써 서로의 강력함을 곱할 수 있다. vim과 쉘을 연동해서 쓰는 방법들을 몇가지 소개한다.

여기서 소개하는 방법들은 gvim이 아닌 터미널에서 실행하는 vim을 위한 것이다.

쉘로 나갔다가 돌아오기

vim 사용중에 Ctrl+z로 쉘로 나가서 명령을 실행한 뒤, 쉘에서 fg를 입력해 vim으로 돌아온다. 이건 vim과는 아무 상관도 없는 기능이지만, 사실 vim에서 쉘 명령을 써야 할 때 가장 많이 쓰는 방법이다. (쉬우니까)

screen 혹은 tmux

vim은 자신 안에서 쉘을 띄우는 기능이 없다. 플러그인이 있긴 한데 그다지 쓸만하지 않다. 필요하다면 그냥 screen이나 tmux를 써서 창을 쪼개 한쪽 창에 vim을 띄우는 것이 훨씬 낫다.

옛날엔 screen에서 세로 쪼개기를 지원하지 않아 영 쓰기기 좋지 않았지만, 버전 4.01이후부터는 잘 지원한다.

screen에서는 C-a S로 창을 쪼개고, C-a <Tab>으로 창을 오가며, C-a c로 쪼개진 창에 쉘을 띄운다.

tmux에서는 C-b "로 창을 쪼개고, C-b o로 창을 오간다. 창이 쪼개지는 순간 바로 해당 창에 쉘이 실행되므로 별도로 쉘을 실행해 줄 필요는 없다.

쉘 명령 실행

쉘 명령은 :!로 실행할 수 있다. 예를 들어, ls를 실행해본다면,

:!ls

:r!로 표준출력을 바로 붙여넣을 수 있다. ls를 실행한 결과를 vim에 바로 붙여넣고 싶다면,

:r!ls

선택한 영역을 쉘명령의 표준입력으로 넣어 표준출력으로 출력된 결과가 그 영역을 대체하게 할 수도 있다. 선택한 영역에서 특정 단어가 포함된 줄만 남기려면,

:'<,'>!grep word

클립보드

엄밀히 말해 클립보드는 쉘과 아무련 관련이 없지만, 많은 사용자들이 GUI 환경에서 가상터미널을 띄워 쉘을 사용하고 있을 것이고, 그렇다면 클립보드를 통해 vim에 복사-붙여넣기를 해야하는 상황도 꽤 자주 발생할 것이다.

클립보드에 복사하려면 복사할 영역을 선택하고,

"+y

클립보드에 들어있는 문자열을 vim에 붙여넣기하려면,

"+gP

클립보드와 연동하여 복사/붙여넣기를 하려면, vim이 xterm_clipboard가 가능한 상태로 빌드되어 있어야 한다. vim --version을 했을 떄, +xterm_clipboard가 보인다면 가능한 상태인 것이다.

vim-slime

shell 연동의 종결자라 할 수 있는 굉장한 플러그인이다. 뭐가 가능한고 하니, screen이나 tmux로 창을 쪼개서 한쪽 창에는 vim을 띄우고 다른 창에는 repl을 띄운 다음에, vim에서 작성한 코드를 바로 다른 창의 repl에 보내서 실행시킬 수 있다.

단점은 잘 동작하지 않는다는 것이다.

vim-slime은 screen과 tmux를 지원하는데, 여기서는 screen과 함께 사용하는 법을 소개하겠다.

우선 .vimrc 설정에 몇가지 추가해야 하는 것이 있다.

$ echo 'let g:slime_target = "screen" >> ~/.vimrc

screen은 표준입력을 받아들이지 못하므로, 대신 파일을 이용해 통신해야 한다. 이 때 사용할 파일도 설정해준다.

$ echo 'let g:slime_paste_screen = "~/$HOME/.slime_paste"' >> ~/.vimrc

screen을 실행한 뒤 창을 하나 쪼개고 세션의 이름을 적당히 붙여준다. 여기서는 ‘shell’이라고 이름붙였다.

$ screen -S shell

그리고 다른 창에 가서 vim을 열고 간단히 코드를 작성한 뒤,

Ctrl+c Ctrl+c

이렇게 하면 현재 줄이 옆 창의 쉘에 입력된다. 다만 처음에는 세션 이름과 윈도 이름을 물어본다. 세션 이름은 위에서 정했고, 윈도 이름은 아마 0일 것이다.

한번 입력하고 나면 다시 묻지 않는다. 잘못 입력했다면 다음의 명령으로 다시 입력할 수 있다.

Ctrl+c Ctrl+v

vim을 위키처럼 쓰기

저번 포스팅에서 이야기했었지만, 나는 컴퓨터로 메모를 할 때 vim으로 편집하여 한 디렉토리에 페이지 하나를 파일 하나로 저장하며 버전관리는 git 으로 한다. 원래는 위키엔진을 설치하여 웹브라우저로 보고 편집했지만, 3년전부터 이 방식으로 바꿨다. vim으로 충분히 웹브라우저를 대체할 수 있음을 알았기 때문이다.

위키엔진과 웹브라우저의 조합이 제공해주는 기능을 vim으로 대체하기 위해 다음의 단축키 및 기능들을 사용한다.

링크 따라가기

링크된 페이지(파일)를 열어야 할 때는 링크에 커서를 놓고 다음 명령을 입력한다. 커서 위의 단어로 파일을 여는 명령이다.

g f

새 윈도를 열어 링크된 페이지(파일)를 열어보고 싶다면,

Ctrl+w f

링크된 페이지를 본 뒤 다시 원래 페이지로 돌아가려면,

Ctrl+o

자동완성

위키페이지 이름을 입력할 때 자동완성이 필요하다면,

Ctrl+x Ctrl+f

현재 디렉토리에 있는 파일 이름으로 자동완성된다.

커밋

Git 저장소로 쉽게 커밋하려면 VCSCommand 플러그인이나 fugitive를 사용한다.

VCSCommand 로 커밋하려면 다음과 같이 ex 명령(:을 입력하면 들어가지는 그것)을 실행한다.

:VCSCommit 커밋로그

fugitive에선 이렇게 하면 된다.

:Gcommit -m 커밋로그

fugitive가 더 기능이 좋은데 종종 불안정한 모습을 보인다. 문제가 있는 것 같다면 VCSCommand를 사용하자.

검색

vim에서 grep을 사용할 수 있다. 다음과 같이 ex 명령을 입력하면 된다.

:grep 키워드

날짜/시각 넣기

가끔 오늘 날짜와 시각을 넣어줘야 하는 경우가 있다. :r!으로 쉘명령을 실행해서 표준출력 을 바로 붙여넣기 할 수 있다. 따라서 리눅스라면 다음의 명령으로 현재 날짜와 시각을 바로 입력할 수 있다.

:r! date

표 정렬

그다지 자주 쓰이지는 않지만, 종종 표를 그려야 하는 경우가 있다. 사실 이것만큼은 vim만으로는 좀 보기가 힘들다. 조금이라도 더 나아보이도록 하기 위해 정렬이라도 해주자.

정렬을 위한 플러그인은 align, Tabular 등이 있는데, 나는 Tabular를 사용한다. 정렬할 내용을 블럭으로 선택하고 다음의 명령을 입력하면 |을 기준으로 정렬한다.

:Tab/|

합계 계산

이것도 역시 쓸 일은 매우 드문데, 아주 간혹 유용하다. 숫자들을 블록으로 선택하고 다음의 ex 명령을 입력하면 선택한 숫자들의 합계가 계산된다.

:VisSum

VisSum 플러그인이 설치되어 있어야한다.

VirtualBox: Ubuntu 호스트 + Windows 7 게스트(bootcamp)

나는 맥북에어에 MacOSX Lion, Ubuntu 12.04, Windows 7을 모두 설치해서 사용하고 있다.

MacOSX를 쓸 때는, Parallels가 워낙 훌륭해서 간단히 부트캠프에 설치된 Windows 7을 잘 인식해서 가상머신으로 사용할 수 있었는데, Ubuntu 12.04 호스트에 VirtualBox를 써보니 알아서 뚝딱 되지는 않았다. 하도 잘 안되서 그냥 윈도 필요할 때 마다 재부팅을 하곤 했었는데, 어제 맘먹고 구글링 좀 해서 성공시켰다.

사실 우분투라고 해서 특별한 건 없고, 다른 OS에서 물리디스크에 설치된 운영체제를 가상머신으로 사용하는 방법을 그대로 적용하면 된다.

우선 윈도가 설치된 파티션을 알아낸다. df -hfdisk -l를 이용하면 될 것이다.

$ fdisk -l /dev/sda
...중략...
Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1      409639      204819+  ee  GPT
/dev/sda2          409640   143771647    71681004   af  HFS / HFS+
/dev/sda3       391034632   392304167      634768   af  HFS / HFS+
/dev/sda4   *   392304640   482023423    44859392    7  HPFS/NTFS/exFAT

위에서 보다시피 /dev/sda4 에 윈도 파티션(NTFS)가 설치되어있다. 그럼 이제 이 파티션을 이용해 가상 디스크(vmdk)를 만든다.

sudo VBoxManage internalcommands createrawvmdk -rawdisk 
/dev/sda -filename /path/to/bootcamp.vmdk -partitions 4

이렇게 하면 /path/to 경로에 bootcamp.vmdk 파일과 bootcamp-pt.vmdk 파일이 생긴다. 둘 다 사용할 수 있도록 읽기/쓰기 권한을 준다.

sudo chmod u+rw /path/to/*.vmdk

일반 유저 권한으로 가상머신을 사용하려면, 유저를 disk 및 vboxusers 그룹에 포함시켜야 한다.

sudo usermod -a -G disk,vboxusers <username>

설정이 반영될 수 있도록 로그아웃 후 로그인 한다.

마지막으로 VirtualBox를 실행하여 Windows 7 가상머신을 생성한다. 생성 중 “가상 하드디스크” 선택을 할 때 “기존 하드 디스크 사용하기”를 고르고 /path/to/bootcamp.vmdk 를 선택하도록 한다.

이렇게 하고 나면 문제없이 잘 동작할 것이다.