우리는 C/C++ 언어에서 포인터란, 정수와 비슷한 형태이긴 하나 일반적인 숫자가 아니라 메모리 주소를 가리키는 특수한 자료형이라고 배운다. 포인터는 하드웨어 친화적이고(기계 입장에서 아주 직관적임) 매우 강력한 프로그래밍 요소이지만, 그만큼 길들여지지 않은 야생마처럼 위험 부담이 크다. 포인터 자체하고 포인터가 가리키는 메모리 영역이 따로 놀 가능성이 언제든지 있기 때문에 memory leak, dangling pointer 같은 위험에 노출되기가 매우 쉽다. 자유라는 약이 무질서라는 독으로 변질될 여지가 큰 것이다.

포인터의 값은 다른 지역/전역 변수의 주소로부터 얻어지거나 아니면 메모리 할당 함수를 통해 생성된다. 우리가 직접 상수 값을 대입하는 경우는 거의 없으며, 두 포인터의 값의 차이를 상대적으로 비교하는 경우는 있을지언정, 포인터가 나타내는 그 숫자 자체는 프로그래머에게 사실상 아무 의미가 없다.

사실 이 숫자가 무엇을 의미하는지는 C/C++ 언어의 영역이 아니라 그 언어를 돌리는 플랫폼 내지 운영체제의 영역으로 넘어가게 된다. 포인터란 그만큼 저수준인 존재이며, C++ 이후에 등장한 더 진보한 언어들은 포인터를 더 다루기 편하고 덜 위험한 형태로 어떻게든 감싸고 포장하고 더 상위 계층을 만들려고 애쓰고 있다.

우선 0은 NULL 값으로 유명하며, 윈도우 운영체제의 경우 0뿐만이 아니라 그 이후 0xFFFF 번지까지가 모두 오류로 간주된다. 즉, 이 영역은 운영체제가 어떤 경우에도 메모리를 가리키는 주소로 절대 인정하지 않으며, 오히려 응용 프로그램이 일반 숫자를 포인터로 착각하고 잘못 사용한 것으로 간주하여 무조건 오류를 일으켜 주겠다는 뜻이다. 이런 정책은 사실 프로그래머에게 굉장히 유용하다. 16비트 범위 안에 드는 작은 숫자는 메모리 주소보다는 인덱스 번호 같은 일반 숫자의 의미를 갖는 경우가 훨씬 더 많기 때문이다.

그 후 32비트 윈도우를 기준으로, 64KB부터 2GB까지는 응용 프로그램이 마음대로 사용할 수 있는 “사용자 영역”이다. 이 공간에 나의 EXE, DLL들이 로딩도 되고, 스택/힙 같은 메모리 공간이 할당되고 모든 일이 일어난다. 한 프로세스는 다른 프로세스의 이 영역을 넘볼 수 없다.

단 여기서 잠깐 예외가 있는데, 윈도우 9x는 앞부분의 64KB부터 4MB까지가 또 도스 및 16비트 윈도우 프로그램과의 호환성 유지를 위한 고정된 공용 주소로 예약이 되어 있다. 이런 이유로 인해 윈도우 9x는 4MB에 해당하는 0x400000보다 낮은 메모리 주소에다가는 32비트 바이너리를 불러올 수 없다. EXE/DLL의 preferred base가 이보다 더 낮은 주소인 데다가 재배치 정보까지 들어있지 않다면 그 바이너리는 윈도우 2000/XP 이상에서는 실행 가능하지만, 9x에서는 실행할 수 없게 된다. 비주얼 C++을 보면 EXE의 디폴트 기준 주소가 0x400000으로 잡혀 있는데, 이것은 윈도우 9x와의 호환성을 고려한 귀결이다.

NT급 윈도우는 0x80000000부터 커널이 사용하는 메모리 영역이 시작된다. 쉽게 말해 32비트 포인터로 가리킬 수 있는 4GB의 영역을 응용 프로그램이 2GB, 커널이 2GB로 반반씩 나눠 쓴다는 뜻이다. 물론 여기 부근에도 NT 계열과 9x 계열 윈도우는 메모리를 사용하는 방법이 대동소이한 차이가 존재한다.

NT급 윈도우에는 0x80000000 이전의 64KB 공간을 또 떼어서, 프로그래밍의 편의상 무조건 사용하지 않고 여기에 접근하는 것을 에러로 간주하는 영역을 또 두고 있다. 0~0xFFFF의 용도와 마찬가지이며, 말 그대로 사용자 영역과 커널 영역 사이에 안전을 위해 마련해 놓은 "메모리의 비무장 지대"인 셈이다.

한편 9x 계열은 그런 것은 존재하지 않는다. 대신 0x80000000부터 0xC0000000 사이의 1GB를 “공유 메모리 전용 영역”으로 지정하여, 일부 운영체제 커널 DLL과, 응용 프로그램들이 생성하는 ‘공유 메모리’(memory mapped file)를 이 영역에다 따로 두고 있다. 물론 NT 계열은 그런 것들도 다 구분 없이 사용자 영역에 저장된다. 실제로는 같은 물리 메모리를 가리키더라도 이를 가리키는 포인터의 값은 프로세스마다 다 다를 수 있다는 것이다. 이런 이유로 인해, 공유 메모리를 생성해 보면 9x 계열은 메모리 위치가 0x80000000을 상회하는 높은 주소인 반면, NT 계열은 심지어 자기 EXE가 로딩된 0x400000보다도 낮은 위치에 매핑이 된 경우도 볼 수 있다.

본인 생각에, 이것은 안정성을 약간 희생하여 좀더 작고 빠른 저사양 친화형 OS를 추구한 9x 계열의 고육지책으로 보인다. 사용자 영역에는 진짜로 각 프로세스마다 따로 돌아가야 하는 메모리만 넣고, 조금이라도 프로세스들이 공유할 여지가 있는 메모리는 여기에다가 따로 옮겨 둔 것이다.
이런 구조상의 차이로 인해 윈도우 9x는 NT 계열만치 커다란 메모리 맵 파일 내지 공유 메모리를 생성할 수 없다. 모든 응용 프로그램들이 1GB짜리 공간 안에서 바둥대며 살아야 하기 때문이다. 하지만 NT 계열은 설령 공유 메모리라 할지라도 마치 자기 개인 메모리 다루듯이 얼추 2GB 안에서 자유롭게 그런 것들을 만들어 보호도 잘 받으면서 쓸 수 있다.

