« Previous : 1 : ... 119 : 120 : 121 : 122 : 123 : 124 : 125 : 126 : 127 : ... 221 : Next »

* 서로 관계가 없는 여러 글들이긴 한데, 따로 따로 올리기는 좀 짧고 정보량이 적은 편이고, 귀찮은 구석이 있기도 해서 한데 묶었다.

1. 이미 실행돼 있는 프로그램을 스스로 종료한 뒤에 제거하기

본인은 설치· 배포 패키지를 만들 때 Visual Studio가 기본 제공하는 설치/배포 패키지를 사용하고 있다.
얘는 마소에서 직접 제공하는 물건이다 보니 정말 기본적인 퀄리티는 보장되고 기능이 나쁘지는 않다. 하지만 버그나 불편한 점이 아주 없는 건 아니고, 또 동작 customize의 폭이 충분하지 못해서 불편한 구석도 많다. Windows Installer라는 API가 제공하는 기능의 극히 일부만을 템플릿화해서 제공하는 형태이기 때문이다.

잘 알다시피 Windows는 실행 중인 EXE나 DLL은 이름을 바꿀 수는 있어도 지울 수가 없어서 뒤끝 없이 깔끔하게 제거하는 게 어려운 구석이 있다. 프로그램이 한번 실행했다가 간단히 종료가 가능한 EXE가 아니라 <날개셋> 한글 입력기처럼 IME가 포함돼 있다거나, 혹은 서비스/데몬류라면 참 난감하다.

EXE라면 자신을 종료하는 명령을 갖추고 있어야 한다. 즉 A라는 프로세스가 이미 돌아가고 있는데, /U나 /Q 같은 옵션으로 A가 다시 실행됐다면 그 A의 인스턴스는 이미 실행돼 있는 다른 A의 인스턴스를 찾아서 거기에다가 이벤트로든 윈도우 메시지로든 종료 명령을 내린 뒤 종료한다. 그럼 이미 실행돼 있는 A는 그 신호를 받고서 자신도 곧장 종료한다. 물론 A라는 한 프로그램의 소스에는 자기가 각각 다른 상황으로 실행되었을 때의 분기 처리가 모두 갖춰져 있어야 한다.

윈도우라면 WM_CLOSE 메시지가 있고 콘솔 프로그램에는 Ctrl+C 인터럽트가 있는데, 콘솔도 아니고 윈도우도 안 만든 채 다른 이벤트를 대기만 하고 있는 프로그램을 상대로 범용적인 종료 신호를 보내는 방법이 있는지 모르겠다. TerminateProcess라는 아주 무식하고 극단적인 방법을 쓰기보다는 그 프로그램이 직접 자신을 종료하도록 유도하는 게 바람직하기 때문이다.

인간 세계에서도 마찬가지다. 말이 안 통하는 미치광이가 만취한 상태로 자동차 운전대나 총칼 같은 위험한 물건을 잡고서 인질극 벌이고 행패를 저지르는 상황이 아닌 이상, 마취총을 쏘거나 머리를 벽돌로 내리쳐서 기절-_-시키거나 최악의 경우 저격을 하는 것보다는 곱게 말로 행동을 저지시키는 게 나은 것이다.
회사에서 필요 없는 사람을 짜를 때도 지방 한직 발령에다 빈 책상만 달랑 세팅해 놓고 아무 업무도 안 주면 그 사람이 더는 못 견디고 알아서 사표 쓰고 나가게 된다. 어지간해서는 대놓고 "너 해고. 내일부터 나오지 마" 이러는 일은 극히 드물다. 그건 고용주의 입장에서도 부담스러운 일이기 때문이다.

갑자기 쓸데없는 얘기가 좀 길어졌다만..
회사 업무 때문에 저런 성격의 EXE를 만들 일이 있었다.
DLL이라면 DllUnregisterServer이라고 원래는 COM용이지만 굳이 그 용도로만 쓰지는 않아도 되는 표준 인터페이스가 존재하지만, 얘는 EXE이다 보니 자신을 종료하여 제거 준비를 완료시키는 옵션을 구현했다. 그리고 패키지가 제공되기 전에는 당연히 그 옵션이 실행되게 이벤트도 넣어 줬다.

그러나 그럼에도 불구하고 이 프로그램을 설치하고 실행한 뒤에 제거를 하자, MSI는 "요런 프로그램이 실행 중이어서 제거를 제대로 할 수 없습니다" 대화상자를 띄우며 꼬장을 부렸다. 헐...;;
거기서 '무시'를 누르면 되긴 됐다. 그러면 종료/제거 스크립트가 실행돼서 "안 돼"가 "돼"로 바뀌었다. 실행 중인 자기 자신을 제거하는 테크닉이야 배치 파일을 이용해서 그리 어렵지 않게 구현 가능하기도 하고.

하지만 저런 대화상자가 뜨는 일은 반드시 막아야 했다. 저건 사용자가 부주의하게 띄워 놓은 게 아니라 우리 소프트웨어 제품이 정상적으로 일부러 띄워 놓은 프로그램이기 때문이다.
먼저 종료/제거 스크립트를 실행부터 좀 하고 나서 아직도 프로그램이 실행되고 있는 게 있으면 그걸 지적하면 되는데 저거 순서만 좀 바꿀 수가 없는지, Visual Studio에는 그런 기능이 없나 하는 아쉬움이 들었다. 얘로는 그럼 서비스 같은 건 제대로 배포하고 제거할 수가 없는 건지?

결국은 어떻게 했는가 하면 자기 자신을 다른 이름으로 복사해서 그놈을 대신 상주시키는 방법으로 문제를 피해 갔다. 그러면 MSI가 실행되어 있는 시점에서 자신이 제거해야 하는 프로그램은 실행돼 있지 않고, 새로 실행되는 동일체 프로그램이 자기 분신을 종료시켜 주기 때문에 모든 요구 사항을 만족할 수 있다. 하지만 굳이 안 해도 되는 삽질이 필요해졌다는 점에서는 여전히 아쉬움이 남는다.

2. 운영체제의 GUI 기본 글꼴 얻기

Windows에서 GUI의 기본 글꼴은 영문판 기준으로 System (불변폭) → System (가변폭) → MS Sans Serif → Tahoma → Segoe UI의 순으로 바뀌어 왔다. 한글 쪽은 명조 내지 바탕체가 들러리로 꼈다가 95/NT 시절부터 MS Sans Serif 대신 굴림으로 10년 가까이 장수한 뒤, 지금은 맑은 고딕이 대세가 됐다.
맑은 고딕과 Segoe UI의 경우 같은 서체이지만 윈도 비스타/7 시절과 8 이후 시절에 글자 모양이 미세하게 바뀌기도 한 것은 눈썰미 있는 분이라면 아실 것이다.

테마가 고전에서 Aero로 바뀌는 과도기를 거친 뒤, Windows 8부터는 자체 테마가 Aero시절에 비해 곡선 테두리나 그러데이션 같은 게 없어지고 굉장히 단촐해진 대신, 이 테마가 과거의 고전 테마를 완전히 대체하게 됐다. 자연히 UI 글꼴도 굴림이 밀려나고 맑은 고딕이 대세가 됐다.

그런데, 운영체제의 언어나 버전에 관계 없이 지금 시스템에 기본으로 지정돼 있는 글꼴을 얻어 오는 방법은 없을까? 이런 건 LOGFONT 값을 얻어 오거나 아예 바로 사용 가능한 stock HFONT 형태로라도 존재해야 하지 않을까? 시스템 색상에 대해서는 solid color 브러시를 얻어 오는 GetSysColorBrush 함수가 있는데 말이다.

실제로 요즘 프로그램 중에는 시스템의 기본 GUI 글꼴에 맞춰서 대화상자를 출력하는 것들도 많다. 비록 그렇게 동작하는 게 필수 관행은 아니지만 말이다. Visual Studio가 대표적인 예이고 <날개셋> 한글 입력기 프로그램들의 대화상자도 마찬가지. 기본 글꼴을 얻어 올 수 있어야 이렇게 동작을 할 수 있을 것이다.

Windows에는 이와 관련된 API가 물론 있긴 하지만 내력이 좀 꼬여 있다.
GetStockObject 함수를 보면 기본 펜이나 브러시 말고 글꼴을 되돌리는 아이템이 있다. 그러나 SYSTEM_FONT, SYSTEM_FIXED_FONT 이런 것들은 트루타입 글꼴과는 하등 관계가 없으며 말 그대로 System, FixedSys, MS Sans Serif, Terminal 같은 25년이 넘는 짬밥을 자랑하는 골동품 구닥다리 고정 봉인 비트맵 글꼴밖에 나오지 않는다.

그나마 유일하게 Windows 95/NT4에서 트루타입 글꼴을 되돌리는 stock 아이템이 딱 하나 추가되긴 했는데 그건 바로 DEFAULT_GUI_FONT이다. 얘는 한글판에서는 굴림 9포인트에, 그리고 아마 영문판에서는 Tahoma 정도에 매핑된다.
그럼 얘를 쓰면 되느냐 하면 그렇지는 않다. 얘는 좀 만들다가 만 물건-_-처럼 됐다. Windows 95 이래로 8에 이르기까지 그냥 굴림으로 고정돼 버렸다. Aero 테마라고 해서 맑은 고딕이 돌아오는 게 아니다.

실질적으로 현업에서 지금 운영체제의 기본 글꼴을 얻어 오는 방법은 SystemParametersInfo 함수를 쓰는 것이다. 아이템 인덱스로 SPI_GETICONTITLELOGFONT를 주면 기본 글꼴의 명세가 LOGFONT 형태로 돌아온다. 이를 토대로 HFONT는 우리가 수동으로 만들어서 사용하고, 다 쓴 뒤엔 해제를 해야 한다. 물론 대화상자의 글꼴을 바꾸는 건 GDI 개체를 만드는 게 아니라 대화상자 템플릿의 내용을 바꾸는 것이므로 방법이 약간 다르다.

3. 64비트 바이너리의 디렉터리 배치에 대한 생각

Windows는 잘 알다시피 Program Files 디렉터리가 32비트용과 64비트용이 나뉘어 있다. SHGetFolderPath 함수는 기본적으로 호출하는 프로그램의 비트수에 해당하는 디렉터리를 되돌리며, 이로써 32비트 프로그램 바이너리(EXE/DLL)와 64비트 프로그램 바이너리가 서로 자연스럽게 분리되어 따로 놀게 해 놓았다.

하지만 응용 프로그램의 바이너리 구분이 그렇게 마냥 깔끔하게만 되지는 않는 경우도 많다.
32비트와 64비트용 Program Files 디렉터리 구분은 편의상 존재하는 구분일 뿐이다. 32비트 디렉터리 아래에 64비트 프로그램이 있다거나 혹은 그 반대의 상황이 됐을 때 그 프로그램의 실행이 구조적으로 거부된다거나 하지는 않는다. 그러니 너무 강박관념적으로 구분하려고 애쓰지는 않아도 된다.

가령, 프로그램 자체는 전반적으로 32비트이지만 탐색기 셸 extension이나 시스템 훅 같은 일부 프로그램만 64비트인 경우..
그냥 Program Files (x86) 밑의 동일한 프로그램 디렉터리에다가 64비트 DLL도 이름을 달리해서 집어넣는다 해도 이상할 것 없다. 한두 개보다는 파일 개수가 많다면, 그 아래에다 x64 같은 별도의 디렉터리를 만들어서 말이다.

Visual Studio도 컴파일러는 32비트용 32비트 타겟뿐만 아니라 32비트용 64비트 크로스 컴파일, 그리고 64비트용 64비트 타겟 같은 컴파일러들이 모두 Program Files (x86) 아래에 있으며, Spy++ 같은 유틸도 32비트와 64비트 프로그램이 EXE와 훅 DLL 모두 한 디렉터리에 있다.
32비트 devenv.exe IDE에서 64비트 프로그램을 디버깅 하기 위해 중재 역할을 하는 64비트 원격 디버깅 서버 프로그램은 그 아래의 x64 디렉터리 안에 들어 있다. 오로지 걔들만을 위해 굳이 64비트 Program Files 디렉터리를 또 건드리지는 않았다.

