가이의 다락방

CarriageReturn 본문

Study/C

CarriageReturn

gaiserne 2010. 6. 7. 22:04

캐리지 리턴(Carriage Return)


486 혹은 그 이전 컴퓨터를 사용하였거나 타자기를 사용했던 세대라면 캐리지 리턴에 대하여 사용하여 보았거나 혹은 들어보거나 본적이 있을 것입니다. 요즘에는 매우 보기 힘들고 쓸 일도 없을 것임에도 언급을 하는 이유가 뭘까요? 언어 게시판에 이러한 글을 썼으니 분명 프로그래밍 언어랑 연관이 있을 텐데 무슨 연관일까!?


우리가 사용하는 컴퓨터의 키보드의 유래는 타자기에서 왔습니다. 쿼티(QWERT) 배열 자판의 시작이 타자기라는 뜻입니다. 타자기를 영화에서 본 사람이라면 타자를 칠 때마다 종이가 옆으로 글자 하나의 크기만큼 밀려나고 끝까지 도달하면 종이가 위로 올라가면서 줄이 바뀌고, 그것을 손으로 밀어서 다시 처음부터 시작하는 것을 알 수 있습니다. 이 시스템이 그대로 내려와서 컴퓨터로 타자를 칠 때에도 줄 바꿈과 줄의 처음으로 돌아가는 기능이 초기에는 따로 있었습니다. 즉 다음 글자를 치기 위해 줄을 바꾸는 명령어와 가장 처음위치부터 줄을 쓰기 위해 캐리지(타자를 쳤을 때 글이 찍히는 위치)가 리턴(처음위치로 돌아가는)되는 명령어가 별도로 존재하였던 것입니다.


워드 프로세서의 사용이 흔해진 지금에 와서 이러한 기능은 필요치 않게 되었죠. 엔터키를 누른다는 것은 줄을 바꾸는 것이고, 새로운 줄을 바꾸는 것은 새로운 문장의 시작이니 커서가 처음으로 가는 것이 당연합니다. 타자기에는 그러한 기능을 당시 기술로는 넣을 수 없었기 때문에 일일이 손으로 돌려야 했으며, 초기 컴퓨터에서는 익숙한 접근을 위하여(혹은 그러한 시스템이 너무나 익숙하여) 그랬던 것으로 생각됩니다. 그러나 오늘날 워드 프로세서를 사용해 보면 알 수 있듯이 더 이상 줄 바꿈과 커서의 이동을 나누는 것은 무의미하다 할만하죠.


그럼에도 이것을 알아야 하는 것은 UNIX와 WINDOWS 그 외 여러 시스템에서 이러한 것이 문제를 일으킬 가능성을 가지고 있기 때문입니다. 대표적으로 문자 코드중 하나인 ASCII 코드의 테이블을 보면 10번에 LF(New line Feed), 13번에 CR(Carriage Return)이 있음을 알 수 있습니다. 오래된 시스템일수록 이 구분이 명확합니다. 그렇다면 이것이 도대체 어떤 문제를 일으키는 것일까? 우선 다음을 알아야 할 것 같군요.


1. Mac 9.x 에서는 CR, Linux/Unix/Max X 에서는 LF, Windows 에서는 CR-LF 가 줄 바꿈 명령 이다. 또한 그 시조가 Unix 계열인 C는 LF를 줄 바꿈에 사용한다.

2. 따라서 일반적으로 문서의 끝에 LF를 붙임으로 줄 바꿈을 표시한다.

3. 그러나 Windows에서는 CR+LF를 사용하여 줄 바꿈을 수행하므로 LF만 있는 문자를 만나면 자동적으로 CR+LF로 대처한다.


자 이제 윈도우에서는 유닉스 계열의 문서를 읽을 때 생기는 문제점을 CR+LF로 바꿈으로 해결한다는 것을 알 수 있게 되었습니다. 그런데 만약 반대의 경우는 어떨까? 윈도우에서 작성된 문서를 리눅스에서 읽게 된다면? 안타깝게도 직접 읽게 된다면 이상한 문자가 표현됨을 확인할 수 있을 것입니다. 윈도우에서는 문서 작성 시 줄 바꿈을 하게 되면 LF가 아닌 CR+LF로 기록하기 때문입니다.