나머지 영역은 전부 커널이 사용한다. 프로세스, 스레드 같은 각종 커널 오브젝트를 생성하고 가상 메모리 내지 페이지 파일들을 관리하기 위한 메모리이다. 쉽게 말해 메모리를 관리하기 위한 메모리. 무슨 커널이 최하 1GB에 넉넉잡아 2GB까지씩이나 주소를 차지하고 있어야 하냐 질문할지 모르는데, 결론부터 말하면 그 정도 공간은 반드시 있어야 하며 사실 2GB조차도 부족한 감이 있다.

NT급 운영체제는 커널 영역의 주소가 사용자 응용 프로그램으로부터 완벽하게 보호받고 있으며 user가 커널 영역 메모리로 접근을 시도하면 즉시 에러가 난다. 둘 사이에 앞서 언급한 "비무장 지대"까지 존재한다. 그러나 9x 계열은 그렇지 못하다.

BYTE *pb = (BYTE *)0xC0001000;
int i;
for(i=0; i<4096; i++) {
        printf("%02X ", *pb), *pb=*pb; pb++;
}

이런 간뎅이-_-가 배 밖에 나온 코드를 실행하면 NT급에서는 당연히 즉시 Access violaton 에러가 나고 프로세스가 사살되는 반면,
9x 계열은 놀랍게도 잘 실행된다. *pb=*pb로 해 줬으니 망정이지 다 0으로 덮어쓴다거나 하면 무슨 일이 벌어질까? 9x 계열이 왜 불안정할 수밖에 없는지 답이 딱 나올 것이다.

같은 32비트 안에서 사용자:커널이 2G:2G가 아니라 사용자한테 좀더 메모리를 많이 줘서 더 대용량의 데이터를 처리할 수 있게 한 3G:1G 부팅 방식도 있긴 한다. 사실 9x 계열도 앞서 말한 구조의 차이 때문에 커널 메모리는 1G이다.
하지만 이 경우 운영체제가 관리할 수 있는 가상 메모리의 이론적 최대치가 크게 감소하고 생성 가능한 커널 오브젝트(프로세스, 스레드, 공유 메모리 등)의 수도 더 줄어든다는 것을 알아야 한다. 또한 응용 프로그램도 large-address-aware하게 빌드되었다는 별도의 플래그가 있어야 한다.

Posted by 사무엘

2010/01/11 00:43 2010/01/11 00:43
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/59

윈도우 API로 다른 프로그램을 "실행", 즉 기술적으로 말하면 프로세스를 생성할 때 쓰는 함수는 크게 다음과 같다.

WinExec, LoadModule, CreateProcess, ShellExecute

어느 것을 사용하더라도 다음과 같은 정보를 받는 란은 꼭 존재한다:
실행 파일 이름, 명령인자, 그리고 메인 윈도우를 표시할 디폴트 방식(SW_SHOW 등).

즉, 윈도우 운영체제는 GUI 기반이라는 특성상 프로그램 메인 윈도우를 기본적으로 최대화하여 실행하라, 창을 숨겨 놓고 실행하라는 식의 지시를 내릴 수 있다. 이런 정보들은 WinMain 함수의 매개변수로 고스란히 그대로 전달된다. 물론 응용 프로그램이 그걸 무시하면 어쩔 수 없지만.

앞의 W..., L... 두 함수는 매개변수가 매우 단순한 편해서 쓰기는 편하나, 16비트 API 시절의 잔재로 치부되어 유니코드 버전조차 존재하지 않으며, 사용이 비추(discourage)되고 있다.

CreateProcess가 32비트 이상급 윈도우 API에서 표준으로 통용되는 가장 원초적인 프로그램 실행 함수이다. 그 대신 받아들이는 매개변수가 무진장 많으며 쓰기가 좀 어렵다. 여기에 대해서는 뒤에서 다시 좀 다루기로 하겠다.

끝으로 ShellExecute는 그 이름이 암시하듯, 커널 계층이 아닌 쉘이라는 꽤 상위 계층에서 구현된 함수로 단순히 파일을 실행하는 게 아니라 인터넷 URL을 기본 웹 브라우저에서 열거나 텍스트 파일을 메모장에서 여는 일도 다 담당한다. 동작 자체도 "open", "print" 등 아예 명령 문자열로 지정할 수 있다. 즉, 쓰임이 훨씬 더 포괄적이다. 이 함수도 EXE를 실행할 때는, 내부적으로 어차피 CreateProcess를 응당 호출한다.

C...는 리턴값이 프로그램의 실행 성공 여부를 나타내는 BOOL 형태인 반면, 나머지 세 함수들은 값이 약간 특이하다. 32보다 큰 정수를 되돌리면 성공을 뜻하고 그렇지 않으면 실패라는 뜻이다.
왜 이렇게 되었냐 하면 이 legacy 함수들은 원래 리턴값이 "인스턴스/모듈 핸들"이었으며 32 이하의 핸들값은 에러를 나타내는 값으로 의미가 예정되었었기 때문이다. 일종의 과거 잔재이다.

오늘날 윈도우 프로그래밍에서 HINSTANCE라고 부르는 핸들은, 과거에는 프로세스 ID와 비슷한 개념이었다. 이 핸들은 자신이 실행한 파일을 식별하는 정보도 있었던지라 동일 EXE를 중복 실행한 것을 WinMain 함수와 함께 넘어온 hPrevInstance로 분간할 수 있었다. 또한 EXE를 실행하여 생긴 인스턴스 핸들과, 그 EXE 안에서 DLL를 읽어들임으로써 이를 식별하는 모듈 핸들(HMODULE)도 별개의 존재였다.

하지만 32비트로 넘어오면서 운영체제의 메모리/파일 관리 모델이 완전히 바뀌었고 오늘날은 HINSTANCE와 HMODULE의 구분이 완전히 없어졌다. 단순히 프로세스 메모리 공간에 맵핑되어 있는 파일 이미지를 가리키는 포인터일 뿐이다. 메모리 영역 overlap에 따른 재배치만 일어나지 않는다면, 해당 DLL/EXE의 preferred base가 그대로 핸들값이 되는 것이다. 인스턴스 핸들이 이렇게 특정 프로세스 안의 주소 공간을 가리키는 포인터가 되는 바람에(national), 이제 이 핸들로 여러 프로세스들을 식별(international)하는 것은 불가능해졌다.

CreateProcess는 사용자가 보내준 파일 + 명령행 사이에다 null 문자를 잠시 삽입하여 토큰화를 했다가, 함수 실행이 끝난 후 문자열을 원래대로 되돌려 준다. C 언어의 strtok 함수를 떠올리면 된다. 이런 이유로 인해 명령행을 넘겨주는 포인터 영역이 read-only const여서는 안 되며 쓰기가 가능해야 한다. (물론 윈도우 NT 계열 운영체제에서 W 버전이 아닌 A 버전을 호출하면 어차피 쓰기 가능한 메모리 버퍼로 인코딩 변환이 일어나기 때문에 read-only 메모리를 넘겨줘도 문제될 건 없다.)