그 반면, 64비트 바이너리가 전체 제품의 일부 형태로 있는 게 아니라 32비트와 완전히 대등하게 있는 경우라면 그때는 32/64비트 프로그램 디렉터리 아래에 대등한 파일과 디렉터리 구조를 갖추고 있는 게 바람직하다.
그리고 프로그램의 비트 수와 관계 없이 공유하는 데이터는 ProgramData라는 또 다른 공용 디렉터리의 아래에다 두면 된다.

<날개셋> 한글 입력기는 64비트 에디션이 처음으로 만들어지던 4.8 시절에 저런 식으로 디렉터리 구조를 싹 바꿨다. 아무래도 외부 모듈이 있다 보니 32비트와 64비트 바이너리는 애초에 대등한 구조가 되어야만 했으며, 그래서 32/64비트 프로그램 디렉터리를 모두 적절히 사용하게 만들어졌다. 프로그램마다 이런 차이가 있다는 걸 생각하면 되겠다.
하긴, 요즘은 관리자 권한을 요구하지 않고 간편하다고 해서 Program Files가 아니라 아예 사용자 계정 디렉터리에다가 프로그램을 설치하는 경우도 있으니 이건 32/64비트 구분이 더욱 모호해진 경우에 속한다.

4. 비주얼 C++ 솔루션의 중복 로딩 감지

Visual C++ IDE는 잘 알다시피 솔루션 단위로 동작한다. 한 솔루션 안에는 여러 관련 프로젝트들이 있을 수 있다. 솔루션은 프로젝트들의 묶음 컬렉션일 뿐이기 때문에 프로젝트를 바로 열면 그 프로젝트를 감싸는 껍데기 솔루션이 자동으로 만들어지기도 한다.
다만 다수의 솔루션들을 동시에 여는 것은 IDE의 능력 범위를 벗어나는 일이다. 그러니 IDE를 여러 개 실행해서 제각각 다른 솔루션을 열어야 한다.

그런데 비주얼 C++을 여러 개(=여러 인스턴스) 띄워서 여러 솔루션을 열어 놓고 작업을 하다 보면, 한 인스턴스에서 이미 열어 놓은 솔루션을 깜빡 잊고 다른 인스턴스에서 또 여는 일이 생기곤 한다. 뭐 그런다고 해서 프로그램이 뻑나거나 데이터가 날아가는 급의 큰 사고가 벌어지는 건 아니지만, 그래도 약간 불편한 일이 벌어진다.

인텔리센스 DB 파일에 공유 충돌이 발생하기 때문이다. 소스 코드의 상태와 인텔리센스 DB 상태를 언제나 동기화시키기 위해 IDE가 해당 파일을 열어 놓은 채 읽고 쓰는 동작을 완전히 독점하는 듯하다. 그래서 솔루션의 복수 중복 로딩을 시도하면, 되긴 하지만 나중에 연 쪽에서는 Class view라든가 인텔리센스가 동작하지 않는다.
이것은 과거 ncb 기반의 비주얼 C++ 200x 시절이든 지금의 201x 시절이든 동작이 동일하다. 다만 201x부터는 파일 쓰기가 가능한 임시 fallback 경로를 지정해서 문제를 좀 더 지능적으로 회피할 뿐이다.

하지만 에러 메시지를 출력하거나 대체 경로를 지정할 필요 없이,
비주얼 C++의 다른 인스턴스에서 해당 솔루션이 열려 있을 경우, 그 인스턴스로 이동만 시켜 주는 게 훨씬 더 월등히 나은 해결책이다. 그게 99.99% 사용자가 원하는 반응이 아닐까? "아, 이미 이 솔루션을 열어 놨었지!"
도대체 동일 솔루션을 중복 로딩해야 할 이유나 필요가 실무에서 무엇이 있겠으며, 이 상황에서 DB 파일을 건드리고 있을 프로그램은 비주얼 C++ IDE의 다른 인스턴스 말고는 다른 선택의 여지가 무엇이 있겠는가? 비주얼 C++의 inter-process 차원에서의 배려가 아쉬운 대목이다.

대체 경로를 지정해 주는 건 CD-ROM 같은 읽기 전용 매체에 저장된 솔루션을 열었을 때에나 유의미한 편의를 제공할 것으로 여겨진다.

5. 하이퍼-V

하이퍼-V인지, CPU 가상화인지 뭔지 잘은 모르겠지만 예전에 Windows Phone 플랫폼 개발을 위해서는 Hyper-V platform이라고 명명된 기능을 모두 켜야 했다.
그런데 VirtualBox가 멀쩡한 64비트 호스트 OS에서도 64비트 게스트 가상 머신을 만들지를 못하고 꼬장을 부리고 있어서 검색을 해 보니.. 이번엔 반대로 Hyper-V platform을 꺼야 했다.

Windows Phone 에뮬레이터도 일종의 가상 머신을 돌리는 것이고 64비트 OS에서만 돌아가는 기능이었는데 Hyper-V에 대해서 도대체 왜 이런 차이가 존재하는지를 잘 모르겠다.
그리고 VirtualBox는 64비트 호스트에서 64비트 게스트를 어떤 이유로든 만들 수 없다면, 그렇게 아무 말도 없이 슬쩍 감추기만 하지 말고 "64비트 게스트를 만들려면 Hyper-V를 꺼 주세요"라고 친절하게 메시지라도 좀 출력해 주지 하는 생각이 들었다.

Posted by 사무엘

2015/07/26 08:32 2015/07/26 08:32
, ,
Response
No Trackback , 3 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1120

Windows 운영체제에서 GUI의 핵심 구성 요소인 윈도우라는 물건은 자신만의 위치, 스타일, 소속 클래스, 부모 윈도우, ID(또는 메뉴 핸들) 등 여러가지 공통 정보를 갖는다. 이들은 숫자 형태로 표현되며, 대부분 GetWindowLongPtr 함수를 이용해 값을 얻을 수 있다.

그런데 그 공통 정보 중에는 숫자뿐만 아니라 문자열인 것도 있으니, 바로 '텍스트'이다. static 컨트롤이나 버튼들이 출력하고 있는 문장이나 단어들이 바로 자신이 갖고 있는 텍스트이다. 그리고 작업 표시줄에 걸려 있는 응용 프로그램들의 제목(Caption)도 다 윈도우의 내부 텍스트이다.

윈도우에 소속된 텍스트를 읽고 쓰는 함수는 잘 알다시피 Get/SetWindowText이다. 그러나 이것의 실제 구현은 그저 C++ 클래스에서

String getText() const { return m_strText; }
void setText(String t) { m_strText=t; }

요렇게 달랑 코딩하는 것만치 단순하지 않으며, 그보다 추상화 계층이 많고 사연이 훨씬 더 복잡하다.

(1) 먼저, 윈도우는 단순히 자신의 내부 버퍼를 토대로 텍스트를 지정하거나 되돌릴지, 아니면 이런 기본 동작을 무시하고 매번 자신이 능동적으로 반응을 할지를 자기 윈도우 프로시저가 재량껏 결정할 수 있다. 이것은 마치 WM_PAINT 메시지를 이미 저장돼 있는 버퍼를 바로 뿌리는 것으로 처리하는지, 아니면 매번 그래픽 API로 그려서 처리하는지의 차이와 같다.

아까도 얘기했던 static이나 버튼 컨트롤을 포함해 대부분의 윈도우들은 기본 내부 버퍼를 기반으로 동작하는 것만으로도 충분할 것이다. 그러나 에디트 컨트롤은 get의 경우 사용자가 입력한 문자열을 되돌리며 set은 자기가 편집하고 있는 텍스트를 변경한다. 이 텍스트는 당연히 기본 내부 버퍼가 아니라 에디트 컨트롤이 자체적으로 관리하는 자료 구조로부터 얻어진 데이터이다.

그럼 그런 customize를 어떻게 하는가? Get/SetWindowText는 대상 윈도우에다가 WM_GETTEXT, WM_GETTEXTLEN, WM_SETTEXT 메시지를 보내어 그 응답을 받는 방식으로 구현된다. 윈도우가 이 메시지를 처리하지 않고 그냥 DefWindowProc으로 넘기면 내부 버퍼에 대한 문자열 get/set인 기본 기능이 구현된다. 이 메시지는 자기가 에디트 컨트롤을 직접 구현하고 있을 때 정도에나 직접 처리하면 된다.

WM_CREATE에서 넘어온 CREATESTRUCT 구조체를 들여다보면, 이 윈도우를 생성한 CreateWindowEx에서 지정해 준 window name 정보가 있는데, 이것부터 자기 자료 구조에다가 복사를 해 둬야 할 것이다.
만약 내 윈도우가 대용량 텍스트를 다루고 텍스트의 일부 구간이 빈번하게 수정된다면, 저런 원시적인 메시지에만 의존하지 말고 해당 동작만을 위한 custom 메시지를 직접 구현해서 그걸 이용하는 게 효율적이다.

(2) 서로 다른 응용 프로그램끼리는 너무 당연한 말이지만 포인터를 주고받을 수 없다. 서로 메모리 주소 체계가 완전히 다르며, 상대방 프로세스의 메모리 내부를 들여다볼 수 없기 때문이다. 그렇기 때문에 이런 프로그램들끼리 가변 길이의 임의의 데이터를 주고 받으려면 WM_COPYDATA라는 특수한 메시지를 써야 하는데, 이건 의외로 굉장히 유용하고 괜찮은 물건이긴 하다.

그런데 WM_GET/SETTEXT 메시지도 비슷한 구석이 있다. 서로 다른 응용 프로그램간에도 마치 동일 프로그램인 것처럼 텍스트를 얻어 오거나 지정할 수 있다. 이 메시지에 대해서도 운영체제가 예외적인 변환 처리를 해 주기 때문이다.
단, 여기에서는 Get/SetWindowText 함수는 동작에서 약간 차이를 보인다. 같은 프로세스끼리 get/set을 하는 것은 메시지를 날리는 것과 동일하게 동작하는 반면, 다른 프로세스에 있는 윈도우에다가 get/set을 하면.. 그 윈도우의 윈도우 프로시저를 실행하는 게 아니라 그냥 그 윈도우에 있는 내장 버퍼의 문자열만 가져오는 걸로 끝난다. 왜 그렇게 된 걸까?

이것은 보안을 위해서이다. 해당 윈도우를 관할하는 응용 프로그램이 현재 메시지에 반응하지 않고 뻗어 있는데(hang) 이때 또 텍스트를 얻거나 지정하는 메시지를 보내면.. 그 요청을 한 우리 응용 프로그램까지 응답을 기다리느라 뻗어 버릴 수 있기 때문이다. 그래서 이때는 언제나 실행이 정상적으로 즉시 끝나는 게 보장되는 윈도우 내부 버퍼만을 건드리는 걸로 끝난다.

단순 내부 텍스트가 아니라 위험을 감수하고라도 해당 프로그램의 윈도우 프로시저가 실시간으로 실행한 텍스트를 얻고 싶으면, 함수만 달랑 호출하지 말고 직접 WM_GETTEXT 메시지를 보내라는 것이 설계 의도이다. 뻗을 걱정을 최소화하면서 메시지를 보내는 함수로는 SendMessageCallback이라든가 SendMessageTimeout 같은 물건들도 있으니 말이다.

사실, 현재 시스템에 떠 있는 모든 윈도우들을 조회하는 Spy++ 같은 급의 특수한 프로그램을 만드는 게 아닌 이상, 다른 프로그램들에서 제일 겉의 프레임 윈도우도 아니고 내부의 에디트 컨트롤까지 시시콜콜하게 내용을 다 들여다봐야 할 일은 거의 없을 것이다. 그러니 16비트 API에서 최초로 32비트 멀티스레드 환경으로 넘어갈 때, 텍스트를 얻는 동작은 함수 호출에 대해서만 저런 조치를 취하는 것이 적절한 조치라고 마소의 엔지니어들이 판단했다.