이를 확인하기 위해서 윈도우 메모장에서 그림 1의 내용을 저장한 뒤 16진 코드의 형태로 읽어 보겠습니다.


그림 1. 윈도우에서 저장된 텍스트.


울트라 에디트를 이용할 경우 쉽게 16진 형태로 읽을 수 있으나, 저는 그게 없는 관계로 C에서 직접 소스를 작성하여 보았습니다. lol


그림 2. 테스트 소스.


그림 2 에서 보다시피 Test_Carriage.txt 파일을 읽어 들인 후 파일이 끝날 때까지 문자를 읽어 들여 16진 형태의 숫자로 화면에 출력하도록 하였습니다.


그림 3. 결과 출력 화면.


자 이제 결과를 분석해 봅시다. 문자 사이에는 여백이 들어가도록 하였기 때문에, 그림 3에 나타난 출력결과를 보면 문자는 총 17개이며, 이것은 그림 2 소스 화면에 있는 9개의 문자와는 전혀 다름을 알 수 있습니다. 그림 2에는 한글 6자 특수기호 3자 가 들어가 있습니다. 그렇군요. 한글은 2바이트를 차지한다고 어디선가 들은 기억이 있습니다. 그렇다면 여기서 한글은 총 12 바이트의 크기를 가지며, 전각 기호인 ‘~’은 아스키코드로서 각 1바이트 이므로 3바이트 그리고 예상한 바와 같이 CR, LF문자인 0x0D, 0x0A가 눈에 보이지 않지만 줄 바꿈 표현을 위해 삽입된 것이었습니다. 그럼 화면 처음에 나타난 B2A5는 한글 ‘꺄’를 나타내겠군요?

이를 위해 가장 많이 쓰인다는 유니코드에서 B2A5를 검색해보니... 이런 아닙니다! 그럼 완성형!?


그림 4. 한글의 문자표에서 찾아본 코드값.


네 한글의 문자표에서 검색해보니 B2A5 라는 숫자와 ‘꺄’라는 문자가 대응되는 표는 완성형(KS)문자표입니다. 윈도우가 어떤 문자표를 사용하는지도 이제 알 수 있겠군요. 윈도우는 확장형 완성형 코드를 사용하고 있었습니다.


이를 통해 해석하면 출력화면은 입력된 문자에 대해 표 1. 과 같이 대응됨을 알 수 있습니다.


표 1. 완성형 코드와 대응되는 16진 값.

확장 완성형

아스키

확장 완성형

~

~

~

[LF]

B2

A5

BF

EF

7E

7E

7E

D

A

BF

EC

B3

A2

BF

EC

B3

A2


윈도우가 확장 완성형을 사용한다고 하였는데, 완성형과 아스키가 어떻게 공존할 수 있는 걸까요? 제 생각을 말하자면 그것은 말 그대로 아스키의 확장이기 때문에 가능합니다. 아스키는 아시다시피 7비트를 사용합니다. 따라서 8비트(1Byte)를 기본으로 하는 통신에서는 1비트의 여분을 이용하여 상위 1비트가 0이면 아스키로서 코드를 읽어내며, 1일 때는 아스키외의 확장형으로 읽어 들입니다. 윈도우에서는 상위 비트가 1 일 때, 그 다음 바이트까지 하나의 문자로 인식하여 기본적으로 확장 완성형코드로 인식하게 되어있는 것 같군요. 그리고 더불어 아스키 코드에 있는 0x0D, 0x0A를 통해 줄 바꿈에 CR, LF 둘 다 사용하고 있음을 알 수 있습니다.


이러한 문서를 Linux계열로 옮긴다면 어떻게 될까요? LF는 정상적으로 줄 바꿈이 이루어지겠지만, CR 문자는 분명 오류가 날겁니다. 실제로도 Linux에서 vi를 이용하여 윈도우에서 작성된 문서를 보게 되면 CR을 ‘^M’로서 잘못 표현함을 알 수 있습니다. 이를 위해 DOS 형태의 문서 읽기가 있기는 하지만 분명한건 별다른 대응을 하지 않으면 오류가 날 수 있다는 것이지요.