프로그램을 실행할 때는 이 프로그램에다 기본으로 넘겨 줄 각종 환경 변수, 콘솔 프로그램인 경우 표준 입출력 스트림의 핸들, 디버그 실행 여부 등 갖가지 고급 정보를 넘겨줄 수 있으며,
프로그램이 실행되었을 경우 생성된 프로세스의 핸들과 ID 등도 돌려받게 된다. 가령, 이 프로그램이 실행이 완전히 끝날 때까지 내가 기다려야 할 때 이 핸들에 대해 WaitForSingleObject를 호출하고 있으면 된다는 뜻이다. 단, 이 핸들을 Close하는 것도 우리 책임이다.

불필요하게 높은 계층에 자리잡고 있는 ShellExecute 대신, 커널 계층에 있는 CreateProcess를 좀더 간편하게 활용하기 위해 본인은 이 함수를 클래스로 감싸서 쓰고 있다. OpenFileName, TaskDialogIndirect (윈도우 비스타) 같은 복잡한 대화상자 UI 함수만큼이나 CreateProcess도

- 각종 디폴트 argument나 구조체들 챙기기
- 소멸자에서는 결과물로 받은 핸들들 닫아 주기
- 커맨드 라인을 알아서 자체 버퍼에다 생성하고, 필요한 경우 매개변수 전체를 따옴표로 싸 주기
- 이 프로그램의 실행이 끝날 때까지 기다리는 멤버 함수도 추가.

같은 자질구레한 일을 클래스로 감싸 놓으니, 프로그램 실행하기가 한결 편리하다.

Posted by 사무엘

2010/01/11 00:42 2010/01/11 00:42
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/58

비행기는 후진을 못 한다..는 것을 이번에 처음 알게 됐습니다.
과거에 철도 차량의 선로 분기 방법에 대해 알게 된 것 같은 새로운 지식입니다. 열차는 분기할 방향을 스스로 전혀 선택할 수 없기 때문에, 외부에서 분기 부분의 선로를 바꿔 줘야 하지요. 조금만 생각해 보면 당연히 알 수 있는 건데, 평소 실감이 잘 안 난 것 같습니다. 비행기도 마찬가지.

헬리콥터 부류를 제외한 일반적인 항공기는 바퀴(랜딩 기어)를 이용하여 일시적으로 도로를 주행할 수 있으며, 이는 이착륙을 위해서도 당연히 꼭 필요한 기능입니다. 그런데 도로 주행이라고 해 봤자 자동차처럼 바퀴에 구동축을 연결해서 엔진 동력을 따로 전달하여 달리는 게 아닙니다. 비행기는 그런 기능에 특화될 필요가 없죠.

  (후진 주행이 전진과 조금도 차이가 없이 가장 잘 발달해 있는 교통수단은 단연 철도 차량이다. 앞뒤로만 달릴 수 있는 유일한 1차원 교통수단이라는 점을 감안하면 이는 명백한 귀결이다.)

당연한 말이지만 비행기가 도로를 주행하는 방법은 바퀴를 따로 굴리는 게 아니라, 하늘을 날 때와 동일한 추진력으로 공기를 뒤로 밀어내는 것입니다. 그 힘을 받아서 바퀴는 저절로 굴러갈 뿐이죠. 추진력을 내는 방향을 바꾸려면 변속을 하는 게 아니라 날개와 날개 아래 팬의 배치를 바꿔야 하는데, 이는 어지간한 구조상 불가능한 일입니다. 이런 이유로 인해 비행기는 스스로 후진을 할 수 없으며, 할 필요도 없습니다.

그런데, 승객을 갓 태우고 출발을 시작한 비행기는 전방이 터미널 건물을 향하고 있죠. 고속버스와 마찬가지로 터미널과 수직 배치입니다. (철도는 무조건 플랫폼과 평행. 선박은 수직, 평행을 둘 다 쓰는 듯.)
후진부터 해서 방향을 바꿔야 주행을 시작할 수 있는데 이때의 후진은 어떻게 하는 걸까요?

그때는 견인 차량(tow car)의 도움을 받아야 합니다. 수십~백수십 톤에 달하는 비행기를 끌어서 방향을 틀어 줘야 하는 이 차량의 역할도 큰 것 같습니다. 그 뒤 비행기가 잠시 대기하는 동안 견인 차량은 옆으로 물러나고, 비행기는 스스로 활주로로 이동을 시작합니다. 이를 towing에 이어 택싱(taxiing)이라고 하죠. 동력 주체가 바뀌었다는 것을 기내 승객은 물론 눈치채지 못합니다. 저도 창 밖으로 다른 비행기가 그렇게 끌려가는 것을 보고서야 이 사실을 알게 됐으니까요.

이런 식으로 비행기는 출발하기 전까지는 다른 차량의 보조를 받는 경우가 흔합니다. 엔진을 정식으로 켜기 전엔 발전차가 기내 전력을 공급해 주기도 하고 심지어 냉방차의 에어컨으로 냉방된 공기를 이런 식으로 기내에 주입하기도 합니다. 활주로라는 발사대까지 느릿느릿 가서 대기하고 있다가 마치 철도 신호등처럼 이륙해도 좋다는 신호가 떨어지면, 그때부터 비행기는 엔진 소리가 한 옥타브 올라가면서 급가속 급발진을 시작하고, 이내 공중에 뜨게 됩니다.

이럴 때면, 공중에서 좌우 상하 전후 6방향으로 마음대로 움직일 수 있고 심지어 공중 정지조차 가능한 헬리콥터가 무척 부러워 보이긴 하지만 속도가 느리고 연료 소비 효율이 너무 안 좋은 게 큰 문제이죠. 한마디로 장거리 비행 및 대량 수송에 매우 부적합. 역시 군용 작전이나 취재, 사고 구조 활동 같은 특수한 용도로나 적격인 것 같습니다.

Posted by 사무엘

2010/01/11 00:40 2010/01/11 00:40
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/57

※ 1기: 1.x 커널