(3) 프로세스 장벽에 비해서는 아주 사소한 문제에 불과하지만, 사실은 문자열 인코딩 장벽도 있다.
어떤 윈도우가 있어서 요즘 추세대로 유니코드를 사용하며 WM_GETTEXT에 대해서는 L"abc" 같은 wide 문자열만 되돌린다. 그런 윈도우를 대상으로 GetWindowTextA 함수를 호출했다 하더라도 문자열 변환은 운영체제가 몰래 알아서 해 준다. 해당 프로그램은 ansi 문자열인 "abc"를 받는다.
요청하는 측에서는 GetWindowText나 SendMessage를 A와 W 중 어느 버전으로 호출했는지로 판단을 하고, 받는 윈도우는 RegisterClass(Ex)에서 A와 W 중 어느 버전을 이용해서 등록했는지로 판단한다.

그럼, 텍스트 지정 API와 관계가 있는 다른 분야 얘기를 또 둘 늘어놓고 글을 맺도록 하겠다.

부록 1. 창을 없애는 것과의 관계

윈도우의 텍스트를 얻어 올 때 함수를 쓰느냐 메시지를 보내느냐 하는 건, 마치 윈도우를 닫을 때 직통으로 DestroyWindow를 호출하느냐 아니면 WM_CLOSE 메시지를 보내느냐 하는 것과 비슷한 구석이 있어 보인다.

WM_CLOSE는 마우스로 X 버튼 누르거나 키보드로 Alt+F4를 누른 것과 같다. 이 메시지를 더 처리하지 않고 DefWindowProc으로 넘기면 얘가 DestroyWindow를 호출해 준다. 응용 프로그램의 경우 "이 문서를 저장하시겠습니까?"라고 질문 메시지를 출력하는 게 이 메시지를 받았을 때이다. 물론 '취소'를 누르고 메시지를 씹으면 실제로 닫히지는 않는다.

그 반면, WM_DESTROY는 이미 자기가 닫히고 없어지는 건 막을 수 없는 지경이 됐고, 그 전에 마무리 작업이나 하라는 통지이다. 아직 자기의 자식 윈도우들도 다 남아 있다. 이 메시지는 운영체제로부터 자연스럽게 받게 해야지 사용자가 인위로 생성하지는 말아야 한다.
이게 끝나고 자식 윈도우까지 다 사라진 뒤에 정말 마지막으로 오는 메시지가 바로 WM_NCDESTROY이다. 이때 하는 일은 C++ 클래스와 연결된 윈도우 프로시저에서 delete this를 하는 것 정도가 전부이다.

Get/SetWindowText가 여타 프로세스의 윈도우에 대해서는 다소 방어적으로 동작을 하듯, DestroyWindow에도 약간의 방어적인 제약이 있다. MSDN의 설명에 따르면, 얘는 다른 프로세스 정도가 아니라 아예 다른 스레드에 의해 생성된 윈도우를 파괴하지는 못한다. 그런 창을 닫으려면 그냥 WM_CLOSE라는 간접적인 방법만을 써야 한다.

앞서 말했듯이 WM_CLOSE는 응용 프로그램이 회피· 거부가 가능하기 때문에 응용 프로그램의 입장에서는 다른 스레드/프로세스의 특정 윈도우를 무조건적으로 없애지는 못한다. 굳이 그렇게 해야 할 필요도 없을 테고.
멀티스레드 환경에서 Windows의 창 관리자가 어떤 식으로 API를 설계했는지를 살펴보면 편의와 안정성을 상호 절충하기 위해 여러가지 생각을 했다는 점을 발견할 수 있다.

부록 2. 아이콘과 글꼴은 어떻게?

앞서 살펴본 것처럼 한 윈도우의 속성 중에 텍스트(TEXT)는 운영체제가 DefWindowProc을 통해 내부 텍스트를 관리하기도 하고 한편으로 값을 읽고 쓰는 동작을 customize하는 방법도 제공한다.
그럼, 윈도우와 관련된 부가 정보 중에는 아이콘과 글꼴은 어떻게 관리되는 걸까? 얘들은 함수가 아니라 메시지로만 값을 지정하고 얻어 온다는 공통점도 있다. WM_(GET/SET)(ICON/FONT)라고 말이다.

아이콘은 기본적으로 윈도우가 클래스에 소속돼 있으며, 그 클래스를 기반으로 만들어진 윈도우들이 한 아이콘을 공유하는 형태이다. 그러나 클래스 아이콘과는 별개로 필요하다면 각각의 윈도우도 자기 아이콘을 예외적으로 변경할 수 있다. 이는 특정 윈도우 클래스가 아니라 운영체제 차원에서 기본으로 제공되는 기능이다.
코드로 표현하자면 대충 이런 구조. commonIcon뿐만 아니라 myIcon도 있다는 뜻이다.

class Window {
    static Icon commonIcon;
    Icon myIcon;
public:
    Window() { myIcon=commonIcon; }
    Icon getIcon() { return myIcon; }
    void setIcon(Icon i) { myIcon=i; }
};

그렇기 때문에 대화상자는 윈도우 클래스는 동일하지만 응용 프로그램이 WM_SETICON을 보냄으로써 자신만의 아이콘으로 customize를 할 수가 있다. 그리고 이 기능은 대화상자에만 있는 게 아니라 임의의 top-level 윈도우가 다 갖추고 있다.

이런 아이콘에 비해 글꼴은 운영체제의 윈도우 내부 자료구조에 정보가 자동으로 저장되지 않는다. 내가 custom 컨트롤을 만들고 있고 거기에 대화상자의 기본 글꼴대로 문자를 찍는 기능이 있다면 내부적으로 HFONT 핸들을 멤버로 추가하고 WM_GET/SETFONT 메시지를 직접 구현해 줘야 한다. 즉, 운영체제에는 인터페이스만 정의되어 있을 뿐이다.
요약하자면 text는 내부 자료구조와 custom 동작이 모두 존재하고, icon은 내부 기본 동작만으로 충분하고, font는 기본 동작이 없기 때문에 필요한 경우 자체 구현을 해야 한다는 뜻이다.

Posted by 사무엘

2015/07/23 08:39 2015/07/23 08:39
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1119

1. Windows와 Office의 IME → 독립했다가 도로 운영체제로 합병

오~ 그러고 보니 MS Office 2013부터는 Office IME가 없어졌다는 걸 이제야 확인했다.
한때 웹브라우저인 Internet Explorer가 3~5버전 시절엔 자기가 운영체제의 셸을 뜯어고치고 comctl32, shell32 같은 시스템 DLL을 마구 업데이트 했던 것처럼, 문자 입력 쪽은 아무래도 오피스 제품의 기술 수준이 더 앞서 있었다.

그래서 IME 기반이던 다국어 입력 기능을 TSF라는 인터페이스로 바꾸는 것도 2001년에 MS Office XP가 최초로 도입했다. 그때부터 Office를 설치하면 한국어/일본어판은 자국어 IME도 새 걸로 바뀌기 시작했다. CJK 쪽이 아닌 라틴 알파벳 언어에서는 필기/음성 인식 같은 기능이 이 인터페이스를 기반으로 첫 도입됐다.

TSF 자체는 Windows XP도 운영체제 차원에서 완전히 내장돼 들어갔다. 그러나 이번엔 MS Office 2003 한글판이 제공하는 IME에서 글자가 아닌 단어 단위로 한자 변환을 하는 기능이 추가됐다. 이것은 운영체제의 IME에는 없던 기능이고 비스타에 가서야 추가됐다. 즉, 운영체제가 Office보다 한 박자씩 늦었던 것이다.

그러나 문자 입력 관련 기술들이 다 상향평준화하고 발전이 정체되면서, 굳이 Office가 IME를 또 제공할 필요가 없어졌다. 실제로 윈도 비스타 내지 Office 2007부터는 Office의 한글 IME나 Windows의 한글 IME나 차이는 거의 없어졌다. 괜히 똑같은 프로그램이 중복으로 존재하는 셈이 됐고 그 관행이 2010에까지 이어졌다가 2013부터는 드디어 Office IME는 없어졌다. 2000년대를 풍미했던 관행이 끝났다.

2. Windows와 IE → 합병하려다가 철회

운영체제의 셸의 발전을 주도하던 IE는 2000년대 중반까지 버전 6으로 90%에 달하는 점유율로 리즈 시절을 찍자, 발전이 정체되면서 역설적으로 Office IME와 비슷한 운명을 맞이할 뻔했다.
물론 IE의 버전업을 완전히 중단하는 건 아니고, IE 팀을 해체하고 Windows 팀에다가 합병시켜서 유지보수 비용을 줄이는 것이다. 그래서 IE는 독자적인 프로그램이 아니라 걍 운영체제의 일부로서 Windows와 함께 같이 유지보수를 하겠다는 것이 계획이었다. 웹브라우저는 전면 무료화가 돼 버리는 바람에 오피스나 개발툴과는 달리, 어차피 독자적인 고유 수입도 없으니 말이다.

그렇게 안일하게 생각했는데 파이어폭스의 급부상으로 인해 MS도 생각을 고쳐 먹었고, 급히 IE7을 만들게 됐다. 그리고 IE는 '셸 통합'이라는 예전 트렌드와는 달리 Windows 탐색기와는 다른 길을 가기 시작했다. Windows XP + IE6 시절에만 해도, 탐색기 창이 곧바로 IE 창으로 바뀌고, IE 주소 창에서 내 컴퓨터 디렉터리를 때리면 그 창이 곧바로 탐색기로 바뀌곤 했었는데.. 이것도 참 아련한 추억이다.
물론 지금은 아예 너무 누더기가 된 IE의 개발을 끝내고 마소가 브라우저를 처음부터 다시 만드는 지경까지 갔고 말이다.

3. Windows와 Office의 파일 대화상자 → 독립했다가 도로 운영체제로 합병

지금은 벌써 세월이 많이 지났지만, 2007년경엔 요런 일도 있었다.
원래 MS Office는 운영체제가 제공하는 파일 열기 대화상자 대신 독자 개발한 대화상자를 썼는데, 이젠 Office도 운영체제의 표준 대화상자로 복귀했다. 비슷한 시기에 출시된 Visual Studio 2008도 동일한 조치를 취했다.

운영체제가 보급으로 제공하는 대화상자는 기능이 너무 빈약하다는 이유로, 혹은 별 이유 없이 잉여력이 넘쳐서 Office 팀에서는 같은 기능을 또 만들어서 썼다. 대표적으로 favorite 폴더를 바로 클릭해서 이동하는 기능은 Windows에서는 2000/ME급에서야 도입됐지만 Office에서는 97 때부터 있었다.

하지만 Windows Vista급쯤 되니까 보급 표준 대화상자도 기능이 충분히 강력해졌고, 굳이 둘을 따로 만들 이유가 전혀 없어졌으니 그 시기에 팀간의 코드 통합이 이뤄졌다.

4. Windows와 Visual C++의 CRT → 통합 불가, 영구 독립

Visual C++은 운영체제 자체만큼이나 그야말로 전세계를 석권한 컴파일러이며, 마소 내부에서도 많이 쓴다. 그러나 전부 얘만 쓰는 건 아니었다.
Windows 개발팀이 자체적으로 보유하고 있는 컴파일러와 C 라이브러리 DLL, 그리고 비주얼 C++이 제공하는 컴파일러와 라이브러리가 처음엔 호환되었지만 시간이 갈수록 서로 호환되지 않게 되면서 문제가 심각한 지경이 됐다.

20년 전이나 지금이나 printf, strcpy, qsort 같은 표준 함수의 구현체가 한번 만들어 놓은 뒤에 도대체 바뀔 게 있나 싶지만..
보안 강화 버전이 도입되고 자료형이 32에서 64비트로 확장되는 등, C 라이브러리도 영구 봉인을 하기엔 바뀌는 게 굉장히 많았다.

그래서 Visual C++ 6.0과 Windows 98 시기를 마지막으로 C 라이브러리는 msvcrt(운영체제) 계열과 msvcr???(VC++) 계열로 서로 완전히 이원화가 돼 버렸다. 그 전에는 이름조차도 crtdll(운영체제)과 msvcrt(VC)로 따로 놀았는데 그건 운영체제가 crtdll을 버리고 msvcrt로 간 것이었다. Windows, Visual Studio, Office, IE 등 마소를 구성하는 핵심 부서들간에는 코드의 공유가 생각보다 원활하게 이뤄지지는 않고 있는 듯하다.

마소에서 만든 Windows나 Office의 구버전 바이너리들은 링커 버전 같은 내부 구조를 보면 일반적인 Visual C++ 컴파일러가 생성해 주는 형태가 아니었다. 그러던 것이 Vista 타이밍이 되면서 그 직전에 나온 가장 최신 Visual C++의 버전이 찍히게 되었으며 Office의 경우 Windows가 아닌 VC++의 CRT 라이브러리를 쓰는 형태로 바뀌었다.

그러고 보니 옛날에는 플랫폼 SDK 내지 DDK에 내장돼 있는 무료 컴파일러와 Visual C++ 컴파일러도 서로 달랐다. 그러나 이 역시 지금은 통합이 이뤄졌다. Visual C++이 일부 기능이 빠진 무료 express 에디션이 2003~2005 사이부터 나오기 시작했으며, 2013부터는 아예 MFC와 리소스 컴파일러까지 다 포함된 Community 에디션이 통째로 조건부로나마 무료로 풀렸으니 말이다. 플랫폼 SDK에 내장된 무료 C/C++ 컴파일러는 비주얼 C++ 원판에 비해서는 최적화 성능이 떨어지는 물건이었으나 그것도 비주얼 C++의 오리지널 컴파일러가 대체를 하게 됐다.

마소 내부에서 컴파일러는 비주얼 C++로 이렇게 교통 정리가 돼 가고 있으나, 워낙 다양한 버전들이 난립하고 있으니 요즘은 혼란의 여지를 원천봉쇄하려고 Visual C++ 2015부터는 "CRT 정도는 어지간해서는 각자 걍 static link하세요. 디스크 용량도 많은데.. ㄲㄲㄲ" 이러는 추세이다. 어찌 보면 CRT의 DLL 링크라는 개념이 존재하지 않던 16비트 시절로 회귀하는 것이기도 하다.

Posted by 사무엘

2015/07/20 19:21 2015/07/20 19:21
,
Response
No Trackback , 5 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1118

뉴 허라이즌스 호, 명왕성 접근

지난 7월 14일, 인류는 드디어 "명왕성과 카론의 모습을 실제 컬러 사진으로 볼 수 있는 시대"를 맞이하게 되었다. (☞ 관련 링크)

사용자 삽입 이미지

와 세상에~!! 우주덕 천문학 덕후라면 저 사진 보고 감격에 눈물이 줄줄 흐르지 않을까 싶다.
이미 위키백과와 각종 인터넷 사이트들은 지금까지 상상도 아니면 작은 점으로만 존재하던 명왕성 그림/사진들을 죄다 레알 표면 사진으로 업데이트한 지 오래이다.

내가 대학 졸업한 지 얼마 안 되어 병특 회사에 다니고 <날개셋> 한글 입력기 버전이 3.x 후반대이던 2006년 1월, 뉴 허라이즌스 호가 발사되던 시절의 기억이 아직도 생생하다. 그리고 그게 우주 공간에서 총알보다 훨씬 더 빠른 속도로 무려 9년 반을 날아간 뒤에야 인제 명왕성에 그럭저럭 도착했다. 욕봤다. 몇 년 전에는 "쟤는 아직도 토성과 천왕성 사이의 방대한 허허벌판을 열나게 뺑이 치며 날아가고 있겠구나!"하고 생각했더랬다.

뉴 허라이즌스 호가 있는 곳은 여기서는 빛이나 전파로도 가는 데 거의 5시간 반이나 걸린다. 그리고 지난 14일 저녁에 명왕성을 제일 가까이 통과했다.
명왕성에 무슨 착륙을 한다거나 하는 건 아니기 때문에, 인증샷 찍고 제대로 관측과 탐사를 할 수 있는 시간은 단 몇 시간에 불과함.

뉴 허라이즌스는 1970년대의 작품인 보이저 1, 2와 파이어니어 10, 11에 이어 21세기에 오랜만에 발사된 외행성 탐사선이다.
옛날에 보이저 2호는 때마침 외행성들이 쭉 늘어선 시기에 발사를 잘 한 덕분에, 명왕성은 말고 지금 우리가 보고 있는 천왕성과 해왕성의 근접 사진을 유일하게 전해 줄 수 있었다. 토성에서 천왕성, 천왕성에서 해왕성까지 가는 데 2, 3년씩 걸렸다. 그만큼 거기는 공간이 방대하다.

그 뒤, 명왕성은 나름 유일하게 미국인이 발견한 태양계 행성이라고 해서 미국에서 애착을 많이 가졌다.
하지만 해왕성 이후로 거기는 뭔가 행성다운 행성이 없고, 명왕성은 너무 작았다. 더구나 유사 궤도에 명왕성과 비슷하게 생긴 왜소행성들이 연달아 발견되면서 명왕성은 행성 지위를 잃게 됐다. 그렇게 결정된 게 하필 뉴 허라이즌스가 발사된 지 얼마 안 된 2006년 8월인 것도 참 절묘하다. 그래서...

사용자 삽입 이미지

<입시명문 사립정글고>라는 웹툰에서는 명왕성이라는 이름의 학생이 저렇게 멘붕해서 열폭· 자폭하는 장면도 나왔다. =_=;;

한편, 킹 제임스 성경 신자라면 친숙할 라킨의 <세대적 진리>라는 책에도 행성들이 늘어선 태양계 그림이 있다. 그런데 거기에는 해왕성까지만 있고 명왕성이 없다.
그 이유는 그 책 자체가 명왕성이 발견되기 전에 만들어졌기 때문이다. 명왕성은 1930년, 1차 세계 대전도 끝나고 대공황 이러던 시절에 클라이드 톰보라는 천문학자에 의해 발견됐다. 아마 은하의 생성 방식도 성운설이 대세이던 시절이었을 게다.

사용자 삽입 이미지

본인의 모교 고등학교에는 천문 동아리가 있었는데 이름이 POP (명왕성 너머의 행성)였다. 지금도 같은 이름으로 잘 돌아가고 있는지 모르겠다.

태양계에서 태양이 전체 물질들의 질량의 99%를 넘게 차지하는 중력 끝판왕인 것은 사실이지만, 한편으로 그 중력이 내는 인력은 거리의 '제곱'에 비례해서 급격하게 곤두박질치기도 한다.
해왕성보다도 더 먼 거리에 설마 단독 궤도를 가질 정도로 충분히 무거운 행성이 또 존재할 수 있을까? 행성이 딱 8개가 있다는 건 마치 정다면체가 딱 5개 있다는 것과 비슷하게 들린다.

그리고 끝으로.. 명왕성의 '명'은 한자가 '어두울 명'(冥)이다.
'사다'와 '팔다'가 형성자로 같은 '매'이고 '주다'와 '받다'가 역시 형성자로 같은 '수'인데 '밝다'와 '어둡다'까지 같은 '명'이라니 본인은 한자 내지 중국어가 참 이상한 문자와 언어라는 생각을 오랫동안 했다. 저런 반의어의 소리가 동일해도 될 정도로 중국어는 성조가 음운 변별에서 차지하는 비중이 매우 큰 것 같다. 물론 한국어에서는 '어둡다'라는 한자어는 '암'(暗)이 더 많이 쓰이긴 하지만 말이다.

Posted by 사무엘

2015/07/18 08:32 2015/07/18 08:32
, , ,
Response
No Trackback , 5 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1117

이탤릭체 이야기

라틴 알파벳에는 다른 문자와는 달리 이탤릭이라고 약간 기울이고 흘려서 쓴 변형 서체 유형이 있다. 획을 진하게 하는 '볼드'와 더불어, 산술적인 변형뿐만 아니라 아예 별도의 폰트를 만들어서 제공 가능한 글자 속성 중 하나이다.

옛날에 비트맵 글꼴 시절에는 윗첨자· 아래첨자와 더불어 이탤릭은 아예 별도의 글꼴(폰트 패밀리)로 제공되는 게 보통이었다. 그러나 출력 장치의 해상도가 올라가고 결정적으로 윤곽선 글꼴 기술 덕분에 글자의 크기 제약이 없어지면서 이탤릭과 윗첨자· 아래첨자는 모두 아무 글꼴에나 추가로 적용 가능한 '변형 속성'으로 바뀐 지 오래다.

우리는 지금까지 이탤릭을 아마 수학식에서 가장 자연스럽게 보고 써 왔을 것이다. 수학에서 일종의 '예약어'라 할 수 있는 sin, lim, log 같은 단어은 반드시 regular 정자체로 쓰고, 나머지 임의의 변수명은 이탤릭으로 썼으니 말이다. 단, 소문자 이탤릭을 너무 흘려서 쓰면 그리스 문자와 구분이 어려워지기도 하므로 주의가 필요하다. 예를 들어 a와 알파, n과 η, x와 χ 같은 것.

개인적으로 20여 년 전, 아래아한글 2.1이던가 2.5에서 처음 도입된 수식체를 아주 좋아했다. regular 모양은 신명조와 별 다를 바 없지만 이탤릭이 굉장히 미려했기 때문이다. 실제로 각종 수학 교재나 상업용 출판물에서 쓰인 서체이기도 했다.
지금 아래아한글은 수식의 서체가 뭔가 LaTex스러운 서체로 바뀌었고 마소 제품의 경우 한때는 그냥 타임즈이다가 지금은 다른 걸로 바뀌었는데... 난 아래아한글의 원조 수식체가 지금도 그립다.

사용자 삽입 이미지

한편, 킹 제임스 성경 신자라면 원문에 없는 단어를 뜻하는 이탤릭체 표기가 아주 친숙할 것이다. (사실은 옛날 한글 개역 성경에도 본문보다 "약간 작게 쓴 글자"가 있어서 개념적으로 동일한 역할을 하긴 했다.)

이탤릭 서체는 세로 중심선이 사선 모양으로 기울어질 뿐만 아니라, 세리프 계열의 경우 세로획의 위· 아래 끝 부분이 살짝 둥글게 삐친 형태로 바뀐다.
이탤릭 전용 서체가 없는 글꼴은 응용 프로그램이 글자 모양을 그냥 수학적인 일차 변환으로 기울여서 찍어 준다. 이것은 엄밀히 말하면 (1) Oblique라고 불리는 다른 모양일 뿐 이탤릭이 아니다.

산세리프 계열에 속하는 서체들은 딱히 이탤릭이나 오블리크나 모양 차이가 별로 없어서 굳이 이탤릭 전용 서체가 필요한가 하는 의문이 들기도 한다. 뭐, 두 글자의 모양을 한데 포개서 차이를 비교해 봐도 되겠지만. 또한 알파벳 말고 숫자 역시 Times 같은 세리프 계열 서체를 봐도 그냥 그대로 기울인 오블리크와 별 차이가 없어 보인다. 숫자는 딱히 italic-ready 문자는 아닌 듯하다.

이탤릭은 정자체보다야 날려 쓴 듯한 느낌을 주지만, 모든 글자들이 한 획으로 완전히 이어진 (2) 필기체를 표방하는 것도 아니다. 가령, 소문자 i나 l의 이탤릭은 세로선이 기울어지고 위와 아래에 동그란 삐침까지만 있지, 필기체처럼 두 선이 한 점에서 만나는 획이 생긴다거나 하지는 않는다.
Brush Script 같은 필기체 계열의 서체들은 정자체 모양이 태생적으로 이미 좀 기울어진 형태이기 때문에 또 이탤릭을 적용하는 것은 무의미하다.