아래아한글 1.x 시절의 에디팅 엔진입니다. 잘 알다시피 단순한 plain text에다가 약간의 서식만 붙은 것 같은 초보적인 형태였죠.
글씨의 크기 조절은 가로 확대/세로 확대만 되고 가변폭 글꼴은 사실상 지원되지 않았으며, 문단 여백도 그냥 칸 수로 지정하던 시절이었습니다. 표는 선그리기 기능으로 그려야 했습니다.
문서의 파일 포맷은 최소한 1.0, 1.1, 1.2 이렇게 세 방식 이상이 존재했던 것 같습니다. 아래아한글 1.5x는 1.2 방식과 문서 파일 포맷이 동일하며, Alt+V (새 이름으로 저장)를 누르면 과거 1.1 방식으로 저장도 할 수 있습니다.

※ 2기: 2.0 커널

1992년에 출시된 2.0부터 97까지 굉장히 장수하여 안정화한 한컴 2바이트 코드 기반의 에디팅 엔진입니다. 글씨 크기를 포인트로, 여백은 mm 같은 단위로 지정할 수 있게 되고 색깔도 8종류 중 하나로 지정할 수 있게 됐습니다. 가변폭 글꼴의 표현이 가능해지고 그림, 표 같은 각종 개체를 넣을 수 있게 됐습니다. 개요, 스타일 같은 개념도 생겼죠.

문서 파일 포맷은 2.0, 2.1, 3.0으로 나뉩니다. 사실 아래아한글 2.1은 기능면에서는 2.0과 그렇게 큰 차이가 없으나, 글꼴 쪽으로 굉장히 많은 변화가 생겼고 또 2.1에서 문서 압축 저장이 추가됐기 때문에 포맷이 바뀐 것으로 기억합니다. 아래아한글 2.5는 파일 포맷의 변동이 없었기 때문에 2.1과 포맷이 동일합니다.
3.0은 하이퍼텍스트라든가 자체 벡터 드로잉 기능, 그리고 윈도우 OLE 데이터 같은 것을 저장해야 하는 데다, 때마침 2.1 방식 문서 파일의 암호가 크랙되어서 큰 논란을 겪기도 했기 때문에 바뀌었지 싶습니다.

※ 3기: 21세기 커널

정말 많은 우여곡절을 겪은 워디안 때부터 지금까지 큰 변화 없이 이어지고 있는 에디팅 엔진 겸 파일 포맷입니다. 아마 아래아한글은 앞으로 이 방식에서 더 바뀔 일이 없을 것 같습니다.
문자 인코딩이 시대의 조류를 따라 드디어 유니코드로 바뀌고 글씨라든가 용지의 크기 제한이 완전히 사라졌습니다. 색깔도 RGB 어느 색으로나 줄 수 있게 되었으며, 여러 쪽에 걸치는 표처럼 MS 워드의 앞선 기능을 대폭 수용하여 2.0 시절 커널과는 비교가 되지 않는 많은 기능들이 추가됐습니다.

더구나 워디안 이후로 아래아한글은 과거에 없던 여러 기능이 추가되고 있음에도 불구하고 예전과는 달리 파일 포맷의 하위 호환성은 비교적 잘 유지되고 있는 것 역시, 처음에 파일 포맷 설계를 확장성 있게 잘 한 덕택이라고 볼 수 있습니다.
아래아한글도 이제 open xml 기반 문서 파일 포맷도 적극 도입해야 하지 않나 싶습니다만 과연 실현될지?

- MS 워드의 경우 97~2003 커널이 가장 보편적으로 널리 쓰이다가 2007에 와서는 에디팅 엔진과 파일 포맷이 또 크게 바뀌었지요. 95 그 이전 기수는 잘 모르겠네요.
개인적으로 워드보다도 엑셀에서, 편집 가능한 셀 수가 크게 증가하고 색깔 제한이 없어진 것을 매우 환영합니다.

Posted by 사무엘

2010/01/11 00:37 2010/01/11 00:37
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/56

한메 타자 교사(HTT).
정말 전설적인 타자 연습 프로그램이며, 이후에 등장한 동일 분야 프로그램들의 근간을 제공했습니다.

아래아한글 1.x와 비슷한 연배의 프로그램이죠. 90년대 초반에 개발된 도스용 응용 프로그램들이 90% 이상 볼랜드 터보 C 2.0 기반이었고 그래픽 모드 동작을 위해 BGI 라이브러리를 사용한 것과는 대조적으로 HTT는 MS C 6.0 기반입니다. (비주얼 C++ 6.0이 아님!)

  당시에 통용되던 프로그램들을 좀더 살펴보면,
페르시아의 왕자도 1, 2 모두 MS C로 개발되었고 볼랜드 계열 빌드가 아닙니다.
아래아한글은 16비트 바이너리들은 전통적으로 볼랜드 컴파일러를 써 왔지만, BGI 라이브러리 기반은 물론 아니지요.

HTT는 제가 두벌식을 쓰던 시절과 맥을 함께 했습니다. 세벌식 연습은 도스용 한컴 타자 연습으로 주로 했고 HTT를 쓰지 않았거든요. 390에서 최종으로 갈아타던 시절에는 박 정만 님이 개발한 <광타>의 도움을 받기도 했습니다. 그때가 얼마나 불모지였냐 하면 390 말고 최종 연습을 정식으로 지원하는 프로그램이 “없었습니다.” 윈도우 운영체제는 말할 것도 없고 아래아한글 97이 제공하던 최종 자판에도 오류가 있었습니다. 지금이야 워디안 때부터 최종 자판이 제대로 지원되기 시작했고, 윈도우용 한컴 타자 연습에도 최종 배열이 추가되긴 했지만, <날개셋> 타자연습이 첫 등장하던 시절엔 정말 제 프로그램의 지위가 더욱 독보적이었었습니다.

한메 타자는 일부러 이렇게 만들기라도 했는지 문장 연습하는 감이 묘하게 좀 좋지 않았습니다. 키를 계속 누르고 있으면 글자가 생기는 느낌이 더디고 좀 latency가 느껴집니다. 아마 이것 때문에 그 당시 세벌식 연습을 한메 대신 한컴으로 사용하지 않았던가 생각됩니다.

두벌식으로는 단문도 700 이상은 정말 무리였지만 지금 세벌식으로 연습해 보니 800 넘는 것도 가뿐하군요. “드는 정은 몰라도 나는 정은 안다.”라는 문장은 완전 세벌식 최적화 문장이어서 1000을 넘기기도 했습니다.

그리고 베네치아 게임을 오랜만에 해 보니,
<날개셋> 타자 게임의 혹독하기 그지없는-_- 지옥 훈련에 단련돼 있는 저한테는 정말 애들 장난도 아니었습니다. 떨어지는 속도도 느리고 단어도 훨씬 더 짧고 쉬운 것들이고..!
1단계부터 시작해 보니 2만점대의 점수로 끝탄을 깼습니다. 껑충 바이러스가 두 번이나 걸렸습니다.