끝으로, 세로 중심선은 90도 수직선인데 이탤릭체에 적용되는 삐침만 적용한 (3) upright italic이라는 것도 타이포그래피 용어로는 있는 모양이다. 실용적인 의미나 가치가 무엇이 있는지는 잘 모르겠고 그냥 이런 게 있다는 것 정도이다.

이탤릭체는 글자의 수직 높이는 변함없는데 중심선이 약간 기울어짐으로써 실질적으로 글자의 크기가 약간 더 커지는 효과를 낸다.
그런데 여기서 궁금한 게 있다. 이탤릭체는 중심선을 정확하게 몇 도 기울이는 것이 정석일까? 여기에 통일된 규격이 있긴 할까?

MS Word의 경우, 이탤릭체가 적용된 글자로 마우스 포인터를 가져가면 신기하게도 포인터의 I자 모양도 이탤릭체 모양으로 기울어진 모양으로 바뀐다. 그리고 cursor(캐럿) 역시 단순 수직선이 아니라 기울어진 사각형 모양으로 바뀐다. 사선 모양이 굉장히 엉성하고 못생기긴 했지만 말이다.

화면 캡처를 해서 들여다보면, Arial, Verdana처럼 이탤릭 전용 서체가 있는 글꼴들은 세로선의 기울기가 5인 듯하다. 즉, 오른쪽으로 1픽셀 움직이는 동안 세로로는 대략 5픽셀이 움직인다. 이것은 각도로 환산하면 약 78.7도(수직선이 90도)이며, 따라서 11~12도 정도 기울이는 셈이 된다. 기울어진 cursor의 기울기도 이것과 얼추 일치한다.

한편, 이탤릭체 모양의 마우스 포인터는 화면을 확대해서 자세히 들여다보면 기울기가 4이다(약 76도).
흥미로운 것은 전용 서체가 없이 프로그램이 기본으로 구현하는 이탤릭이다. 얘는 기울기가 거의 3(약 71.5도)에 가까워서 누운 정도가 위의 글자들보다 더 과격하다. 따로 새로 만들어진 획이 없이 전적으로 산술적인 변형만으로 기울어짐을 구현하는 것이기 때문에 더 기울여 준 건지는 모르겠다. 아무튼 내부적으로 이런 차이가 있다는 것도 알면 흥미로울 것이다.

지금까지 설명한 모든 개념들의 예를 그림으로 정리하면 다음과 같다. Arial은 bold에 대해서도 전용 이탤릭 서체가 있는 반면, Arial Black은 전용 서체 없이 산술 연산으로 오블리크가 이탤릭의 역할까지 하고 있으며 기울기가 더 과격하다는 걸 알 수 있다.

사용자 삽입 이미지

Posted by 사무엘

2015/07/16 08:44 2015/07/16 08:44
,
Response
No Trackback , 3 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1116

사용자의 마우스 클릭에 동작하는 GUI 요소들은 일단은 버튼의 down이 아니라 up 시점 때 반응을 한다. 모든 버튼(push, check, radio 공히)이나 하이퍼링크들이 이렇게 동작하며, 우클릭 메뉴도 오른쪽 버튼을 뗐을 때 튀어나온다. 그리고 이 타이밍 때 그 이름도 유명한 BN_CLICKED라는 notify 메시지가 부모 윈도우에 전달된다.

그에 반해, down 때 바로 반응을 하는 것은 스크롤 바나 슬라이더나 스핀(옆의 숫자를 증가시키거나 감소시키는 up-down 컨트롤)처럼 누르고 있는 동안 '연타'의 여지가 있는 버튼, 아니면 어떤 명령이 즉시 실행되는 게 절대로 아님이 보장되는 첫 단계 메뉴(파일, 편집, 보기) 정도로 국한된다.

그런데 이건 어떨까? 버튼인데, 사용자가 누르고 있는 동안만 풍선 도움말이나 다른 추가적인 정보가 튀어나오고, 버튼을 떼면 그것들이 사라진다. down과 up만 감지하면 되고 그 사이에 연타 개념은 없다.
이건 일단 Windows의 표준 컨트롤에는 없는 기능인 듯하다. 하지만 의외로 요런 UI가 쓰인 경우가 존재한다.

가장 먼저 떠오르는 예는 2007 버전이 나오기 전, 과거의 MS Excel이다. 선에 안티앨리어싱이 없는 건 그렇다 치더라도 색깔이 요즘 것에 비해서 우중충하고 덜 예뻐 보인다.

사용자 삽입 이미지

옛날에 엑셀에는 차트 마법사를 통해서 차트를 만들곤 했다. 1단계는 차트의 종류를 고르는 단계였는데, 아래의 길쭉한 버튼을 살포시 누르고 있으면 지금 사용자의 데이터가 어떤 형태의 차트로 표시되는지 preview를 잠시 볼 수 있었다.
버튼을 한번 눌렀다 뗄 때마다 preview 모드와 선택 모드가 toggle 형태로 바뀌는 게 아니라는 점을 주목하자. 상당히 독특한 UI가 아닐 수 없다. 왜 이렇게 만들었을까?

어지간하면 그냥 대화상자의 왼쪽에 차트의 type과 sub-type을 트리 컨트롤 같은 걸로 모두 때려박고, 오른쪽 전체에 preview 화면을 할당해도 될 듯하지만 그렇게 하기에는 오버헤드가 너무 크고, 또 차트의 타입 자체를 그림으로 표시하기 위한 공간도 많이 필요하니 이런 식으로 preview는 필요할 때 잠깐만 볼 수 있게 UI를 만든 듯하다.

참고로 Office 2007과 그 이후부터는 전통적인 차트 마법사가 없어지긴 했지만, 차트의 종류를 선택하는 대화상자 자체는 남아 있다. 단, 이렇게 버튼을 누르고 있는 동안 preview를 잠깐 보는 기능은 없어졌다.

원래 운영체제의 표준 버튼은 아까도 얘기했듯이 눌렀다 뗀 뒤의 BN_CLICKED 이벤트만 있지, 저렇게 눌러진 것에 대한 이벤트는 제공하지 않는다. 그러니 저런 기능을 구현하려면 일반적으로는 윈도우 프로시저를 서브클래싱하여 마우스 좌클릭과 Space/Enter 누름을 감지해서 좀 불편하게 구현해야 한다.
하지만 MS Office 제품 중에 Word와 Excel은 대화상자 컨트롤들을 운영체제 함수 대신 자체 GUI 엔진으로 구현했기 때문에 편법 없이 저런 기능들이 처음부터 자연스럽게 구현이 가능했을 것이다.

그리고 또 다른 예는 아주 최신 프로그램이다. 바로 Internet Explorer 11.

사용자 삽입 이미지

IE는 최신 버전이자 아마 마지막 버전이 될 것으로 보이는 11이 굉장한 쇄신을 한 것 같다. 예전보다야 가벼워지고 속도가 빨라지고, 텍스트 입력란이 TSF A급으로 바뀌고, 굴림체로 찍히던 기본 글꼴이 맑은 고딕으로 바뀌는 등 변화가 많다.

얘는 웹사이트 내부의 입력란에서 ID와 비번을 입력하기 시작했을 때 오른쪽에 자그마한 버튼이 뜬다. ID 입력란의 오른쪽 끝에는 X 버튼이 생겨서 이걸 누르면 ID가 싹 다 지워진다. 물론 지우는 동작은 눌렀다가 '뗐을 때' 행해진다.
그런데, 비번 입력란의 오른쪽에는 눈알 모양의 버튼이 생기며, 이 버튼을 누르고 있으면 동그라미로 표시되는 암호 문자열의 실제 문자열이 잠시 보인다. 이것 역시 마우스 버튼을 떼는 순간 원상복귀된다!

(1) 엑셀의 차트 미리보기와, (2) IE에서 비번 훔쳐보기가 이 동작에 상당히 적절하게 배치된 경우라고 생각된다. peek라는 동작을 표현한다고나 할까. 이것 말고 요런 동작이 유용하게 쓰일 만한 상황이나 이미 적용된 예가 무엇이 있는지 궁금하다.

마우스 포인터를 갖다대고 있는 동안 뭔가 도움말이나 추가 정보가 나타나는 UI는 그리 새삼스러운 물건이 아니다. 이미 20년 전부터 툴팁이라고 불리는 풍선 도움말이 그 역할을 하고 있으니 말이다.
단, 터치스크린에서는 click과 hover가 구분이 없기 때문에 저렇게 가리키고 있는 것을 표현할 수 없으니 누르고 있는 동안만 뭔가 추가 정보를 표시하는 기능이 더욱 필요할 것이다.

이렇게 글을 바로 맺기는 아까우니 MS Office에서만 볼 수 있는 독특한 UI를 두 가지 좀 늘어놓도록 하겠다.

1. 먼저, 탭 컨트롤의 각각에 Alt 액셀러레이터가 붙은 모양이다. 난 워드나 엑셀을 쓸 때마다 늘 신기하다고 생각해 왔다.

사용자 삽입 이미지

Alt 액셀러레이터는 IsDialogMessage라는 대화상자 전용 메시지 처리 함수가 구현해 주는 것이고, Alt는 윈도우 텍스트를 기반으로 한 윈도우당 한 글자씩만 배당된다. 그러므로 저게 정석적으로 가능하려면 각각의 탭 헤더가 마치 라디오 버튼처럼 독립된 윈도우를 구성하고 있어야 하나, 운영체제의 탭 컨트롤은 그런 구조를 하고 있지 않다.

Alt+단축키를 눌렀을 때 탭 컨트롤의 탭이 어떻게든 전환되게 하는 것 자체는 불가능하지 않다. 하지만 그러려면 윈도우 프로시저 수준이 아니라 해당 응용 프로그램의 메시지 loop 차원에다가 예외적인 처리가 필요하다. MFC로 치면 해당 대화상자의 PreTranslateMessage 함수를 굳이 새로 구현해야 한다.
그래서 본인은 MS Office의 저런 프로퍼티 시트 대화상자를 보면 신기하다는 생각이 든다.

2. 그리고, 라디오 버튼을 더블 클릭하면 대화상자가 OK(확인)으로 종료되는 것도 꽤 독특하다.
요즘 Office 프로그램들이야 워낙 기능이 방대하기 때문에 공간을 아끼기 위해 콤보 박스를 주로 쓰지, 라디오 버튼을 보기는 힘들지만.. 대표적으로 '화면 확대'라든가 탭의 종류를 고르는 화면에서 이를 확인할 수 있다.
아.. 그러고 보니 리스트 박스에서 아이템을 더블 클릭했을 때 대화상자가 재량껏 OK로 종료되는 건 생소하지 않다. 하지만 라디오 버튼을...? 한번 생각해 보시기 바란다.

Posted by 사무엘

2015/07/13 08:45 2015/07/13 08:45
,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1115

올해 초여름의 여행 일지

1. 등산

사용자 삽입 이미지

서울 지하철 4호선의 북쪽 종점인 당고개 역의 주변을 보면 산들이 병풍처럼 둘러싸여 있는 게 참 인상적이다.
기왕 등산을 할 거면 그 산을 한번 올라 보고 싶다는 생각을 진작부터 했다.
결국은 같은 수락산이긴 한데 지난 3월엔 깔딱고개 근처까지 간 반면, 이번엔 귀임봉을 지났으며, '서울 둘레길'을 지나서 7호선 마들 역 근처로 귀환했다.
그리고 예나 지금이나 맥북은 나의 소중한 등산 동반자였다.

사용자 삽입 이미지사용자 삽입 이미지

2. 중앙선 아신 역

이제 전동차의 운행 계통은 경의선과 중앙선이 통합되어 경의중앙선이라고 불리고 있긴 하지만, 그래도 경의선과 중앙선은 같은 수도권 광역전철임에도 불구하고 주변의 분위기가 아무래도 차이가 있다. 중앙선이 지나는 지역인 양평은 상수도 보호로 인해 태생적으로 개발 제한 봉인이 걸린 곳이 많으며, 개량된 중앙선 역시 강을 가까이 지나는 구간이 있기 때문이다.

여러 풍경 사진 중에서 역시 산과 강을 담은 것만 투척한다. 색감이 예뻐서. 한적한 경춘선이나 중앙선 전철역으로 나가서 코딩이나 독서를 하고 있으면 신선놀음이 따로 없다.

사용자 삽입 이미지사용자 삽입 이미지

3. 그린벨트 마을 답사

방학+주말을 기념해서 등산만 했느냐 하면, 그렇지는 않고 차 끌고 여기저기 돌아다니기도 했다.

난 예전에도 한번 언급한 바와 같이, 서울 외곽의 야산과 그린벨트 지대 탐험에 대한 로망이 좀 있는 사람이다. 한번은 동부간선 → 지방도 23호선을 타고, 서울 공항 근처의 신촌동과 심곡동 마을을 드디어 밤에 몰래 답사했다. 여기 사는 주민은 어떤 사람들일까? 대대로 여기 살던 선조의 후손? 아니면 겁나게 부자들? 민통선 안에서 농사 짓는 사람들만큼이나 신기하게 느껴진다.
미처 카메라에 담지는 못했지만 전방에서 갑자기 굉음과 함께 거대한 수송기가 활주로에 내려앉는 모습을 보기도 했다. 서울 공항(=공군 기지)이 코앞이니까.

그 뒤 청계산로로 갈아탔다. 자연의 정취가 살아 있는 으슥하고 한적한 도로를 달리면서 대왕 저수지와 신구대학 식물원 일대를 구경했다. 여기는 바깥쪽 차선이 다 자전거 도로로 만들어져 있었다. 요런 데서 차 세워 놓고 혼자 자면 가히 야영 캠핑이 따로 없을 것 같았다.

사용자 삽입 이미지
위의 고가 도로는 서울-용인 고속도로(171)이다.

계속 진행하자 길은 경부 고속도로를 나란히 지나면서 북쪽으로 가기 시작했으며, 말 그대로 청계산 등산로와 신분당선 청계산입구 역이 나왔다. 중간엔 서울 신원동의 새정이마을을 들러서 답사했다.

4. 경기화학선 폐선 부지

양재-서초 IC 사이는 잠깐 경부 고속도로 구간으로 건넜고, 다음으로 본인은 남부순환로를 타고 서울의 서쪽 끝으로 갔다. 남부순환로는 중간에 압박스러운 경사는 그렇다 치고, 중앙에 화단이 쭉 조성돼 있는 게 참 인상적이었다. 서울에서 이런 도로는 여기밖에 없는 듯. 도로 폭이 차선수를 홀수 개로 어정쩡하게밖에 만들 수 없는 규모이기라도 했나 보다.

그리고 본인이 새벽에 간 곳은.. 오류동 역과 푸른수목원의 사이에 있는 경기화학선 폐선 부지였다. 세상에, 주거지 근처에 이렇게 풀이 무성하게 우거진 폐선을 보는 건 옛날 수인선 협궤 폐선 이래로 처음이었다. 게다가 여긴 엄연히 인서울 지대인데! 과연 철덕의 성지 순례 코스가 아닐 수 없었다.

사용자 삽입 이미지사용자 삽입 이미지

사용자 삽입 이미지사용자 삽입 이미지
5. 서울 지하철 7호선 천왕 차량기지

서울 남서쪽 끝까지 먼 길을 찾아가서 철도 답사를 했는데, 여기를 들르지 않고 간다면 그건 철도에 대한 예의가 아니다.
서울 지하철 7호선 천왕 차량기지를 경건한 마음으로 한바퀴 빙 돌면서 성지순례를 했다. 자동차가 있으니 가능한 일이었다. 내가 여기를 직접 가 보는 날이 오는구나!

차량기지 중에는 도봉이나 개화처럼 아예 내부에 역이 있는 것이 있는가 하면(7호선 장암, 9호선 개화 역) 지축, 창동, 구로, 군자, 신내처럼 다른 전철역 근처에서 기지를 그럭저럭 볼 수 있는 것도 있다.
아니면 철도로는 접근을 못 해도 고덕이나 수서나 모란처럼 고속/고속화도로를 달리는 자동차의 차창 밖으로 어렴풋이 볼 수 있는 것도 있다.
하지만 천왕 차량기지는 그 어느 것에도 속하지 않기 때문에 차량기지들 중에 가장 존재감이 없고 접근이 상대적으로 어려운 곳이라고 여겨져 왔다.

여느 차량기지와 마찬가지로 대부분의 구간은 담장과 철조망이 쳐져서 은폐되어 있었지만 그래도 용케 요런 곳을 찾았다. SR001 전동차가 지상에 나와 있는 실물 사진을 건지는 데 성공했다. 허나, 내가 하는 행동은 남이 보기엔 영락없이 국가 기간 시설에서 어슬렁거리면서 무단 촬영이나 하는 수상한 간첩-_-처럼 보였을 듯..

사용자 삽입 이미지사용자 삽입 이미지

이번 여행을 통해 그린벨트 마을 3군데와 경기화학선 철길, 그리고 천왕 차량기지 답사라는 수확을 거두고 돌아왔다. 자동차는 이런 데 활용하라고 만들어진 편리한 문명의 이기임을 실감했다.

Posted by 사무엘

2015/07/10 08:36 2015/07/10 08:36
, , , , ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1114

고전 소프트웨어의 추억을 발굴하는 작업은 변함없이 계속된다.
몇 달 전엔 비트맵 그래픽 에디터 얘기를 했다. 구글링으로도 좀체 정보를 발견할 수 없던 Splash와 Image72를 찾아 냈다. 이어서 오늘은 도스용 셸 유틸리티 얘기를 해 보겠다. 출처를 도저히 알 수 없었던 한 외국산 프로그램의 정체를 또 파악하는 데 성공했기 때문이다.
그것은 이름하여 Packard Bell이다.

사용자 삽입 이미지

옛날 도스 시절엔 부팅이 끝나면 화면에 뜨는 건 시꺼먼 화면에 C:\ 프롬프트가 전부였다. 이런 인터페이스로는 초보자건 전문가건 컴퓨터를 제대로 활용하기가 몹시 불편했기 때문에, 컴퓨터에 존재하는 다른 프로그램들을 빠르고 편하게 실행시켜 주는 '셸'에 해당하는 프로그램이 별도로 여럿 만들어지곤 했다.

전문가를 위해서는 MDIR이나 노턴 커맨더처럼 파일 관리 유틸리티를 겸하는 셸이 쓰였다. 이런 프로그램들은 파일 정보만 표시하면 되니 보통 텍스트 모드에서 실행되었다.
그러나 초보자를 위해, 당시의 Windows 3.0에 준하는 GUI를 표방하면서 알록달록한 아이콘이 나오는 그래픽 셸도 있었다. 골치 아픈 단축키를 외울 필요 없이 마우스 클릭만 하면 원하는 프로그램을 실행할 수 있었다.

MS-DOS 버전 4인가 5부터 제공되었던 '도스셸'은 그래픽 모드에서 실행되는 것도 가능했지만 그래도 전자와 후자 중에서는 전자의 성격에 더 가까운 물건이었다. 그래도 GUI의 불모지인 도스에서 나름 마우스 드래그 드롭을 구현했고, 프로그램의 색상과 화면 모드를 다양하게 바꿀 수 있는 게 인상적이었다.

자, 그 와중에 저 '패커드 벨'이라는 프로그램은 우리 집 컴퓨터에 처음부터 있었던 프로그램은 아니고, 친구 집 컴퓨터에서 접했다. 그런데 GUI가 굉장히 고퀄이고 화면이 예뻤다. 16색 VGA에서 실행되는데 투박한 표준 팔레트를 쓴 게 아니라 보다시피 자체적으로 팔레트 색상을 재정의했으니 더욱 이색적인 느낌이 났다. 색상도 그렇고 글꼴도 그렇고, 알록달록한 아이콘까지, 뭔가 프로그래머가 대충 발로 그린 게 아니라 그래픽 전문가의 손길이 닿은 티가 났다. 어린 시절에 본인은 저렇게 "나만의 세계가 느껴지는 비주얼"을 보면 아주 사족을 못 썼다.

저 스크린샷에서는 안 보이지만, 원래는 마우스 드라이버가 있건 없건 마우스 포인터도 나타난다. 그런데 포인터도 운영체제가 그냥 기본으로 주는 작고 투박한 화살표가 아니라, 무려 살색의 사람 손가락 모양이다. 요즘으로 치면 웹 브라우저에서 링크를 가리킬 때 나타나는 그 마우스 포인터와 비슷하다.
화살표 키를 누르면 지금의 마우스 포인터 위치에서 그 화살표 방향으로 가장 가까이 있는 버튼으로 포인터가 이동하는데, 이것도 즉시 되는 게 아니라 부드럽게 궤적을 그리면서 이동한다. 이런 것까지 세심하게 신경을 썼다.

워드 프로세서나 그래픽 에디터가 아니고, 그렇다고 게임도 아니고.. 자체 한글 같은 것도 필요하지 않는 외국산 도스용 유틸리티가 그래픽 모드에서 가변폭 영문 글꼴 출력까지 구현한 것은 그 당시로서는 몹시 드문 일이었다.
도대체 이 프로그램은 누가 언제 어디서 만들었는지 알고 싶어서 뒤늦게 인터넷을 수소문했지만, 정보를 도저히 얻을 수 없었다.

본인은 이 프로그램의 이름이 Pen Bel(l) Desktop인 것으로 기억하고 있었다. 왕년에 베이직 프로그래머였으니 PB라고 하면 파워베이직의 이니셜이 가장 먼저 떠오르지만, 저 추억의 프로그램의 실행 파일에도 PB라는 문자가 포함되어 있긴 했다. 하지만 저 이름으로는 아무것도 검색이 되지 않았다.

이 프로그램에 대한 결정적인 단서를 얻은 곳은 IE is evil!로 유명한 이 사람의 GUI 갤러리 웹사이트였다.
도스는 말할 것도 없고 Windows 3.1 시절까지만 해도 기존의 허접 구닥다리 '프로그램 관리자'를 대체하는 싸제 셸 유틸이 수요가 있었다. 노턴 데스크톱, 그리고 MS의 흑역사 Bob 같은 프로그램들이 있는데.. 어? Packard Bell 내비게이터라는 프로그램이 있었다.

3.5 버전은 완전히 Bob처럼 그래픽 기반으로 바뀌었지만, 1.1은 보아하니 도스용과 완전히 같지는 않아도 색상과 외형이 웬지 도스용 프로그램과 관계가 있는 것 같다는 생각이 들었다.

사용자 삽입 이미지

튜토리얼, Support, your software처럼 큰 메뉴 구성이 꽤 비슷해 보이는 데다 자음 이니셜이 일치하기도 하니 동일 회사의 프로그램일 거라는 감이 강하게 들었다. 그래서 이 키워드로 구글링을 계속했다.. 그러나 일단 '패커드 벨'은 컴퓨터 제조 회사인지라 걸려 나오는 것은 온통 컴퓨터 사진밖에 없었다.

그랬는데 어느 국내 블로그에서 드디어 월척을 낚는 데 성공했다. 내가 찾던 바로 그 프로그램의 스크린샷이 나온 것이다. 프로그램과 개발사 이름이 동일하게 '패커드 벨'인 듯하다.
이 회사는 소프트웨어가 아닌 하드웨어가 주력 상품이고, 프로그램은 자기 컴퓨터에 번들로 설치되는 것 위주로만 개발한 듯하다. 소프트웨어만 전문으로 만든 게 아닌데도 1991년경에 도스와 Windows용 셸을 모두 그것도 상당히 뛰어난 퀄리티로 만든 것이 무척 대단하게 느껴진다.