8단계부터 시작하니 클리어 시 보너스가 더욱 붙어 47000점대의 점수를 획득했습니다. 물론 단 한 번도 HP를 소모한 적이 없었으므로 재건 바이러스는 아무 의미가 없었죠.

<날개셋> 타자연습의 게임은 베네치아를 전혀 어려움 없이 가뿐하게 엔딩 보는 개발자 본인도 만신창이로 간신히 다 클리어할 정도로 월등히 더 어렵게 짜여 있습니다. 옛날 버전은 지금보다도 더 어려웠어요. -_-;; 난이도와 각종 주인공 밸런스들은 거의 05~06년 이후로는 더 수정 없이 완전히 정착한 듯합니다. 지금 이 상태가 딱 적당하며, 더 어렵게도, 더 쉽게도 만들 필요 없을 것 같습니다. 지금은 타자를 치는 인구가 훨씬 더 늘었으니 국민 평균 실력도 영어 실력만큼이나 더욱 상향 평준화해 있을 거라는 점, 모아치기 같은 세벌식 고급 입력 기능을 십분 활용할 수 있다는 점을 감안하면 말이죠.

옛날에 두벌식 쓰던 시절엔 베네치아도 6~8단계 정도만 되면 글자 떨어지는 게 무서워서 차마 못 할 정도였는데 정말 격세지감입니다. 그나저나 “에이즈 바이러스 퇴치!”와 “지뢰 바이러스”는 도대체 뭘 하는 놈이고 왜 넣었는지 모르겠습니다. 전자는 아무 효과 없는 꽝인 것 같고, 후자는 글자들이 지뢰에 부딪히면 점수가 깎이는 것 정도밖에 모르겠네요.

<날개셋> 타자연습 1.x를 개발하던 초창기 시절엔 한메, 한컴, 광타는 물론이고 신의 손, 번개손, 천타를 꿈꾸며 같은 당대의 경쟁(?) 프로그램들을 많이 참고했습니다. 개인적으로는 도스용 <신의 손>이 정말 완성도가 높다고 인정하며, 그 열악한 640*480 16컬러에서 어지간한 게임을 방불케 하는 비주얼 디자인을 연출해 낸 것에 최고의 점수를 주고 싶습니다. 게임도 나름 테마를 갖춰서 무척 잘 만들었죠.

아무튼, 한메 타자 연습을 보니 이런 저런 여러 생각이 들었답니다. 그리고 세벌식 만세입니다. =_=;;;

Posted by 사무엘

2010/01/11 00:35 2010/01/11 00:35
, ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/55

한자파들의 패턴

- 한글 전용에 반대하고 학교에서 한자 교육을 더 일찍 더 많이 더 강화하는 걸 좋아한다.
- 각종 안내 표지판이나 공문서 같은 곳에서 한자를 더 많이 볼 수 있게 되는 걸 좋아한다.

- 한글 풀어쓰기를 극렬 반대하고 배척한다.
- 그들에게 한글과 한자는 수레의 양 날개이다.
- 중국· 일본의 지명/인명을 현지음으로 읽는 걸 극악으로 혐오한다. (북경 > 베이징, 모택동 > 마오 쩌둥)
- 띄어쓰기를 싫어하며 어지간한 복합 명사들은 붙이는 걸 선호한다.
- 세로쓰기에 굉장히 우호적이다.
- 중국, 일본 사람과의 필담(?)을 엄청 좋아하며 한중일 한자 일치 사업에 우호적이다.

- 영어, 알파벳 남발을 싫어한다. 거기까지는 좋은데 요즘 그렇게 돼 가는 원인이 한자를 안 가르쳤기 때문이라고 생각한다. -_-;;
- 오늘날 문화가 저질화하고 어휘력/사고력/학력 저하 따위가 한글 전용 때문이라고 생각한다. 일각에서는 심지어 좌경화까지 한글 전용 탓으로 돌린다.

- 부모님 이름을 한자로 못 쓰는 건 정말 치욕적인 불효이다.

* * * * * *
그 반면, '한글' 진영 안에서 보편적으로 통용되는 신념은..

- 한자 교육은 현행처럼 중학교부터 가르치는 거나 똑바로 잘 하면 충분하다고 여긴다.
- 한글 전용법의 '얼마 동안을' 조항마저도 이제 삭제해야 한다고 여긴다.
- 풀어쓰기는 주류가 되기는 곤란하나 특수한 분야의 연구 주제로 가치 정도는 인정한다.

- 한글 하나만으로 충분하며 한자는 말 그대로 얼마든지 우리 마음대로 처분해도 되는 낡은 유물(legacy)일 뿐이다.
- 언어에는 청각성이 배제되어서는 안 됨을 인지하며 불필요한 한자어 남발을 자제한다.
- 한자 문화권 국가라도 가능한 한 현지음 표기를 존중해야 한다고 여긴다.
- 엄밀한 맞춤법과 띄어쓰기를 추구하여 한글 자체를 '표의성'을 지닌 표음문자로 활용하려 노력한다.
- 가로쓰기, 탈네모꼴 글꼴 같은 쪽에 우호적이다.

- 한중일은 한자 안에서도 말과 글이 서로 다 달라져 있기 때문에 글자 일치 사업에 거의 의미를 두지 않는다.

Posted by 사무엘

2010/01/11 00:33 2010/01/11 00:33
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/53

우주 쓰레기

http://www.hani.co.kr/arti/science/kistiscience/336364.html
http://pc21th.egloos.com/4496840
(참고)

철도는 선로 위의 돌멩이가 치명적인 약점이고
항공기는 조류 충돌이 치명적인 약점이라면
인공 위성, 우주 왕복선 등에는 지구 표면을 뒤덮고 있는 수천, 수만 개의 우주 쓰레기들이 치명적인 위협으로 작용하고 있습니다.

5, 60년대 처음 발사되던 당시에 인공 위성은 인류에게 우주 개발 시대를 여는 신호탄이었고, 미국· 러시아 같은 강대국의 최첨단 과학 기술의 총아였습니다.
지구는 둥글기 때문에 직진하는 전파만으로는 지구 반대편으로 신호를 보낼 수 없습니다. 과거에는 고맙게도 지구 대기권의 전리층이 전파를 반사해 주었기 때문에 어느 정도 무선 통신이 가능했습니다.

하지만 오늘날처럼 정보가 폭증하고 있고 옛날보다 훨씬 더 파장이 짧은 전파도 쏘아올리는 시대에는, 지구 전리층만으로는 한계가 있고 통신 위성이 전파를 별도로 처리해 주어야 합니다. 달에는 전리층 같은 것도 없기 때문에 달 뒷면에 쏙 숨으면 지구와 교신이 그대로 끊어져 버립니다. 놀랍죠?

위성은 말 그대로 한없이 지구를 향해 떨어지고 있는 덕분에 지구상에 떠 있는 존재입니다. 통신 용도로 쓰이며 지구 자전 주기와 공전 주기가 완전히 같은 '정지 위성'은 지표면으로부터 무려 35000km에 달하는 곳에 떠 있으며, 개수도 전세계적으로 200개가 채 되지 않습니다. 이 이상은 더 띄우지 않기로 국제 협약까지 맺어져 있습니다.

하지만 이보다 더 낮은 고도, 짧게는 300~2000km 정도의 고도에서 도는 인공 위성도 굉장히 많이 존재합니다. (이 정도만으로도 이미 최소한 열권 이상이고 우주나 다름없는 영역입니다) 그리고 이 저궤도 위성이 문제입니다.

낮은 궤도를 도는 위성은 그만큼 지표면과 가깝기 때문에 통신이나 정찰 임무를 더 원활히 수행할 수 있으며 띄우는 데 드는 비용도 저렴합니다. 그렇지만 그만큼 대기와의 마찰도 고궤도보다는 커서 계속 떠 있기가 힘들며, 지구를 매우 빠르게 돌아야 합니다. 공전 횟수가 하루에 10수 회 정도는 기본인 걸로 알고 있습니다.

이런 이유로 인해 저궤도 위성은 수명이 짧습니다. 열권 정도만 돼도 위성은 잘 알다시피 태양 방면과 지구 방면의 표면 온도차는 달의 낮과 밤의 차이만큼이나 벌어집니다. 위성은 이런 환경에서도 자체적으로 열 제어를 하고, 마치 통닭구이처럼 뱅글뱅글 돌면서 온도 배분을 균형 있게 하도록 설계되지요. 지표면보다 훨씬 더 열악하고 살벌한 환경에서 동작하는 기계인 것입니다. 거기에 돌아가는 컴퓨터도 오늘날의 PC에다 견주자면 XT급이 될까말까 하지만 그걸로도 옛날에는 임무 수행 할 걸 다 한 셈입니다.

하지만 수명이 다하고 이물질 때문에, 혹은 초속 수십 km로 날면서 공기와의 마찰이 누적되어 야기된 물리적 손상 때문에, 제품에 미묘한 오동작이 발생하면.. 이런 균형이 깨지게 됩니다. 위성은 이 온도차를 견디지 못하고 단순히 고장나서 작동만 중단되는 게 아니라 배터리 같은 것이 열받아서 펑 폭발합니다.

수명이 끝난 폐 인공 위성이라든가 이런 잔해들은 땅에 잘 떨어지지도 않고 초속 수~수십 km로.. 총알보다도 더 빠른 속도로 날아다니면서 우주 교통을 방해하는 요인이 되고 있으며, 인공 위성의 추후 발사를 어렵게 만들고 있습니다. 말 그대로 우주 쓰레기들입니다. 부딪치면 꽤 많이 아플 겁니다. 이 정도면 조류 충돌쯤은 저리가라이죠?

인공 위성 잔해는 아니지만, 로켓이 발사되면서 떨어뜨린 수백 kg급의 연료 탱크가 바닷속에 처박히지도 않고 우주 쓰레기가 되어 지구 주변을 돌고 있었다는 말에도 적지 않은 충격.
인간의 손길이 닿은 곳은 땅, 물, 공기도 모자라서 우주 공간까지 자가 회수가 되지 않는 폐기물 찌꺼기들로 몸살을 앓게 되는 것 같습니다. 무슨 일을 해도 깔끔하게 하질 못하고 꼭 side effect를 남기고, 뒷수습을 스스로 못 합니다.

이런 우주 쓰레기들은 컴퓨터로 비유하자면 garbage collection 없이 memory leak가 한계에 달하고 있는 컴퓨터 메모리라든가, 수천 개의 legacy들과 DLL hell로 몸살을 앓고 있는 과거 윈도우 시스템 디렉터리를 보는 것과 같습니다.

Posted by 사무엘

2010/01/11 00:31 2010/01/11 00:31
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/52

자동차가 다니는 도로 중에는 일반 시가지의 도로와는 달리, 진출입로를 입체화하여 신호 대기를 없애고 보행자는 물론 이륜차도 접근할 수 없게 한 ‘자동차 전용’ 도로가 있다. 이런 도로는 최고 속도 제한뿐만 아니라 최저 속도 제한까지 있어 많은 자동차가 원활하게 통과하도록 하고 있다.

한편, 도시와 도시를 이으며 해당 지역이 아닌 중앙 정부에서 노선을 직접 고시하여 관리하는 도로를 ‘국도’라고 부른다. 국도는 이미 번호로 매겨져 있어서 가령 1번 국도는 서울, 안양, 평택 등 처음엔 경부선 철도와 비슷한 길을 가다가 목포로 가며, 4번 국도는 경주 감포에서 출발하여 대전까지 경부선과 비슷한 방향을 향하다가 당진에서 끝난다. 국도라는 용어에는 시설이라는 개념은 그다지 들어있지 않기 때문에, 심지어 비포장 아니면 2차선 도로일 수도 있고 최근에 리모델링된 국도 구간은 미국 프리웨이급의 8차선의 고가 도로일 수도 있다. 원래 국도의 노선은 북한 지역까지 다 포함하고 있다.

이 글에서 다루고자 하는 한국의 고속도로는 자동차 전용 도로의 성격에 가깝지만 행정상으로는 ‘고속 국도’이다. 즉 국도이지만 통행료를 받는 유료 도로이고 시설이 일반 국도보다 훨씬 더 좋다. (88올림픽 고속도로는 예외이지만.)
사실 이런 고속도로와 개념적으로 정확하게 100% 대응하는 말이 영어에는 존재하지 않는다. 미국에는 한국의 경부 고속도로급의 넓고 잘 뻗은 길이 경부-경인 축이나 수도권에만 있는 게 아니라 미국 전역에 구축되어 있다. 하지만 한국과 같은 유료 도로는 아니다.