사용자 삽입 이미지

그래서 이 도스용 '패커드 벨' 셸은 메뉴 구조가 좀 특이했다. ESC를 누르면 도스셸이나 '로터스 웍스' 같은 붙박이 고정 프로그램이 있고, 'Your software'을 골라야만 아까와 같은 프로그램 아이콘 리스트가 나타났다. 패커드 벨 컴퓨터에는 원래 '로터스 웍스'도 번들로 제공되었던 듯하다.

사용자 삽입 이미지사용자 삽입 이미지

새로운 프로그램을 등록하는 화면이다. 아이템에 사용할 '아이콘', 밑에 표시할 텍스트, 그리고 실제로 실행할 프로그램 이렇게 세 가지 정보를 서로 다른 화면에서 지정해 줄 수 있다. 아이콘은 저 35종류의 기성 그림 중 하나만 선택할 수 있고 다른 외부 그림 파일을 사용할 수는 없다는 게 특이하고 한편으로는 아쉬운 점이다. 기성 그림들은 각각 어떤 컨셉으로 만든 건지는 잘 모르겠다.

그리고 저 스크린샷에서는 제대로 나타나지 않았지만, 원래 이 프로그램은 하드디스크에 존재하는 모든 실행 파일들을 아래의 리스트에다가 표시해 준다. 그래서 사용자는 일반적인 파일 열기 대화상자를 다룰 때처럼 매번 디렉터리를 오갈 필요 없이 한 목록에서 실행 파일을 곧장 선택할 수 있었다. 이건 사실 MS 도스 셸에도 있던 기능이다. 2~30여 년 전, 한 하드디스크가 크기가 수십~100수십 MB밖에 하지 않던 시절에나 가능했던 일이다.

지금 다시 저 프로그램을 접할 수 있다면 무척 감회가 새롭고 흥미진진할 것 같다.

도스 셸 하니까 생각나는데, 옛날에 MS-DOS 4.0은 우리가 아는 그 4.0만 있는 게 아니라 '멀티태스킹 에디션'이라고 유럽 쪽에서 주로 쓰인 다른 브랜치가 있었다고 한다. 16비트 Windows가 사용하던 New Executable 포맷도 사실은 이때 처음으로 제정되었다고 하고.

또한, 국내에서 개발된 그래픽 위주 도스 셸로는 먼 옛날(1993년쯤) 이 종하 씨가 개발한 '능금'이라는 프로그램도 있었다. 옛날에는 '파란연필'이라는 텍스트 에디터도 개발했던 분인데 본인은 요것들은 옛날 컴퓨터에서 다 직접 써 봤다.
'능금'은 셰어웨어였으며, 비등록 공개판은 등록할 수 있는 그룹과 프로그램 개수에 제한이 걸려 있었다.

사용자 삽입 이미지

그래픽 셸로서 '능금'이 지닌 가장 독특한 점은.. 한 아이템에 대한 아이콘을 최대 5개까지 연달아 지정해서 초보적인 수준의 '움짤'을 만들 수가 있다는 점이었다. 물론 외부 파일 사용 가능함. 저 스크린샷을 보면 '그래픽'의 경우 물결이 출렁거렸고, '게임'은 테트리스 블록이 내려가는 모습이 반복되곤 했다.
그래도 '능금'의 기본 팔레트 화면과 저 아이콘들은 '패커드 벨'에 비하면 좀 아마추어 같은 느낌이 들긴 한다. ^^

Posted by 사무엘

2015/07/07 08:34 2015/07/07 08:34
, , ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1113

대변 처리 관련 이야기 외

1. 하수도 시설

사람이 사는 환경에서 배설물의 처리는 생각보다 굉장히 골치 아프면서 결코 무시할 수 없는 중요한 문제이다.

오늘날과 같은 위생적인 상하수도 인프라가 없던 시절엔 정말 말도 못 할 정도로 상황이 열악했다. 건물들로 가득한 도시에서는 농촌과는 달리 퇴비로 활용할 수도 없으니, 오물을 그냥 바로 길거리에다 버렸다고 한다. 그럼 길거리는 대변 썩는 냄새로 진동하고 온갖 해충과 불결한 동물들이 들끓었으니 전염병이 돌기도 딱 좋았다. 길거리에서 똥을 안 밟으려고 하이힐이 만들어졌고, 구린내를 가리려고 향수가 발명되었다니 그 시절을 생각하면 무섭기까지 하다.

닥치고 기름 끼얹고 불태워 버리면 악취는 좀 줄어들지 않으려나 싶지만, 갓 배출된 대변은 수분이 상당히 많은 물질이어서 소각하기가 쉽지 않을 것이다. 또한 매번 그렇게 처분하기엔 비용도 많이 들고 이산화탄소-_- 배출 측면에서도 별로 좋을 것 같지 않다.

잘은 모르겠지만 다른 동물보다도 사람의 X이 유난히 더 독하고 구리다고 어디서 들은 것 같다. 성경에서도 이 점이 감안되어, 에스겔이 징징대자 하나님이 인분 대신 소똥을 말려서 연료로 쓰라고 대체제를 제안하신 장면이 나오는 게 아닐까? (겔 4:12-15)
또한 같은 인분이어도 요즘은 경제적으로 풍요로워지면서 육식 섭취가 늘면서 단백질 때문에 더 구려지기도 하지 않았나 싶다. 지금 이 문단에 나오는 말들은 다 개인적인 추측임을 밝힌다.

우리나라도 조선 구한말 때 한양에 인구가 크게 늘었을 때는 인구 대비 도시 기반 시설이 너무 열악했던 관계로 길거리에 굴러다니는 오물이 심각한 수준이었다고 한다. 조선이 미개하고 일제에 의해 망해도 할 말 없는 개막장이었다는 것을 강조하는 진영에서는 이런 사진도 제시하는 모양이다. 길바닥에 굴러다니는 붉은 원이 전부 X이라고 한다. 노면전차가 다닐 정도로 사대문 안의 최대 번화가인데도!

사용자 삽입 이미지

그리고 21세기까지 지구상에 존속하고 있는 최악의 생지옥인 북한에서는 다른 깡촌도 아니고 평양의 상류층 아파트에서까지 안습한 일이 벌어지고 있다고 전에 한번 얘기한 바 있다.
수돗물과 전기, 가스 따위가 제대로 공급되지 않아서 겨울에 이불 뒤집어쓰고 냉방으로 지내는 건 차라리 양반. 수십 층 위에서 노인들은 집 밖으로 나오질 못하고(계단!), 게다가 수세식 변기도 물을 내릴 수가 없어서 신문지 위에다 응가를 본 뒤 오물을 밤에 몰래 베란다에서 아래로 투척한다.

그런 짓을 하지 말라고 감시를 해도 주변에 남조선처럼 가로등 불빛이 있나, CCTV가 있나, 그 암흑천지 속에서 누가 몰래 갑자기 투척하는 걸 잡아 내는 건 불가능하다. 그게 크기가 아주 큰 것도 아니고..
그러니 매일 아파트 근처 바닥에 철퍼덕 떨어진 똥을 치우는 사람들이 고역이라고 한다. 심지어는 밤에 길을 지나가다가 똥벼락을 맞는 사람도 있다. 밤에는 아파트 근처에는 접근을 안 하는 게 상책이다.

우리나라는 그 정도까지 막장은 아니지만 철도 차량이 1980년대까지만 해도 대소변이 그대로 선로 밖으로 떨어져 나가는 '비산식 화장실' 객차가 다니곤 했다. 물론 지금은 그런 미개한 객차는 전국에서 완전히 자취를 감춘 지 20년 가까이 됐지만 말이다.

2. 극지와 험지, 특수한 직업

이런 상하수도 시설과는 별개로, 직업적으로 제때에 화장실에 갈 수가 없는 사람들이 있다. 가장 가깝게는 화장실이 없는 교통수단을 운전하는 택시/버스 운전사나 지하철 기관사이다. 지하철 기관사의 경우, 정말 급할 때는 소변 정도는 섬식 승강장역에 정차했을 때 승강장 쪽이 아닌 벽 쪽 문을 열고 몰래 처리하기도 했다고 한다.

여객기가 아닌 전투기 조종사는 장시간 임무를 수행해야 할 경우 별 수 없다. 기저귀를 챙긴다고 한다.

성경에도 지금으로 치면 야전에서 싸우는 육군 보병에게 적용되는 말이 있다. 필드에서 볼일을 보고 나면 삽으로 흙을 파서 오물을 잘~ 덮어서 은폐를 하라고(신 23:12-14) 말이다. 마치 옷을 입어서 신체의 부끄러운 곳을 가리듯, 더러운 배설물도 안 보이게 잘 가려 놓으면 하나님이 전쟁 중에 복을 주실 거라고까지 약속했다. 의외로 이런 시시콜콜한 얘기가 모세 율법에 기록돼 있다.

옛날에 아문센과 스콧 시절에는 어떠했는지 모르겠지만, 남극 조약까지 다 체결된 지금 남극을 탐험하는 팀은 사람이 안 사는 곳이라고 해서 주변에 무단 방뇨· 방변을 해서는 안 된다. 모든 인원의 배설물은 고이 회수해서 정화 처리를 한 후, 남극의 밖에다 버려야 한다. 쓰레기는 말할 것도 없고 인체의 생리 현상으로도 주변을 오염시키지 않아야 한다는 국제 협정이 맺어져 있기 때문이다.

과거에 달 포함 우주에 갔다 온 사람들도 자기 배설물을 감히 지구 밖으로 방출하지 않았다. 단, 이와 관련해서 황당하지만 마냥 웃을 수만도 없는 안습한 사건이 1969년 5월 말에 발사된 아폴로 10호 미션 때 있었다.

아폴로 10호는 달에 최초로 착륙을 한 11호의 직전 미션이었다. 달의 궤도에 진입하여 사령선과 착륙선이 분리를 하고, 착륙선이 달 표면 기준 15.6km 고도의 상공까지 내려갔다가 도로 사령선으로 합류한 뒤 지구로 돌아왔다.

달 탐사 우주선은 우주 정거장이 아니며, 화장실을 따로 만들 공간이 없다. 사람이 재량껏 엉덩이에다 봉지를 요강 삼아서 오물을 잘 담아야 한다.; 그런데... 사령선 안에서 누군가가 대변을 보는데 뒷처리를 제대로 못 한 모양이었다. 그래서 주인을 알 수 없는 똥이 그 좁은 우주선 안의 무중력 공간에서 둥둥 떠 다니는 참극(...ㅠ.ㅠ)이 벌어졌다!

승무원들 3명이 모두 자기가 싼 똥이 아니라고 주장하는 대화 내용이 고스란히 녹음되고 문서로 기록됐고=_=;;, 그게 수십년 뒤에 비밀이 풀려서 일반인에게까지 공개됐다. 예기치 않게 실수로 초대형 민폐를 끼친 당사자만이 그 똥이 누구 똥인지에 대한 진실을 죽을 때까지 혼자 간직하다 갈 것이다. =_=;;;

사용자 삽입 이미지

착륙선의 분리는 없이 최초로 달을 돌고 오는 것까지 성공했던 아폴로 8호 미션(1968년 크리스마스) 때는.. 창세기 1장 낭독 애드립이 있었다. 그 뒤 10호 미션 때는 저런 똥 해프닝이 있었다는 점이 흥미롭다.

3. 저격수 비유

본인은 예전에 군대에서의 전문직인 전투기 조종사와 저격수를 비교하는 글을 쓴 적이 있었다.
저격수의 경우 총만 기가 막히게 잘 쏜다고 해서 되는 게 아니다. 혼자 몰래 잠입해서 임무를 수행한다는 특성상 간첩, 무장공비, 공작원과 같은 성격도 지닌다.

이런 배경으로 인해 저격수는 수풀 속에서 위장을 한 후 목표물이 나타날 때까지 꼼짝도 안 하고 근성으로 기다리는 훈련을 한다. 공작원이 적진에서 비트를 파고 잠복하는 것과 비슷하다. 위장을 잘 하면 적군들이 자기 위를 밟고 지나가기도 한다.
그런데 그 긴 시간 동안 정말로 꼼짝도 안 하고 있을까? 밥과 물은 안 먹는다 쳐도 대소변은 어떻게 처리해야 할까?

지난 2011년 9월에는 MBC 시사매거진 2580에서 저격수 특수부대를 취재한 적이 있었다.

사용자 삽입 이미지

저격수: 위장을 한 채로 표적이 나타날 때까지 3박 4일 동안 한 자리에서 꼼짝도 안 하고 견뎌 본 적이 있습니다.
기자: 생리현상 같은 건 어떻게 해결해야 합니까?
저격수: 그게 가장 힘든 부분인데, 최대한 자제를 하며... 정말 어려울 경우에는... 어쩔 수 없습니다. 어떤 경우든 절대 움직이지 않고 해결하고 있습니다.


이런 게 인생이고 현실이며 실전이다. 현실의 전쟁은 스타크래프트가 아니며 저런 임무에도 간지 나고 아름다운 모습만 있는 게 아니다.
머뭇머뭇 쭈뼛거리면서 "정말 어려울 경우에는... 어쩔 수 없습니다..."라고 대답하는 저격수의 속사정은 무엇일까?

별 수 없다. 도저히 어쩔 수 없으면 결국은 바지에다 싼다는 얘기다.
그런 것까지 대비해서 저격수 훈련 중에 기저귀까지 미리 지급해 주는지는 난 모르겠지만, 결국 대놓고 직접 얘기를 안 할 뿐이지 뻔한 결말인 것이다.

자기 입으로 직접 말하기는 민망하지만, 직접 말 안 해도 결국 그 말이 그 말인 사례는.. 성경에도 많다.

  • 가인은 누구와 결혼했는가? (여동생 중 하나와 결혼했다. 그 시절엔 근친 결혼이 이상한 짓이 아니었으니까.)
  • 함은 술 취해 잠든 아버지 노아에게 무슨 짓을 했는가? (검열삭제를 했다)
  • 입다는 자기 딸에게 결국 무슨 행동을 했는가? (결국 딸을 이삭 죽이듯이 죽였다)
  • 6일 창조가 있기 전에 이전 세상에 무슨 일이 있었는가? (물의 넘침으로 멸망했다)
  • 노아의 홍수 이전에 하나님의 아들들이 사람의 딸에게 무슨 짓을 했는가? (유전자가 교란된 반신반인 괴생명체가 태어나게 되는 짓을 함)
  • 민수기 24장과 25장 사이에 발람이 무슨 짓을 했는가? (차마 입에 담을 수 없는 비열한 방법으로 하나님의 성품을 역이용해 이스라엘 백성들을 실족시켰다)

"에이, 저 멋진 정예 군인인 저격수가 바지에 똥을 쌀 리가 없어. 저건 문자적인 배설물이 아닐 거야, / 문자적인 3박 4일이 아닐 거야" 이런 반응을 할 게 아니라면, 성경에 기록된 엄연한 사건을 문자적으로 믿지 못할 이유는 없을 것이다. 하나님의 입장에서도 민망해서 굳이 일일이 디테일을 기록할 필요가 없고 정황상 안 봐도 뻔하니 간접적으로 기록을 해 놓은 것이다.

이상. 성경을 읽고 내용을 믿는 태도에 대해서 얘기하기 위해서 먼저 똥 얘기부터 장황하게 늘어놓게 되었다. ^^

Posted by 사무엘

2015/07/04 08:28 2015/07/04 08:28
, , , , ,
Response
No Trackback , a comment
RSS :
http://moogi.new21.org/tc/rss/response/1112

Visual C++ 디버거 관련 생각

코딩으로 먹고 사는 프로그래머 내지 소프트웨어 개발자에게 필요한 것은 단순히 새로운 코드를 스스로 잘 작성하는 능력뿐만이 아니라, 문제가 생겼을 때 디버깅을 잘 하고 남이 만들어 놓은 코드를 신속하게 읽고 분석하는 능력이다. 아니, 업계에서는 어찌 보면 후자가 전자 이상으로 더 중요한지도 모른다. 왜냐하면 오늘날은 뭔가 완전히 새로운 솔루션을 천재 프로그래머 한 명에서 밑바닥부터 새로 만들어 낼 일은 거의 없어졌기 때문이다.

나의 영원한 친구는 비주얼 C++이고, 비주얼 C++ IDE는 예로부터 굉장히 편리한 디버깅 기능을 제공해 왔다. (일례로 Shift+F5는 엉덩국 홍콩행 C언어 병맛 만화에도 나올 정도로 유명한 비주얼 C++ 단축키이다. 디버그 중단 =_=)
특히 IDE가 32비트임에도 불구하고 64비트 프로세스를 아주 seamless하게 디버깅 해 내는 건 아무리 생각해도 대단해 보인다. 물론 이를 구현하기 위해 내부적으로는 64비트 디버그 서버 프로세스를 따로 만들고, 걔가 IDE와 디버기 프로그램 사이를 중재하고 있긴 하다. 그렇게 하는 것 말고는 기술적으로 다른 방법이 없다.

다만, 여러 편리한 기능에도 불구하고 본인이 일말의 아쉬움을 느끼는 점들을 나열하자면 다음과 같다.

1.
소스 코드에서 breakpoint를 여러 곳에 지정해 놓고서
한 breakpoint(A)가 적중한 뒤부터 다른 쪽 breakpoint(B)를 지났을 때 프로그램이 멈추게 하는 게 지원됐으면 좋겠다.

디버깅을 하고자 하는 지점이 평소에도 자주 지나는 곳이긴 하지만, 특정 조건이 만족된 뒤부터 실제로 의미를 갖는다는 뜻이다.
이런 상황에 대비해서 n회 이상 적중했을 때 멈춤, 특정 변수값이 변했을 때 멈춤 같은 여러 breakpoint 옵션이 있긴 하지만..
다른 breakpoint의 hit에 의존하여 그 뒤부터 멈추게 하는 기능은 Visual C++에서 지금까지 못 본 것 같다. 이거 회사일을 할 때와 <날개셋> 개발 중에 자주 필요성을 느꼈다.

IDE 내지 디버거가 이런 기능을 지원 안 해 주면 결국 사람이 해당 기능을 직접 코드에다 써 넣어야 한다.
bool 타입의 전역변수(bkpoint)를 하나 만든 뒤 A에 해당하는 지점에서는 bkpoint=true를 지정하고,
B에 해당하는 지점에서는 extern bkpoint; if(bkpoint) DebugBreak() 를 호출하는 식이다.
이런 긴급/땜빵 코드를 집어넣을 때는 굳이 클래스 따위 생각할 필요 없이 global scope이 존재하는 C/C++이 편리하게 느껴진다.

하지만 조건을 지정하는 코드와 멈추는 코드가 서로 다른 모듈에 있는 경우(static LIB, DLL, EXE 등) 여러 모듈을 고쳐서 재빌드해야 하고 일이 골치아파진다. 그러니 코드를 건드릴 필요 없이 이런 기능 정도는 개발툴이 바로 지원해 주는 게 속 편하다.

사실, 이런 쪽의 기능이 계속 추가되다 보면 디버거도 전처리기나 빌드 시스템처럼 일종의 프로그래밍 가능한 독자적인 시스템이 될지도 모르겠다. 사실은 <날개셋> 한글 입력기의 개발에서는 todo list를 분류하고 체계화하는 것부터가 전략이고 프로그래밍이다.

2.
디버그 로그를 찍는 API 함수는 OutputDebugString이며, 얘는 문자열을 받아들이는 여느 함수들과 마찬가지로 W 버전과 A 버전이 있다. 그러나 얘는 실제로는 오늘날의 NT 계열 운영체제에서도 유니코드를 지원하지 않는다.
다른 함수들은 A 버전이 문자열을 변환한 후 W 버전을 호출하는 형태이지만, 이 함수는 뜻밖에도 W 버전이 문자열을 변환한 후 내부적으로 A 버전을 호출한다.

물론 99%에 가까운 상황에서 프로그래머가 필요로 하는 로그 문자열은 단순히 알파벳과 숫자만으로 이뤄져 있어도 하등 지장이 없으며 충분하다. 그러나 본인처럼 문자 입력기 내지 마이너한 유니코드 문자/글꼴 쪽을 종종 연구하는 입장에서는.. 그런 문자열을 디버거로 곧장 확인할 수가 없어서 불편을 겪은 적이 생각보다 자주 있었다.

디버거 쪽이 여전히 1바이트 문자열 기반 프로토콜이 관행이어서 유니코드를 도입할 수 없다는 말도 변명에 지나지 않는다. 그런 용도로 쓰라고 엄연히 utf8이라는 물건이 있기 때문이다. 소프트웨어 국제화의 혜택이 사용자 인터페이스뿐만이 아니라 이런 데에까지 도달해야 하지 않을지?
직접 확인해 보지는 않았지만 C++말고 C#이나 자바는 디버그 로그가 유니코드를 지원 안 할 리가 없으리라고 생각한다.

3.
최신 201x 버전에서도 가끔은 프로젝트를 빌드하는 데 쓰였던 멀쩡한 소스 파일이 디버거에서 인식이 안 되는 경우가 가끔 있다. F9를 눌러도 해당 라인엔 빈 동그라미○만 생기지 breakpoint가 성공적으로 만들어졌음을 의미하는 ●가 생기지 않는다.
DebugBreak()를 손수 집어넣어서 강제로 세우더라도 그 지점에서 call stack 리스트가 제대로 생성돼 있지 않다. 또한 breakpoint는 만들어지지만 심벌 테이블이 좀 맛이 갔는지 변수값 조회가 동작하지 않을 때도 있다.

본인은 이 현상에 대해 정확한 문제 재연 조건과 원인, 해결 내지 예방 방법을 아직도 정확히 모른다. 프로젝트 전체를 재빌드하고 Visual C++ IDE를 재시작하고 나면 해결되기도 하고 안 그럴 때도 있었던 것 같다. VC++ 6의 고질병이던 허접 인텔리센스 ncb가 깨지는 문제는 오늘날 더 볼 일이 없지만, 디버깅은 여전히 완벽하지 못하다.

그러고 보니 디버그 심벌 데이터베이스는 IDE의 인텔리센스 데이터베이스와는 커버하는 영역이 정확하게 같을 수가 없겠다는 생각이 들었다. 전자는 우리 프로젝트 밖에서 빌드되어 LIB, DLL들에 존재하는 소스 코드와 그쪽 심벌까지 모두 연계해서 동작해야 하기 때문이다. (인텔리센스 정보가 없는 곳)

4.
이 외에도,
함수 안으로 들어가긴 하는데(F11), 그 함수의 인자와 관련된 함수 호출들은 모두 무정차로 건너뛰고서 들어가는 step in이 있었으면 좋겠다. 즉, A(b(), c()) 줄에서 시작한다면 b()나 c()로 들어가는 게 아니라 바로 A()의 몸체로 들어간다는 뜻이다.

그리고 디버깅과 직접적인 관계는 없지만, 텍스트를 검색하는데 주석 내용은 빼고 검색하거나 주석에서만 검색하는 기능도 있으면 좋겠다. #if 0과는 달리 주석 영역을 파악하는 건 단순 텍스트 패턴 매칭이므로 그리 어렵지 않을 것이다.

Posted by 사무엘

2015/07/01 19:31 2015/07/01 19:31
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1111

« Previous : 1 : ... 119 : 120 : 121 : 122 : 123 : 124 : 125 : 126 : 127 : ... 221 : Next »

블로그 이미지

그런즉 이제 애호박, 단호박, 늙은호박 이 셋은 항상 있으나, 그 중에 제일은 늙은호박이니라.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2024/12   »
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:
3053218
Today:
1525
Yesterday:
2713