고속도로가 많지 않던 시절에는 매 도로마다 이름이 붙어 있었지만 요즘은 고속도로가 워낙 거미줄처럼 많이 놓이고 구조가 복잡해지면서, 우리나라도 고속도로의 이름을 없애고 일반 국도처럼 번호만으로 부르려고 시도하고 있다. (한국의 고속도로로서 상징적인 의미가 매우 큰 경부 고속도로는 당당히 1번이다.)
하지만 국민 정서상 그게 금방 정착할 것 같지는 않다. 주변에는 여전히 경부, 중부내륙, 영동 같은 명칭이 친숙하다.

이 한국의 고속도로는 유료 도로이다 보니 통행료를 징수하는 톨게이트가 존재한다. 마치 지하철 역 내부가 승차권 개집표기 전후로 분리되어 있고, 공항 내부가 탑승권 소지자만 들어가는 구역으로 분리되어 있는 것처럼 고속도로 구간을 분리하는 역할을 톨게이트가 하는 셈이다. 톨게이트는 차량의 소통을 크게 방해하기 때문에 이 오버헤드를 줄이고자 요즘은 하이패스 같은 기술이 등장하기도 했다.

톨게이트는 고속도로가 시작하는 양 종점에 있고 또 각 지역 인터체인지 말단에도 있다. 그래서 자동차는 톨게이트를 통과하여 고속도로에 진입한 후 톨게이트를 통과하여 고속도로에서 벗어나게 된다. 여기까지는 이해하는 데 아무 어려움이 없을 것이다.

그런데 경인이나 외곽 순환 같은 수도권 고속도로에서는 얘기가 좀 달라진다. 여기서는 단순히 장거리 여행이 아니라 매일 출퇴근을 고속도로로 하는 사람도 굉장히 많다. 진출입로인 인터체인지도 훨씬 더 조밀하게 많이 있다. 마치 일반 철도역 간격으로 있던 역이 (광역)전철역 간격으로 바뀌는 것과 정확히 같다. 여기에 일일이 다 톨게이트를 설치하고 수많은 차들을 세우는 것은 현실적으로 무리이다.

그렇기 때문에 이 두 고속도로는 다른 방법으로 통행료를 징수하고 있다.
일단 고속도로에 진입 자체는 톨게이트 없이 마음대로 한다. 하지만 도로 중간중간에 톨게이트가 있다. 외곽 순환의 경우 전구간을 통틀어 6개의 톨게이트가 있으며 경인 고속도로는 도로 중앙에 톨게이트가 하나 있다. 물론 통행료도 일반적인 거리 비례제가 아니라 고정된 요금을 매우 조금만 징수한다. 또한 톨게이트를 통과하지 않는 구간만 이용할 때는 통행료를 낼 필요가 없다.

따라서 경기도 남부에서 수평축의 외곽 순환 고속도로와 만나는 수직축의 서해안/경부/중부 고속도로들은, 외곽 순환 고속도로와 만나기 전에 이미 전통적인 방식의 요금 정산과 징수를 끝내야 한다. 그래서 제각기 서서울/서울/동서울 톨게이트는 안산, 성남 같은 꽤 남쪽에 자리잡고 있다.

철도뿐만 아니라 도로도 수도권과 비수도권이 상이한 교통 수요에 따른 상이한 운영 방식을 유지하고 있다는 것을 알 수 있다.

참고로, 철도는 서울을 기점으로 보지만 도로는 남북 통일과 대륙 진출을 염두에 두고 남쪽을 기점으로 보고 있다는 것이 흥미로울 것이다. 즉 경부 고속도로의 기점을 서울이 아닌 부산으로 본다는 것이다.

Posted by 사무엘

2010/01/11 00:28 2010/01/11 00:28
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/51

class CAppFrame: public CWnd {
public:
        void PostNcDestroy() { delete this; }
};

class CMyApp: public CWinApp {
public:
        BOOL InitInstance();
};

CMyApp g_App;

BOOL CMyApp::InitInstance()
{
        m_pMainWnd=new CAppFrame;
        m_pMainWnd->CreateEx(0, AfxRegisterWndClass(0), _T("Hello World"), WS_OVERLAPPEDWINDOW,
                100, 100, 500, 500, NULL, NULL);
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
        return TRUE;
}

위의 코드는 MFC를 써서 만들 수 있는 가장 간단한 GUI 프로그램이다. 빈 창만 달랑 뜨는 게 허전하면, message map 넣고 OnPaint에다가 Hello, world! 출력하는 코드만 추가해 주면 된다.
MFC로 창을 띄우기 위해서는 본질적인 것 딱 두 가지만 기억하면 된다.

첫째, CWnd에서 상속 받은 클래스를 만들기

둘째, CWinApp에서 상속 하나 받아서 전역 개체를 하나 반드시 만들고, InitInstance를 오버라이드하여 내 윈도우 클래스를 생성하는 코드를 짜 주기

물론 요즘은 닷넷 프레임워크 같은 더 객체 지향적이고 깔끔한 API도 나와는 있지만 저 정도만 해도 그냥 C언어 + Win32 API만 썼을 때와는 비교할 수도 없이 간단하게 내가 원하는 일을 곧장 시작할 수 있다. 윈도우 클래스 등록, 윈도우 프로시저 등 온갖 지저분한 내부 처리를 상당 부분 MFC가 알아서 해 주기 때문이다.

MFC의 핵심부이며 가장 자주 다루게 되는 부분은 역시 윈도우를 나타내는 CWnd 관련 개체이다. 응용 프로그램의 메인 윈도우부터 시작해서 대화상자와 대화상자 안의 자그마한 컨트롤까지 매우 다양한 용도로 쓰이는 HWND를 한 뿌리 클래스와 상속 클래스만으로 원활히 제어하기 위해 MFC는 굉장히 심도 있게 설계되었으며 내부적으로 자질구레한 일들을 매우 많이 해 주고 있다. 단순히 ShowWindow(hWnd, SW_SHOW)를 wnd.ShowWindow(SW_SHOW)로 바꿔 주는 것을 훨씬 넘어서는 수준이다.

더구나 메시지 맵을 통해 컨트롤 서브클래싱(기존 윈도우 컨트롤의 동작을 부분적으로 조작하는 것)까지 매끄럽게 연결시킨 것까지 보면, 솔직히 굉장히 잘 만든 프레임워크임을 인정하지 않을 수 없다.

이런 프레임워크를 만들 때 근본적으로 문제가 되는 것은 CWnd라는 C++ 오브젝트와 운영체제의 HWND 사이의 씽크를 맞춰 주는 작업이다. 둘은 원래 개념적으로 생성 주기나 scope이 서로 완전히 다른 존재이다. 하지만 MFC는 한 HWND를 가리키는 CWnd 오브젝트가 중첩되지 않도록 배려하고 있으며, 나의 C++ 코드에 의해 생성되지 않은 외부 HWND에 대해서도 임시 맵까지 만들어 가면서 CWnd를 동기화해 주고 있다. 멀티스레드 환경까지 감안하면 이는 더욱 복잡한 작업이 된다.

new 연산자로 CWnd가 생성될 때 CreateWindow를 같이 해 주고, HWND가 완전히 소멸되어 WM_NCDESTROY가 왔을 때 CWnd까지 delete로 지워 주는 것은 대부분의 경우엔 바람직한 디자인 패턴이나, 이것이 언제나 유용한 것은 아니다. 가령 modal 대화상자는 자체적으로 message loop까지 갖추고 있기 때문에 heap이 아닌 스택에다가 간단히 지역변수로 선언하는 경우가 더 유용하기 때문이다. 더구나 대화상자는 사용자가 대화상자를 닫았더라도, 이 C++ 클래스 갖고 있는 데이터 변수들을 후에 활용하는 경우가 많기 때문에 HWND 개체가 사라진 뒤라도 C++ 개체는 남아 있어 줘야 한다.

이래저래 CWnd와 HWND 사이의 관계와 생성/소멸 주기는 여러 모로 이해하기 까다롭다. CWnd 클래스 중에서 new로 생성되고 HWND의 소멸과 동시에 소멸되어야 하는 오브젝트라면, PostNcDestroy 함수를 오버라이드하여 delete this를 넣어 주어야 메모리 누수가 발생하지 않는다. 응용 프로그램의 주 프레임 윈도우라든가 modeless 대화상자가 이런 예에 속한다.

저 소스 코드에서는 CWnd를 날것으로 사용했지만, CWnd에서 파생되어 아예 전문적으로 응용 프로그램의 주 프레임 윈도우를 담당하고 있는 MFC 클래스인 CFrameWnd는 PostNcDestroy가 이미 저렇게 구현되어 있다. 그뿐만 아니라 이 클래스는 LoadFrame 함수에서 이미 윈도우 클래스의 등록까지 다 알아서 해 주기 때문에 저 소스 코드에서처럼 AfxRegisterWndClass를 번거롭게 호출할 필요도 없다. 사용자가 준 ID와 일치하는 응용 프로그램 타이틀, 아이콘, 심지어 단축키 액셀러레이터 테이블 따위를 모두 엮어서 윈도우의 기반을 자동으로 구성해 주기 때문이다.

MFC를 써서 아주 간단한 프로그램을 짜고 싶은데 비주얼 C++의 MFC 마법사가 기본으로 생성해 주는 코드는 군더더기가 너무 많다. 그래서 이럴 때 본인은 MFC 없이 일반 Win32 응용 프로그램으로 프로젝트를 시작한 후, 저 코드 템플릿을 갖다 붙이고 프로젝트 세팅을 “MFC 사용”으로 수동으로 바꾸는 방법을 쓴다.

필요한 건 MFC가 잘 캡슐화해 준 message loop, 몇몇 GDI 오브젝트 같은 것밖에 없는데 이것만 쓰기에는 MFC는 덩치가 너무 커지고 static link를 하기에도 오버헤드가 너무 큰 것도 불만이다. 차라리 known DLL만 쓰기 때문에 매우 가벼운 바이너리를 만들 수 있는 비주얼 C++ 6.0이 그리울 때도 있다. 어차피 이후 버전에서 추가된 기능은 거의 안 쓰기 때문에.

<날개셋> 타자연습은 소스를 보면 알겠지만 딱 MFC를 써서 개발되었다. 하지만 한글 입력기는 3.0부터 MFC를 쓰지 않으며, 믿거나 말거나 MFC를 어설프게 흉내 내어 본인이 내부적으로 자체 개발한 프레임워크 라이브러리를 static link하여 개발해 오고 있다. 하지만 자체 라이브러리는 오버헤드 줄이고 최대한 가볍게 만드느라, Win32 API라든가 각종 핸들을 캡슐화한 수준이 MFC 수준으로 범용적이고 체계적이고 편하지는 못하기 때문에, 여전히 MFC가 그리울 때가 있다. ^^;;

Posted by 사무엘

2010/01/11 00:27 2010/01/11 00:27
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/50

베지어 곡선으로 표현한 원

사용자 삽입 이미지
밝은 초록색 선은 정석적인 원그리기 알고리즘으로 그린 진짜 원.
파란색 선은 제어점이 2개인 3차 베지어 곡선 하나로 사분원을 흉내낸 것,
그리고 빨간색 선은 제어점이 하나인 2차 베지어 곡선 두 개로 사분원을 흉내낸 것입니다.

베지어 곡선으로 원을 수학적으로 100% 정확하게 기술할 수는 없습니다.
단지 제어점을 잘 배치해서 원과 굉장히 비슷하게 생긴 곡선만을 그릴 수 있을 뿐입니다.

그래도 곡선이 그려진 곳에 초록색 점을 거의 찾을 수 없는 걸 알 수 있는데요, 3차 베지어 곡선(파란)만 해도 원하고 실용적으로 아무 차이가 없을 정도로 잘 근사해 냅니다.

빨간 선인 2차 베지어 곡선도 파란 선(≒ 원)과 상당히 일치하긴 하지만 그래도 파란 선이 초록 선과 일치하는 것만치 일치하지는 못합니다. 미묘하게 서로 살짝 어긋나는 오차가 보이죠?
(2차 곡선 여러 개를 모아도 3차 곡선을 근사만 할 수 있을 뿐 정확하게 일치시킬 수는 없습니다.)

컴퓨터의 벡터 드로잉에서 쓰이는 곡선들은 다 베지어 곡선(또는 이와 수학적으로 동일한 형태로 변형할 수 있는 다른 스플라인)입니다.
특히 트루타입 폰트가 쓰는 곡선은 2차 베지어 곡선이기 때문에 이렇게 빨간 선을 표현하는 방식과 동일한 방식으로 O, 이응, ● 같은 글자가 표현된다고 생각하시면 정확합니다.

Posted by 사무엘

2010/01/11 00:20 2010/01/11 00:20
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/49

« Previous : 1 : ... 147 : 148 : 149 : 150 : 151 : 152 : 153 : 154 : 155 : ... 156 : Next »

블로그 이미지

철도를 명절 때에나 떠오르는 4대 교통수단 중 하나로만 아는 것은, 예수님을 사대성인· 성인군자 중 하나로만 아는 것과 같다.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2019/10   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

Site Stats

Total hits:
1265263
Today:
431
Yesterday:
469