« Previous : 1 : ... 117 : 118 : 119 : 120 : 121 : 122 : 123 : 124 : 125 : ... 221 : Next »

※ 메모리 단편화

컴퓨터에서 무작위 읽기/쓰기가 가능한 모든 기억장치.. 즉 RAM, 파일 시스템, 데이터베이스 따위에는 모두 구조적으로 단편화라는 문제가 존재한다.
메모리를 10바이트씩 찔끔찔끔 요청했는데 최소 할당 단위 제약 때문에 실제로는 수백 바이트 단위로 성큼성큼 용량이 짤려 나간다거나(내부 단편화),
전체 남은 용량은 1000바이트인데 한 600바이트 정도 연속된 구간이 없어서 메모리 할당이 실패하는 외부 단편화가 모두 존재한다.

메모리라는 게 1차원적인 공간이기 때문에 이건 뭐 어쩔 수 없다.
그래서 컨텐츠가 실제로 차지하는 용량보다 전체 소모 용량이 더 커지게 되고, 이런 걸 관리하는 프로그램이나 유틸리티에는 조각 모음(defrag), shrink, compact 같은 동작을 강제로 수행하는 기능이 있다. (뭐, 디스크 중에서 SSD는 예외적으로 조각 모음이 필요하지 않은 구조라고는 하지만.)

디스크는 애초부터 파일 시스템의 지배 하에 있으며 그 시스템이 제공하는 방식대로 디렉터리와 파일 이름을 통해서만 내용에 접근 가능하다. 일반적인 응용 프로그램이 디스크를 무슨 실린더 번호 x, 트랙 y, 섹터 z 같은 형태로 무식하게 접근하는 경우는 거의 없다. 그런 방식은 오늘날의 운영체제에서는 더욱 금기시되고 있다.

그렇게 파일명이라는 고수준 추상 계층이 있는 덕분에 디스크는 내부적으로 막 조각 모음을 해도 딱히 파일을 못 찾는 일이 발생하지는 않는다. 저수준 처리는 운영체제의 파일 시스템이 알아서 다 처리해 준다. 또한 디스크 정도면 물리적으로 액세스를 하는 데서 발생하는 병목이 소프트웨어적인 추상화 계층을 거치는 시간보다 훨씬 더 길기도 하고 말이다. 사용자에게는 외부 단편화보다는 클러스터 최소 단위로 인한 내부 단편화가 현실적으로 더 와 닿는다.

그런데 RAM은 디스크와는 사정이 다르다. 단편화를 예방한답시고 함부로 컨텐츠들을 재배치하면 memcpy 오버헤드는 둘째치고라도 그 메모리 주소를 직접 가리키고 있던 수많은 포인터들이 작살이 나 버린다.
메모리 자원이 극도로 가난하고 열악하던 16비트 Windows 시절에는 운영체제의 global/local heap으로부터 메모리를 할당받고 나면 곧바로 포인터가 돌아오는 게 아니라 핸들 하나만이 돌아왔다. 이 핸들이 가리키는 메모리는 운영체제의 사정에 따라 수시로 재배치될 수 있는데, 메모리를 실제로 사용할 때만 lock을 걸어서 위치를 고정시킨 뒤, 포인터를 얻어와서 메모리를 참조하곤 했다. 사용이 끝나면 다시 unlock을 해 줘야 한다.

이것이 바로 GlobalAlloc - GlobalLock - GlobalUnlock - GlobalFree 사이클이다. 재배치를 하는 이유는 당연히 메모리 단편화를 극복하고, 연속된 긴 메모리 공간을 언제나 확보하기 위해서이다. 16비트 시절에 메모리 블록이나 리소스 같은 데에 discardable, resident, non-resident 같은 속성이 달려 있던 이유는, 수시로 재배치 내지 재로딩 같은 빡센 메모리 관리에 대응하기 위해서이다.
운영체제가 자동으로 무슨 garbage collect를 해 주는 것도 아니고, 저런 일을 해야만 했다는 게 참 안습하다.

여기서 우리가 알 수 있는 점은, 32비트 정도 되는 주소 공간에서 가상 메모리가 제공되는 게 프로그래머의 관점에서 얼마나 축복이냐 하는 것이다. 4기가바이트 정도 넉넉한 공간이 있으면, 단편화 문제는 주소빨로 어느 정도, 상당 부분 극복이 가능해진다. 어지간히 단편화가 심한 상태라 해도, 또 대용량 메모리 요청이 들어오면 걍 다음 주소를 끌어다가 물리 메모리에다 대응시켜 쓰면 되기 때문이다.

그 연속된 가상 메모리 주소를 실제로는 여기저기 흩어졌을 가능성이 높은 지저분한 물리 메모리로 대응시키는 건 운영체제와 CPU의 몫이다. 물리 메모리가 부족하면 하드디스크 스와핑까지 알아서 해 준다. 가상 메모리 덕분에 프로세스간에 보안이 더 향상된 것도 덤이고 말이다.

이것이 RAM과 디스크의 차이이다. 디스크에 파일명이 있다면 RAM에는 가상 메모리 메커니즘이 있다. 한 주소 공간 안에서 스레드가 여러 개 있는 경우 가상 메모리의 필요성은 더욱 커진다.
물론, 세상에 공짜는 없으니, 가상 메모리는 메모리를 관리하기 위한 추가적인 메모리도 적지 않게 소요하는 테크닉인 걸 알아야 한다. 물리적인 메모리뿐만이 아니라 가상 메모리 주소 영역 자체도 떼먹는다.
오늘날 64비트 운영체제라 해도 어마어마하게 방대한 공간인 64비트 전체를 사용하는 게 아니라 40비트대 정도만 사용하는 것도 이런 이유 때문이다.

※ 옛날 이야기

옛날의 프로그래밍 언어나 소프트웨어 플랫폼을 살펴보면, 메모리와 관련하여 오늘날 당연한 기본 필수라고 여겨지는 요소가 대놓고 빠진 것들이 적지 않아 놀라게 된다.

(1) 예를 들어 옛날에 포트란 언어는 함수 호출은 가능하지만 초기에는 동일 함수에 대한 중첩/재귀 호출이 가능하지 않았다. 세상에 뭐 이런 언어가 다 있나 싶다..;; 함수 안에서 지역 변수의 사용이 스택 기반으로 되어 있지 않고 늘 고정된 주소로만 접근하게 돼 있어서 그랬던 모양이다.

오늘날의 프로그래밍 언어에서야 지역 변수는 스택의 기준 주소로부터 상대적인 위치를 건드리게.. 일종의 position independent code 형태로 접근된다. 재귀 호출 지원뿐만 아니라 코드 실행 주체가 증가하는 멀티스레드 환경에서는 각 스레드가 또 독립된 스택을 갖고 있으니 절대 고정 주소가 더욱 의미를 상실하기 때문이다. 멀티스레드는 thread-local이라는 일종의 새로운 scope까지 만들었다.

(2) 한편, 프로그래밍 언어 쪽은 아니지만, Win32의 구현체 중에 제일 허접하고 불안정하고 열악하던 Win32s는..
멀티스레드도 없고 각 프로세스마다 독립된 주소 공간이 없는 건 그렇다 치는데... DLL은 자신이 붙는 각 프로세스별로 자기만의 독립된 데이터 공간마저도 보장받지 못했다. 16비트 DLL과 다를 바가 없다는 뜻.

옛날에 아래아한글 3.0b는 윈도 95나 NT 말고 3.1 + Win32s에서 돌아갈 때는 무슨 자기네 고유한 메모리 서버 프로그램을 먼저 실행한 뒤에야 실행 가능했다. 이제 와서 다시 생각해 보니, 그 메모리 서버가 하는 일이 바로 DLL별로 고유한 기억장소를 할당하는 것과 관련이 있지 않았나 싶다. 아래아한글의 소스를 모르는 상태에서 그냥 개인적으로 하는 추측이다.

아시다시피 16비트 Windows는 가상 메모리 같은 게 없다 보니, 콜백 함수의 실행 context를 레지스터에다 써 주는 것조차 소프트웨어가 수동으로 해야 할 정도로 진짜 가관이 따로 없었다.

※ 쓰레기(다 쓴 메모리) 수집

끝으로 garbage collector 얘기다.
heap으로부터 할당하는 메모리는 너무 dynamic한지라 언제 얼마만치 할당해서 언제 해제되는지에 대한 기약이 없다. 그걸 소스 코드만 들여다보고서 정적 분석으로 완벽하게 예측하는 건 원천적으로 불가능하다.

하지만 정해진 scope이 없는 동적 메모리를 잘못 건드려서 발생하는 소프트웨어 버그는 마치 자동차의 교통사고처럼 업계에서 상당히 심각한 문제이다.
memory leak은 당장 뻑이 나지는 않지만 프레임 단위 리얼타임으로, 혹은 수 개월~수 년간 지속적으로 돌아가는 소프트웨어에서는 치명적이다. 또한 다른 메모리/포인터 버그도 단순히 혼자만 뻑나는 걸로 끝나면 차라리 다행이지, 아예 악성 코드를 실행시키는 보안 문제로까지 상황을 악화시킬 수 있다.

이 동적 메모리 관리를 사람에게 수동으로 맡겨서는 안전하지 못하니, 메모리 자원 회수를 프로그래밍 언어 런타임 차원에서 자동으로 보장되게 하는 기법이 연구되어 왔다.
고전적인 reference counting 테크닉은 C++의 생성자/소멸자 패러다임과 맞물려서 일찍부터 연구되어 왔으며 smart pointer 같은 구현체도 있다.

이건 원리가 아주 간단하며, 언어 차원에서 포인터의 scope가 벗어나는 족족 메모리가 칼같이 회수되는 게 컴파일 시점에서 보장된다. 그래서 깔끔한 것 하나는 좋다.
허나 이 기법은 생각보다 비효율과 단점도 많다. 대표적인 논리적 결함인 순환 참조는.. 서로 다른 두 객체가 상대방을 서로 참조하여 똑같이 참조 횟수가 1보다 커지고, 따라서 둘이 메모리가 결코 해제되지 않아서 leak으로 남는 문제이다.

즉, 레퍼런스 카운팅이 잘 동작하려면, 참조를 받은 피참조자는 자신을 참조하는 놈을 역참조하지 말아야 한다. 이걸 어기면 객체간의 레퍼런스 카운트가 꼬여 버린다.
문제는 이걸 일일이 조심하면서 코드를 작성하는 게 상황에 따라서는 차라리 걍 메모리 자체를 수동으로 관리하는 게 나을 정도로 효율이 떨어질 수 있다는 것이다. 게다가 고리가 어디 A-B, B-A 사이에만 생기겠는가? A-B, B-C, C-A 같은 식으로 더 골치 아프게 생길 수도 있다. 참조 관계는 정말로 cycle이 없이 tree 형태로만 가야 한다.

그러니 이 문제는 예상 외로 굉장히 심각한 문제이다. 멀티스레드에서의 '데드락'하고 다를 바가 없다! 서로 뭔가 꼬여서 끝이 안 난다는 점, 잡아 내기가 극도로 어렵다는 점이 공통점이다.
성능을 더 희생하고라도 메모리 leak 문제를 완전히 다른 방식으로 접근한 전용 garbage collector가 괜히 등장한 게 아니었겠다 싶다.

가비지 컬렉터라고 해서 무슨 용 빼는 재주가 있는 건 아니다. 기본적으로는 당장 접근 가능한 메모리로부터 출발해서 그 메모리로부터 추가로 접근 가능한 메모리 블록을 줄줄이 순회하여 표시를 한 뒤, 표시가 없는 메모리를 죄다 해제한다는 아이디어를 기반으로 동작한다. 동적으로 할당받은 메모리 내부에 또 동적 할당 메모리의 포인터가 있고, 그게 또 이상하게 얽히고 배배 꼬인 걸 어떻게 일일이 다 추적하는지 더 구체적인 방법은 잘 모르겠지만.

어찌 보면 단순무식하다. 주인 없이 주차장에 장기간 방치되어 있는 폐자전거들을 일괄 처분하기 위해 모든 자전거에 리본을 달아 놓은 뒤, 일정 날짜가 지나도록 리본이 제거되지 않은 자전거를 갖다 버리는 것과 개념적으로 비슷하다! 혹은 기숙사의 공용 냉장고에서 주인에게로 접근(?)이 안 되는 장기 방치 식품을 주기적으로 제거하는 것과도 비슷한 맥락이다. 단지 좀 더 성능을 올리기 위해, 메모리 블록들을 생존 주기별로 분류를 해서 짬이 덜 찬 메모리가 금방 또 해제될 가능성이 높으므로 거기부터 살펴보는 식의 관리만 하는 정도이다. 자바, .NET의 가상 머신들도 이런 정책을 사용한다.

이건 즉각 즉각 자원이 회수되는 게 아니며, 리얼타임 시스템에서는 적용을 재고해야 할 정도로 시공간 오버헤드도 크다. 그러나 한번 수집이 벌어질 때 랙이 있다는 말이지, 매 대입 때마다 시도 때도 없이 카운터 값을 변화시키고 그때 스레드 동기화까지 해야 하는 레퍼런스 카운팅도 성능면의 약점은 상황에 따라 피장파장일 수 있다.

언어 차원에서 이런 가비지 컬렉터가 제공되어서 delete 연산자와 소멸자 자체가 존재하지 않는 언어가 요즘 추세이다. 자바나 C#처럼. 하지만 메모리는 그렇게 자동으로 수집되지만, 파일이나 다른 리소스 핸들은 여전히 수동으로 해제를 해야 할 텐데 무작정 소멸자가 없어도 괜찮은지는 잘 모르겠다. 본인은 그런 언어로 대규모 프로그램을 작성한 경험이 없다. C++ 이외의 언어에서는 RAII 개념이 아예 존재하지 않는 건지?

Posted by 사무엘

2015/09/20 08:28 2015/09/20 08:28
, ,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1140

찰리 채플린 이야기 외

"어린 시절, 어머니가 무대 가수로 일하다 목이 쉬어서 삑사리가 나서 청중들로부터 막 야유를 받고 있었는데.. 그때 자기가 어머니를 대신해서 천부적인 개인기를 즉석에서 선보여서 '브라보!' 동전세례와 환호를 받았더라.." 본인은 찰리 채플린에 대해서 이런 얘기를 아주 어렸을 때 읽은 적이 있다.

그것 말고 본인이 더 알고 있는 건 그 특유의 히틀러 수염 + 중년 정장 복장의 광대 같아 보이기도 하는 개그 캐릭터, 일명 Little Tramp이다. 그리고 모던 타임즈라는 풍자 영화를 만들어서 연기한 것 정도만이 전부였다.

사용자 삽입 이미지
하지만 채플린은 모던 타임즈 이전부터 그야말로 리즈 시절을 누린 대단한 사람이었다. 그야말로 영화라는 매체의 초창기 역사를 함께한 산 증인이다.

채플린이라 하면 일단 무성 영화 시절의 인상이 아주 짙지만, 그는 나중에 유성 영화와 컬러까지 다 경험하긴 했다. 애니메이션과 음악만 있는 건 요즘으로 치면 플래시 무비 같은 느낌도 든다. 그 시절엔 화면 전환이나 글자 자막을 전부 아날로그 방식으로 어렵게 넣어야 했겠지만.
유튜브에 굴러다니는 영화 몇 편을 보니 저때 그 사람이 추구한 개그 코드가 이런 식이구나 하는 건 대충 알겠다. 산업 혁명의 원조 국가 출신답게 문명 사회에 대한 풍자가 많다. 밥을 떠먹여 주는 기계는 그 시절에 그런 생각을 했다는 게 정말 시대를 앞서갔다 싶다.

그리고 광대 연기만 한 게 아니라 각본 쓰고 연출을 하고 음악까지 혼자 다 작곡했다는 건 보통일이 아니다.
대사가 없기 때문에 시종일관 BGM이 차지하는 비중이 훨씬 더 높던 무성 시절부터 말이다. 연기뿐만 아니라 음악의 천재이기도 했다는 점도 다시 봐야겠다. 타의 추종을 불허하는 만능 예능인이 맞다.
"빠라라람? (똑딱똑딱) 빠라라람!" CF에서도 들은 적이 있는 음향이었는데 이것도 원조는 채플린 영화였구나.

저 사람 콧수염 모양이 아무래도 히틀러를 닮았다고 생각했는데, 의도한 건 아니었겠지만 실제로 닮은 게 맞았다. 채플린은 히틀러를 희화한 영화를 한두 차례 만들어서 히틀러 연기를 했다. 히틀러 당사자 역시 처음엔 자기를 풍자한 영화를 '재미있게' 봤다고 하지만, 1940년작 <위대한 독재자>는 풍자의 도가 지나쳤는지 나치 독일에서 국내 수입과 상영을 금지당했다고 한다. 참고로 채플린과 히틀러는 나이가 완전 동갑인 동시대 인물이었다. 둘 다 1889년 4월생이고 생일도 나흘밖에 차이가 안 남.

아인슈타인을 백발의 혀 쑥 내미는 얼굴만 보다가 젊었을 때 모습을 보면 적응을 못 하듯, 채플린도 일명 Little Tramp 코디인 중년 신사 연기 모습만이 너무 짙게 각인되어 있는지라, 젊었을 때나 말년 모습을 보면 적응이 안 된다.
채플린은 89세의 나이로 천수를 누린 뒤, 자던 중에 타계했다. 죽는 과정이 아주 이상적이었다.

다음은 그 밖의 trivia들.

1. 찰리 채플린은 가난하고 못 사는 집안 출신이었고 작품 중에 사회 풍자적인 메시지를 종종 담다 보니, 정치적 소신은 아무래도 성장보다 분배를 좋아하고 노동자를 편드는 쪽에 가까웠다. 그 자체가 문제가 있거나 잘못됐다는 뜻은 아니지만, 일련의 행적으로 인해 그는 그 살벌하던 냉전 시기에 일부 국가와 높으신 분들 계층으로부터는 좀 빨갱이 취급을 받았다. 한때 미국 입국을 금지당하기도 했을 정도이며, 한국에 채플린의 작품이 생각보다 늦게 소개된 것도 이 때문이다.
하긴, 그 시절에 헬렌 켈러도 장애를 극복한 위인이기만 한 게 아니라 굉장한 좌파 성향의 사회 운동가였고, 심지어 피카소 화가도 비슷한 성향이었다.

2.
연예인들이 인기 관리에 대한 압박감과 공연 후의 허무함 때문에 멘탈에 대미지를 입으며 지내고 급기야 마약에 빠지고 자살까지 하는 것처럼.. 저 사람도 남을 웃기는 직업과는 정반대로 심한 우울증에 시달렸다고 한다.
그래서 이를 견디다 못해 하루는 정신과 의사에게서 상담을 받았는데.. 환자가 누군지 모르던 의사는 그에게 이런 권고를 했다.
"찰리 채플린이 나오는 영화를 몇 편 좀 보시죠? 그러면 마음이 즐거워지고 증세가 나아질 겁니다~ ^^"

이런 비슷한 사례가 또 떠오르는 게 있다.
우리나라에 정 근모 박사는 핵 물리학자 출신으로 전 과학기술처 장관, 호서대 총장 등을 역임한 분이다. 학창 시절에는 경기고를 4개월만 다니다가 그냥 고졸 검정고시 + 월반을 해서 서울대 문리과대학에 차석으로 입학해 들어갔다.

하지만 아무리 머리가 좋아도 절대적인 학업 축적량이 부족하니, 수학· 과학만 잘하지 영어까지 바로 따라갈 수는 없었다. 신입생을 대상으로 한 교양 영어 시간 때 교수/강사의 질문에 대답을 못 해서 쩔쩔맸다. 그러자 그 선생은 정 군에게 이렇게 핀잔을 줬다.
"아니 명색이 서울대를 들어왔다는 학생이 이것도 모르냐? 여기에는 고등학교를 4개월만 다니다가 월반해 들어온 천재도 있는데!"
이에 주변의 학생들은 다 빵터졌다고 한다..;; (정 근모 박사 자서전에 언급되어 있는 일화)

3.
옛날에 내 동심을 자극하던 '찰리' 캐릭터로는 찰리 채플린 말고 만화 주인공인 찰리 브라운도 있었다. 만화의 원제가 <피너츠>였고 이 만화는 4컷 형태로 생각보다 오래 최근까지 연재되었다는 것은 작가가 작고하고 나서 한참 뒤에야 알게 됐다. 연재 기간은 1950년부터 2000년 진짜 딱 반세기에 달한다.

공교롭게도 우리나라에서 비슷하게 그 정도로 오래 연재된 4컷 만화는 <고바우 영감>이다. 이것도 주간지 시절까지 포함하면 딱 1950-2000이다.
뭐, 채플린과 직접적인 관계는 없지만 그래도 얘도 20세기 추억의 만화물이고 연재 기간이 채플린이 살아 있던 기간까지 포함하고 있으니 같이 연상이 될 만도 해 보인다.

Posted by 사무엘

2015/09/17 08:33 2015/09/17 08:33
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1139

철도 계시와 비유

1.
먼저 성경 말씀 패러디부터 좀 소개하겠다. 난 철도의 역사가 드디어 욥기 장면과도 오버랩되는 경지에 이르렀다.

"내가 서울-부산간의 땅에 철길을 놓을 때에 네가 어디 있었느냐? 네게 명철이 있거든 밝히 고하라.
누가 그것들의 궤간을 정하였는지 네가 아느냐? 누가 선로 위에 열차를 맞춰 놓았느냐?
그 차량의 대차를 어디에 고정하였느냐? 혹은 그것의 동력 기관을 누가 놓았느냐?
어느 때에 새벽별들이 함께 노래하고 하나님의 모든 아들들이 기뻐 소리를 질렀느냐?" (욥 38:4-7 패러디)

"이제 내가 너를 만들 때 함께 만든 특대형 디젤 전기 기관차를 보라. 그가 소처럼 기름을 먹느니라.
이제 보라, 그의 기력은 엔진에 있고 그의 힘은 발전기와 연결된 전동기에 있느니라.
그가 자기 바퀴를 백향목같이 움직이며 동력 전환 계통의 부품들은 서로 얽혀 있고
그의 대차는 강한 놋 덩이 같으며 그의 차축은 쇠막대기 같으니라.
그는 하나님의 철길들 중에서 으뜸이거니와 그를 만든 이가 자신의 연장을 그에게 가까이 댈 수 있느니라." (욥 40:15-19 패러디)


베헤못 빙고.
사실, 힘 자체는 전기 기관차가 더 좋지만 소리와 포스가 더 웅장한 건 디젤 전기 기관차여서.. ^^
욥이 그 당시에 무슨 총연장 몇 km에 차량이 몇 량 있는 사철을 소유하고 있는 회사 사장이었을 것 같은 생각이 든다.

2.
5월에는 어린이날과 어버이날이 나란히 있는데.. 그때 본인은 윌리엄 워즈워쓰의 유명한 시 <무지개>가 문득 떠올랐다. 본인은 아주 오래 전에 접했지만 "아이는 어른의 아버지"라는 역설법 싯구가 워낙 강렬해서 내 기억에도 여전히 남아 있다. "이것은 소리 없는 아우성"처럼.
아이와 어른을 대조한 다른 유명한 구절은 성경에서 고전 13:11인데, 거기서는 어른이 된 뒤에 유치하고 초딩스러운 일을 버렸다는 심상이어서 낭만주의 시와는 분위기가 영 다르다.

My heart leaps up when I behold
A rainbow in the sky:
So was it when my life began;
So is it now I am a man;
So be it when I shall grow old,
Or let me die!
The Child is father of the Man;
And I could wish my days to be
Bound each to each by natural piety.


첫 행이 무척 공감이 갔다. 나는 when I behold a rainbow in the sky가 아니라 when I listen to Looking for You일 때 my heart leaps up이다. 과거에도 그러했고 지금도 그러하며 앞으로도 영원무궁토록 그러하리라! 그리고 자연의 경건함이 아니라 철도의 경건함 속에서 매일 매일 살고 싶다.

아니, 시의 제목 자체를 레인보우가 아니라 레일웨이라고 바꿔도 될 것 같다. 소리가 비슷하다!
예전에 3· 1 운동 관련 글을 읽으면서 천도교를 보면서도 철도교를 연상한 적이 있었다. rain과 rail도 역시 ㄴ과 ㄹ 차이이다!

3.

"참고로 카지노의 카페트와 조명들은 전부다 심리학적으로 매우 신경써서 만든 것들인데, 들어서자마자 이상하게 두군거리고 슬롯머신을 한번쯤을 돌려봐야할것 같은 느낌이 들도록 (...) 구성되어 있다. 특히 슬롯머신처럼 단순하게 생긴 카지노 장비들(...)의 효과음은 돈 짤랑거리는 소리 등 도박욕구(...)를 자극하기 위해 정말 공들인 사운드 이펙트를 자랑한다."
* 나무(엔하)위키의 '카지노' 설명 본문 중.


그렇다. 새마을호 역시 카페트와 조명, 안내 방송과 음향들은 전부 심리학적으로 매우 신경써서 만들어져 있었다. 들어서자마자 이상하게 두근거리고 단순 이동이 아니라 뭔가 철도라는 악기를 이용한 문화 예술 공연 같은 느낌이 들도록 구성되어 있다. 기내지 레일로드, 고급스러운 간접 조명과 독서등, 두툼한 좌석에다 Looking for you 음악은.. 그야말로 승객을 뼛속까지 철덕으로 세뇌시키고 철도의 노예로 만들기 위한 정말 공들인 사운드 이펙트였다.

도박은 왜 하는지는 모르겠지만 어쨌든 만약 유흥 차원에서 한다면 내 돈을 잃거나 뺏긴 게 아니라, 그냥 게임 요금에 자리값/서비스료를 지불했다는 생각으로 하는 게 그나마 바람직하다.
비슷한 맥락으로 철도를 이용하는 것, 더 구체적으로 새마을호를 타는 것은 단순히 몸을 이동하는 데 드는 교통비 운임을 지불한 게 아니라 샘솟는 평안과 기쁨, 행복을 구입했다는 생각으로 접근하는 게 바람직하다. 아이폰만 감성 마케팅을 한 게 아니었다.

"네 소원이 무엇이냐?" 하고 하나님이 물으시면, 나는 서슴지 않고
"내 소원은 Looking for you를 듣는 것이오" 하고, 대답할 것이다.
"그 다음 소원은 무엇이냐?" 하면, 나는 또
"새마을호 객실에서 흘러나오는 Looking for you를 듣는 것이오" 할 것이요, 또
"그 다음 소원이 무엇이냐?" 하는 셋째번 물음에도, 나는 더욱 소리를 높여서
"나의 소원은 경부선 새마을호 전후동력형 디젤 동차를 타고 열차가 시종점에서 도달할 때 연주되는 Looking for you를 객실에서 듣는 것이오"라고 대답할 것이다.


4.
전철을 타서 좌석에 앉으면 가방이나 도시락 같은 소지품을 어디에다 놔 둘지가 고민되는 때가 생긴다.
그런데 그런 물건을 두는 위치는 전기 철도 차량의 전력 공급원 내지 집전 방식에 대한 좋은 예표라는 생각이 문득 들었다. 제각기 장단점이 있다.

  • 머리 위의 선반에다 두는 것은 가공전차선+팬터그래프 집전 방식에 해당한다. 제일 편하긴 하지만 깜빡 잊고 짐을 놔 두고 내리기 쉽다.
  • 바닥의 양 발 사이에다 두는 것은 바로 제3궤조 집전 방식이다. 놔두고 내릴 염려는 적지만 발을 편하게 두기 어렵다.
  • 그냥 손에 쥐고 있거나 백팩에 넣은 채로 있는 것은 배터리 또는 기름+전기 하이브리드 방식이다. 놔 두고 내릴 가능성은 0이지만 승차감이 제일 안 좋다.

선반에 물건을 적재하는 건, C++ 프로그램으로 치면 '전동차 탑승'이라는 함수가 실행되고 스택에 C++ 개체를 하나 선언하는 것과 같다고 생각한다.
전동차에서 내리는 것은 함수 실행이 종료되고 그 변수가 scope을 벗어나는 것과 같다. 그러니 변수는 스택에서 소멸되고 해당 개체의 소멸자 함수가 실행되어야 한다. 하지만 현실에서는 heap도 아니고 스택에 선언된 개체에 대해 메모리 leak이 발생하기도 하는 것 같다.

난 옛날에 논산 훈련소에 있을 때 침상형 생활관에서 바닥 위의 빨랫줄을 보고도 전차선을 떠올렸다. 국방색은 갈록색을 빼닮은 듯이 비슷해서 서울 지하철 7호선의 예표이고, 긴 행렬이 우측통행을 하는 것 역시 지하철의 예표이다.

성경에는 질질 끌리는 긴 옷자락(사 6:1) 내지 수행원 행렬(왕상 10:2)조차도 train이라는 단어로 표현했으니 저렇게 생각을 하는 건 성경적인 근거가 충분하다.
자나깨나 철도를 생각하는 것은 가까운 것부터, 일상생활을 소재로 삼으면 얼마든지 가능하다.

5.
난 솔직히 내가 아니어도 전세계의 날고 기는 천재들이 알아서 다 발전시켜 줄 컴퓨터 하드웨어/소프트웨어 신기술에는 별 관심이 없다.
기술은 어지간한 건 다 상향평준화해 버리고 심지어 오픈소스로 풀리기까지 한다.
내가 안목이 좁은 건지.. IT 업계는 어지간한 아이템, 아이디어는 나올 거 다 나오고 게임 말고는 더 할 게 없는 레드오션이 돼 버린 지 오래인데, 미국은 아직도 뭘 더 만들 게 있어서 컴퓨터 관련 학과가 인기가 많고 코딩을 배우네 창업을 하네 하는 분위기인지 궁금하다. 아이템이 계속 있다면 참 다행이긴 한데.

나는 컴퓨터보다는 우리나라 철도를 위해 일하고 싶다.
나를 죄에서 구원한 예수님의 은혜에 감사하고 감격해서 내 삶을 주께 드리고 내 몸을 살아 있는 희생물로 드리듯이,
객실에서 Looking for you를 틀어서 잠자던 내 야성과 똘끼를 깨우고, 감성을 흥분시키고 한편으로 촉촉히 적시고, 한편으로는 무한한 행복과 감동과 평안과 희락을 준 철도를 위해, 철도를 전하는 일에 내 일생을 바치고 싶다.

"철도 안에서의 한 날이 세상 다른 곳에서의 천 날보다 나으니이다. 내가 장막들에 거하는 것보다 차라리 철도의 집(= 철도역) 문지기가 되겠사오니" (시 84:10 패러디) 가 강렬하게 떠올랐다.

  • 피스톤 왕복 엔진 (자동차. 휘발유와 디젤 모두)
  • 제트 엔진 (비행기. 터보 제트, 터보 팬)
  • 로켓 엔진 (우주 발사체)
  • 전기 모터 (전동차, 전기 철도)

의 내부 구조와 원리, 제원을 측정하는 규격과 물리적 특성, 구동음 등등을 전부 마스터 하고 싶다. 난 정작 대학 졸업할 때까지 기계· 전자 같은 건 완전 담을 쌓고 살았다만..;;

아 뭐 지금처럼 국어정보학 쪽으로 가서 언어를 공부하는 프로그래머가 됐고 한글 입력기와 글꼴 쪽으로 논문 쓰게 된 것도 충분히 의미가 있고 무엇보다도 창의적인 일이긴 하나,
내가 새마을호에서 Looking for you를 몇 년 좀 일찍 들었으면 진로가 딴판으로 바뀌었을 가능성이 아주 높다.
철도 만세 만만세. 새마을호여 영원하라.
자동차나 비행기 쪽에 관심이 가는 것도 언제까지나 철도와의 비교 차원에서 하는 거다.

사용자 삽입 이미지
얼마 전 학교 안 대졸자 취업 박람회(?)에서 본 코레일 부스..;;

Posted by 사무엘

2015/09/14 08:34 2015/09/14 08:34
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1138

KTX 개통과 운행 내력 외

한반도에 KTX라는 이름의 고속철이 개통하여 상업 운행을 시작한 지 어언 10년이 넘었다.
개통한 지 무려 반세기가 넘은 일본의 신칸센에 비할 바는 못 되겠지만, 그래도 KTX도 개통 내력이 은근히 복잡해지고 있으니 한번쯤 정리할 필요를 느낀다.

2004. 4. 1. [경부 1차 개통]
- 경부선: 서울-부산 (고속선은 대전-광명, 대구-옥천만)
- 호남선: 기존선의 복선전철화. 용산-목포 (대전 이남엔 고유한 고속선 구간 없음)
- KTX 개통과 함께 (1) 서울교외선에 정규 열차 운행이 중단됨. (2) 통일호 폐지, (3) 경춘선 무궁화호 폐지.

* 이 일대 시기의 서울/철도 소사를 참고 차원에서 열거하면 다음과 같다.:
- 청계고가의 철거와 청계천 복원 사업이 시행됨.
- KTX 개통 약간 전에 서울역 민자역사가 개관함.
- KTX 개통 후 얼마 안 있어 경부선은 서울 역, 호남/전라/장항선은 용산 역으로 역의 역할이 완전히 이원화됨.
- 2004년 7월, 서울 수도권의 버스· 지하철 통합 환승 제도가 시행됨.
- 2005년부터 철도청 폐지, 한국철도공사(코레일) 출범.

2007.
- 경부선: 대전-대구 사이만 기존선으로 달리면서 김천과 구미에 정차하는 KTX 일부 운행

2010. 11. 1. [경부 2차 개통]
- 경부선: 대구-신경주-울산-부산 사이의 고속신선 신규 개통. 기개통 구간엔 오송과 김천구미 역이 추가 영업 시작함
김천· 구미 KTX는 폐지. 그 대신 수원· 영등포 정차 KTX 생김

2010. 12. 15.
- 경전선: 기존선의 복선전철화. 대구 이남으로 창원, 마산으로 가는 노선. 수요 폭발이었다고 함.

2011. 10. 5.
- 전라선: 기존선의 복선전철화. 익산 이남으로 여수엑스포 행

2012.
- 드디어 KTX-산천 차량 투입

2014. 6. 30.
- 일부 열차가 인천 공항까지 직결 운행 시작

2015. 4. 2. [호남 1차 개통]
- 호남선: 고속신선 신규 개통. 익산· 정읍· 광주송정을 경유하며 공주 역 추가 영업 시작. 저 역들을 제외한 호남선 기존선 역들은 KTX 취급이 폐지됨(광주, 김제 등).
- 동해남부선(앞으로 동해중부선과 연결되어 동해선이 될 예정): 포항 직결 운행 시작

2015. 8. 1.
- 대전과 (동)대구는 기존선과 인접하는 도심 구간까지도 기존선 연결선이 아니라 고속선이 깔림으로써.. 운행 계통이 일반열차와는 완전히 분리되는 복을 누리게 됐다.

요약하면:
고속신선은 오송에서 분기하는 경부선과 호남선 축으로 깔려 있고, KTX 운행 노선은 거기에다 호남 분기(전라선), 경부 분기(경전선, 동해남부선), 그리고 서울 이북으로 공항선이 추가적인 겉저리로 붙은 형태이다.
차량은 아무래도 1세대 떼제베 차량과 2010년대 이후의 2세대 산천 차량 정도로 나뉜다. 혹시나 해서 말하는데 KTX-산천은 HSR-350의 기술로부터 만들어진 열차이긴 하지만 산천 자체가 HSR-350을 그대로 양산한 건 아니다.

더 먼 미래엔:
(1) 호남 고속철이 광주 이남으로 2차 구간이 마저 개통할 것이며, (2) 수서 발 수도권 고속철과 (3) 강릉 방면 동서 고속철이 남아 있다.
“희망을 싣고 번영을 싣고 뻗어가는 철도 따라 커 가는 나라”대로 될지어다. 아멘. (철도의 노래 가사 중)

* 고속철의 이름: 차량이냐 선로냐

고속철 보유국으로서 프랑스와 일본을 비교해 보면 좋은 차이를 발견할 수 있다.
프랑스 떼제베(TGV)는 '매우 빠른 열차'라는 뜻이며 차량 중심으로 작명됐다. 한국의 KTX도 이니셜을 보면 알 수 있듯, 차량 중심이다. 프랑스는 차량 기술에 자부심이 많은지 그 뒤에도 증속 경쟁을 제일 열성적으로 진행해 왔다. 2007년엔 자기 부상 열차가 아닌 재래식 바퀴식 열차로 무려 시속 574km라는 사기적인 시운전을 성공하기도 했다.

그러나 일본 신칸센은 '새로운 간선 철도'라는 뜻으로 의외로 차량이 아닌 선로 중심으로 작명됐다. 본인은 철덕으로서 이 차이가 매우 신기하게 와 닿는다. 그들의 입장에서는 차량보다도, 기존 협궤가 아닌 표준궤로 고속철 신선을 깔았다는 사실이 더 중요하게 와 닿았던 것이다. 1964년에 첫 운행을 한 신칸센 0계 전동차는 떼제베 같은 독자적인 디자인도 아니고 걍 자기네 옛날 전투기와 비슷한 투박한 외형이었다.

새로운 교통수단을 만들 때는 성능뿐만이 아니라 안전도 굉장히 높은 가중치로 고려 대상이 되며, 고속철을 개발하는 과정에서도 마찬가지였다. 시속 200km를 넘게 증속을 하는 기술보다도, 그렇게 고속 주행 중에 장애물이 나타나고 돌발상황이 발생했을 때 제동 거리를 얼마를 넘지 않고 비상 정지를 도대체 어떻게 할지가 더 심각한 고민거리로 대두되었다. 엔지니어들이 별별 아이디어를 다 짜내 봤지만 뾰족한 수가 없었다.

그래서 그들은 결국은 "싸우지 않고 이기는 싸움이 가장 좋은 싸움이다"라는 결론을 도출하게 됐다.
"가장 좋은 인디언은 죽은 인디언이다." (They're only good when dead 포카혼타스 Savages 대사;; )처럼.
애초에 비상 정지를 할 일이 없게 만들자는 것이다.
건널목 따위는 전혀 안 만들고 모든 구간을 무조건 입체교차로 만들고, 선로에는 아무도 접근을 못 하게 겹겹이 벽을 두르면서 일본의 경부선뻘 되는 도카이도선을 표준궤 고속선으로 새로 만들었다. 1960년대에 벌써 그런 생각을 한 것이다. 그래서 이름이 선로를 내세운 '신칸센'이 됐고 이것이 일본 고속철의 선로, 열차, 시스템의 명칭이 됐다.

이런 일본과 프랑스의 고속철 역사를 살펴보면, 철도라는 걸 처음 만들 때는 당연한 말이지만 차량보다 선로가 먼저라는 원칙을 확인할 수있다.

우리나라도 1992년에 대전-천안간의 경부고속선 본선 겸 시험선 구간을 먼저 착공한 뒤, 차량의 선정 계약은 더 나중인 1994년에 맺었다.

시속 200km를 넘는 장거리 간선 철도의 건설 자체는 1964년의 일본 신칸센이 세계 최초이다. 하지만 그 뒤의 추가적인 속도 경쟁은 후발 주자인 프랑스 떼제베가 앞섰다. 가령, 시속 260km대의 상업 운전은 1981년에 떼제베가 세계 최초로 달성했고 신칸센은 그로부터 10년 가까이 뒤인 1992년에야 300계 전동차가 도입되면서 그 속도를 따라잡았다. (300계는 TGV-R, ICE와 더불어 우리나라 고속철의 차량 입찰 후보이기도 했다.)

우리나라는? 잘 알다시피 1984년 8월에 경부선 천안-서정리 구간에서 겨우 시속 150km 시운전 성공.. 이러던 지경이었다. 그러니 국제적인 안목이 있는 철도 공학자와 경영자들이 통탄할 법도 했다. 1980년대, 전국 곳곳에 포장 도로가 깔리고 마이카 시대가 코앞인데 이래 가지고는 "한국 철도엔 답이 없다"라는 게 뻔히 보였다. 철도가 경쟁력을 확보하는 길은 선택과 집중, 그리고 증속을 통해 많이 빠르게 실어 나르는 "회전율 향상"뿐이었던 것이다.

우리나라도 1985년 11월에 서울-부산 4시간 10분이 달성된 후, 지속적인 레일 장대화와 선형 개량, 기관차 출력 증대로 서울-부산을 1980년대 말까지 3시간 반까지 단축시키려는 계획은 잡혀 있었다. 그러나 그런 미봉책만으로는 한계가 있다는 것을 느끼고 1992년에 드디어 인천 공항의 건설과 더불어 경부 고속철 사업을 추진하게 되었다. 그 뒤의 역사는 여러분이 다 아시는 그대로이다.

우리나라에서 떼제베 대신 신칸센이 낙찰됐다면, 철덕의 입장에서 전망해 보자면 다른 건 몰라도 떼제베보다 폭이 더 넉넉하고 애초부터 역방향 좌석이 없는 열차가 도입됐을 가능성이 높다. 신칸센은 2-3배열 가축수송 열차가(한 줄에 좌석이 5개!) 있을 정도로 같은 표준궤에서도 뚱뚱한 덩치이기 때문이다. 자기네 자위대 전차의 부품도 제대로 수송을 못 할 정도로 빼짝 마른 협궤에 이골이 난지라, 신칸센은 이왕 표준궤로 까는 김에 열차의 폭까지 최대한 더 키운 듯. 하지만 지나친 고자세 때문에 입찰 후보들 중에서는 신칸센이 가장 먼저 탈락했다.

Posted by 사무엘

2015/09/11 08:32 2015/09/11 08:32
, , , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1137

1. 하라 vs 하지 말라

세상의 법이나 규칙 같은 것은 사람의 행동을 통제하고 질서를 유지하는 것이 목적이기 때문에 아무래도 '-하라'(do)보다는 '-하지 말라'(don't) 위주로 만들어져 있을 수밖에 없다.
시험 문제야 학습자의 심리적인 영향을 감안하여, "-틀린 예는?, -아닌 것은? -없는 것은?" 같은 부정적인 문제는 일정 비율 이상 만들지 말라고 하는 가이드라인이 있다. 그러나 법률은 아무래도 죄를 다루고 사람의 재산과 생명을 다루다 보니 심각하고 부정적인 말이 많다.

자동차나 총기, 전기톱, 독극물 같은 위험한 물건의 취급 설명서는 온갖 오· 남· 악용 상황을 금지하는 주의· 경고문으로 가득하다.
복싱은 룰의 태반이 금지 반칙 조건의 리스트라고 한다. 그 덕분에 위험한 격투기이면서도 신사의 스포츠로 품위가 유지되는 듯하다.

프로레슬링에서는 그 이름도 유명한 "Please, don't try this"(제발 따라하지 마세요!)가 관객을 대상으로 하는 대표적인 don't 규칙이다. -_-;; 옛날에는 at home이라는 단서가 붙어 있었다. 저건 다~ 전문가들이 지극히 통제된 환경에서 각본 다 짜서 하는 액션이고, 그러고도 후유증이 쌓이고 가끔은 안전사고도 나니... 일반인이 현실에서 따라할 생각이라고는 절대로 하지 말라는 뜻으로 home을 붙인 것이었다. 그런데 "응? 집이 아니면 학교나 도장에서는 해도 된다는 얘기네?" 이렇게 이상하게 받아들여서 사고 치는 친구들이 너무 많았던지라 at home은 나중에 빠지게 됐다.

don't에 비해 do 법은 "납세나 병역 따위의 의무를 수행하라" 말고는 흔치 않다.
세상법에서는 어린 자녀를 제대로 먹이고 재우고 치료하지 않은 것 정도가 꽤 적극적인 do 법의 위배이다. 이것 말고도 선한 사마리아인 법도 만드네 마네 하는 말이 있지만, do 법은 아무래도 마음의 동기를 측정 가능치 않다 보니 적용이 현실적으로 쉽지 않다.
아까 말이 나온 자녀 부양도 do 법의 위배가 걸리는 것보다는 자녀를 학대하지 말라는 don't 법의 위배까지 간 뒤에야 적발되고 처벌되는 경우가 더 많다.

성경에도 물론 don't 법이 적지 않다. 특히 최초의 법인 "선악과를 따먹지 말라"도 don't 법이었다. 그러나 그것 말고 do 법도 의외로 좀 있다.
십계명에서 하나님 계명과 인간 계명의 중간쯤에 속하는 것으로 여겨지는 제4와 제5는 don't가 아니라 do 계명이다. (안식일을 지켜라, 부모를 공경하라)

부모에게는 단순히 패륜을 저지르지 '않는 것'만이 다가 아니라 그 이상의 적극적인 예우를 해 줘야 하기 때문이다. don't는 그건 너무 당연한 거고, do까지 해야만 죄가 성립되지 않게 된다.
또한 안식일은 유대인과 하나님 사이의 표적으로서, 일정 주기로 강제로 쉬는 것도 당장 손해를 감수하는 믿음이 필요한 일이었다. (안식일에 전쟁이 벌어지지 않기를.. 6·25나 진주만 폭격이나 다 일요일에 벌어졌다!) "안식일에 일을 하지 말라"가 아니라 "안식일을 거룩히 지키라"라고 돼 있으니 don't가 아닌 do 형태라고 본다.

구약 모세오경을 보면, 신성모독을 저지른 어느 혼혈아만 공개처형(레 24:10-23)을 한 게 아니라, 안식일에 일을 하다 걸린 사람을 처형하는 장면도 나온다(민 15:32-36). 싸이코패스 연쇄살인범 흉악범도 아니고 겨우(?) 그런 죄를 저지른 사람까지 중범죄로 간주하여 죽였던 것이다.

안식일이야 신약 시대에 직접적으로 적용이 안 되는 것이니 논외로 하더라도, 성경엔 믿지 않은 것, 기도를 게을리 한 것, 복음 안 전하는 것 등 더 적극적으로 do 법을 명시하고 있다. 종교적으로는 하지 않는 것이 죄인 것도 많이 있는 셈이다.

특히 오늘날 성경이 말하는 "하나님을 거짓말쟁이로 만드는 죄, 지옥 가는 유일한 죄"는 살인· 간음· 사기처럼 하지 말라는 짓을 저지른 죄가 아니라, 하라는 것을 안 한 죄이다!
마치 출애굽 직전에 문설주에 양의 피를 반드시 발라 놓아야 한다거나, 놋뱀을 반드시 바라봐야만 살 수 있다거나 한 거처럼. 대단히 의미심장한 일이다.

2. 법을 만드신 분, 법 위에 계신 분

성경에는 신약에서 구약 성경을 인용한 예가 아주 많다. 이것은 성경과 성경간의 연계 효과를 강화하고 내용을 교차검증하는 매우 긍정적인 효과가 있다. 가령, 여느 무신론자 개독안티가 아니라 예수 믿고 교회도 댕긴다는 사람이 창세기 1~3장은 설화일 뿐이라고 생각한다면 바로 이렇게 치고 들어가면 된다. "야, 니가 믿는 그 예수님도 아벨이 실존 인물이고 의인이라고(마 23:35, 눅 11:51) 아주 진지하게 인증을 했구만 그럼 예수님도 팩트가 아닌 거짓을 믿은 거냐?" 이런 식이다.

어디 그 뿐이랴? 여타 성경 인용의 정확도는 변개된 성경과 그렇지 않은 성경을 판단하는 잣대 역할도 한다. 막 1:2의 대언자들 vs 이사야가 대표적인 예 중 하나이다.
그런데, 성경의 용례를 찾아보면, 예전 성경을 언제나 문자 그대로 곧이곧대로 정확하게 인용하지는 않은 예도 많다.

“의인은 자기 믿음으로 살리라”(합 2:4)는 신약에서는 ‘자기’가 빠지고 의인은 그냥 “믿음으로 살리라”(롬 1:17, 갈 3:11, 히 10:38)로 바뀐 걸로 유명하다. 그것도 무려 세 번이나 말이다. 이것 말고 또 다른 예로는 이 글을 참고하라.

왜 이런 일이 벌어지는 걸까?
예수님 역시 초림하셨을 때는 율법을 폐하러 온 게 아니라 완전하게 하러 오셨다고 말씀하셨다. 안식일 때 제자들이 곡식을 비벼 먹었는데, 이때 주변 율법주의자들과 키배를 하면서 하신 말씀이 “사람의 [아들]은 곧 안식일의 [주]니라” (마 12:8)였다. 이건 결국 안식일을 뭐 어찌 하셨다는 뜻이겠는가? 이 모든 사례들은 무엇을 의미하는 걸까?

어떤 법을 제정한 주체에게는 자신도 그 법을 지킴으로써 자신의 권위와 일관성을 유지해야 할 의무가 있는가 하면,
한편으로 그 기존 규칙을 초월하는 새로운 법을 제정할 수도 있고, 또 규칙 위에 예외를 둘 권리도 있다.
성경에는 다른 여러 사건들도 많지만 특히 에스더기가 그 두 사례를 잘 보여준다고 여겨진다.

결국은 하나님께는 두 적용을 자유롭게 할 권리가 있으며 우리는 신자로서 그 모든 판단(judgment)이 옳다고 믿는 것이다(시 119:75).
이 관계를 잘 생각해 봐야 예수님/사도들의 성경 인용은 필요에 따른 적절한 수정인 반면에, 이브와 사탄의 성경 인용은 변개라고 판단할 수 있을 것이다.
또한 킹 제임스 성경도 God forbid 같은 표현은 축자 번역이 아니라 동적 일치 의역이라는 식으로 딴지를 거는 시비에도 대처할 수 있을 것이다.

그러고 보니 어렸을 때 봤던 월트 디즈니 <알라딘>도 이 법의 권위와 관련된 비슷한 문제를 잘 다루고 있다. 그래서 처음에는 술탄이 자스민 공주에게
“법에 따르면 너는 네 다음 생일 때까지 반드시 왕자와 결혼해야만 한다구.” (The law says you must be married to a prince by your next birthday.)
라고 융통성 없게 말하지만, 나중에 결말부에서는 결국 이렇게 말하니까 말이다.

법을 고치겠다. 난 술탄(왕)이니까. 지금부터 공주는 자기가 적합하다고 생각하는 그 어떤 사람과도 결혼할 수 있다. (꼭 왕자가 아니어도)”
(물론, 사람이 완벽하지 않기 때문에 오락가락 이랬다 저랬다를 막으려고 현대의 민주주의 정치 체계에서는 입법과 행정을 분리하고 있다. “짐이 곧 법이다”를 제도적으로 가능하지 않게 막은 것이다.)

Posted by 사무엘

2015/09/08 08:36 2015/09/08 08:36
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1136

1.
하임 바이츠만. (Chaim Weizmann; 1874-1952)
우리나라의 초대 대통령이 문과 계열의 만렙 박사였다면, 현대 이스라엘의 초대 대통령은...;; 천재 과학자였다.
그리고 우리나라 초대 대통령이 미국을 끌어들여서 나라를 세웠다면, 저 사람은 영국을 끌어들여서 자기네 땅을 얻어 냈다. 서로 나이 차이도(1874 & 1875년생) 거의 안 나는 동시대 사람이다. 그러고 보니 윈스턴 처칠과도 동갑임.

사용자 삽입 이미지

하임 바이츠만은 1차 세계 대전 당시에 옥수수로부터 아세톤을 저렴하게 양산하는 기술을 개발하는 데 성공했다. 이게 전시 군수 물자인 탄약을 만드는 데 꼭 필요한 기술이었던지라 그는 이것 덕분에 완전 나라를 구한 영웅이 됐다.
영국 정부에서는 그의 노고를 치하하며 그에게 훈장을 주려 했다. 그때 그 사람이 말했다. "저는 돈과 명예는 필요 없습니다. 단지 우리 민족을 약속된 땅 팔레스타인으로 들어가서 살게 해 주세요." 성경에서 에스더가 아하수에로 왕에게 자기 동족을 구해 달라고 간청하는 장면이 떠오르지 않는가?

"우리 대영제국의 식민지 중엔 거기보다 더 넓고 좋은 땅도 얼마든지 있는데. 가령, 아프리카에 우간다 영토 일대는 어때?"라는 제안에도 그는 전혀 아랑곳하지 않았다.
"ㄴㄴ. 런던이 지금 같은 영국 수도가 되기도 전부터 예루살렘은 원래 우리 땅이었습니다. 부디 거기를 돌려 주십시오. 부탁입니다."

영국 내부에는 이스라엘의 회복을 믿는 크리스천들이 물론 있었으며, 이를 토대로 1차 세계 대전의 말에 1917년에 밸푸어 선언이 이뤄졌다. 우리나라 역사로 치면 2차 세계 대전 말기에 발효된 카이로 선언 및 포츠담 선언과 비슷하다. 일제로부터 조선의 독립이 그때 명시됐으니 말이다.

허나, 그렇다고 해서 유대인들의 귀환이 곧장 이뤄진 건 아니었다. 그로부터 수십 년 뒤, 유대인들이 몇백만 명씩이나 나치에 의해 처참하게 학살당하고 세계 질서가 확 바뀐 뒤에야 이스라엘이 세워질 수 있었다. 사람에겐 기본적으로 귀차니즘이 있는지라 박해를 안 받으면 잘 안 움직이니까.;;

어쨌거나 초대 대통령이 군인이나 외교관 같은 다른 직업이 아니라 과학자라니 참 멋있고 부럽다(우리나라는 박 근혜 대통령이 일단 전자공학과 출신이긴 하다만..). 바이츠만은 자기 실력을 민족의 독립과 건국을 위해 사용한 위인 애국자였다.

2.
이스라엘의 국가인 Hatikvah(희망)은 우리나라 교회에서는 우연의 일치인지 <밝은 빛을 따라서 앞만 향해 나가자>라는 희망적인(?) 내용의 찬송가 멜로디로 쓰인다. 하지만 쟤네들 국가 가사는... 나 같은 비유대인이 보기에도 인간적인 감정상 정말 구슬프고 찡하고, 나라 없는 백성의 한이 레알 서려 있는 게 느껴진다. 1절 가사를 대충 드라마틱하게 의역하면 이런 내용이다.

“내 심장은 동방을 향해, 시온을 향해 오늘도 꿈틀댄다.
우리는 결코 희망을 잃지 않으리.
약속의 땅에서 자유로운 내 조국을 세우는 날을 염원한 지가 어언 2천 년.
그곳은 시온 땅의 예루살렘이어라.”


이 글에서는 이스라엘이 팔레스타인 땅을 뺏었네 나쁜 깡패네 하는 얘기는 논하지 않을 것이므로 이 점을 양해 바란다. 원래 그런 분쟁이 얼마든지 안 생길 수 있었고 이스라엘은 합법적으로 땅을 받았고 팔레스타인 사람들에게 보상을 하는 것도 다 합의가 돼 있었는데 영국이 약속을 제대로 이행하지 않고 오해가 생기면서 내력이 복잡하게 배배 꼬인 게 있다. 그런 것까지 다 설명하기에는 시간과 지면이 부족하다.

아 그리고, 이스라엘도 사람 사는 곳이고, 모든 이스라엘 국민들이 자기네 국가를 좋아하는 건 아니다. 저런 노래가 너무 국뽕스럽다고 싫어하는 사람도 있다. 한국인 중에도 애국가 별로 안 좋아하는 사람이 있고, 일본인 중에도 기미가요가 너무 존재감 없다고 안 좋아하는 사람이 있는 것과 같은 이치이다.

3.
하나님이 보우하셨는지 유대인들이 참 똑똑하긴 했다. 바이츠만 말고 프리츠 하버(1868-1934)도 비슷한 시기를 살았던 천재 과학자이다. 그는 공기 중의 질소로부터 암모니아를 합성하는 기술을 개발하여 인공 질소 비료를 만들어 냈다. 햇볕을 이용해 사람을 죽이는 핵을 만드는 게 아니라 공기로부터 사람을 살리는 빵을 만드는 급의 엄청난 기적을 이뤘다. 기아 해소와 인류 복지에 결정적인 공헌을 한 그는 응당 노벨 상도 받았다.

사용자 삽입 이미지

허나 그는 바이츠만과는 달리 줄을 치명적으로 잘못 섰다. 그는 독실한 유대교 신자도, 시온주의자도 전혀 아니었다. 그리고 영국이 아닌 독일에 충성했다. 그것도 아주 열정적으로. 그래서 조국을 위해 사람을 살리는 발명만 한 게 아니라 독가스도 발명했다. 1차 세계 대전 때 전장에 처음으로 살포된 염소 가스부터 시작해, 유대인 아우슈비츠 수용소 시절의 치클론 B 독가스도 다 이 사람 혼자 또는 공동 연구로 만들어졌다.

그럼 그가 그 덕분에 독일로부터라도 인정받고 떵떵거리며 살았느냐 하면 그렇지도 않았다. 이용 가치는 있지만 굉장히 애매한 왕따 포지션이 되어서 타지에서 무척 쓸쓸한 최후를 맞이했다. 독일로부터는 나중에 나치 당이 집권하면서 "저런 더러운 생물(=유대인)을 고위 과학자 자리에 앉혀 둘 순 없다"라고 문전박대를 당했고, 영국 등 다른 나라로부터는 "저 자식은 머리는 비상하지만 정신이 완전 맛이 간 싸이코야."라고 단단히 찍혔다.

그래도 다행히 2차 세계 대전 이전에 일찍(1934년) 죽은 덕분에 히틀러와 엮이지는 않았으며, 홀로코스트의 희생자가 되거나 반대로 나치 출신의 전범 매드 사이언티스트로 전락하지는 않았다. 그러나 그가 관여한 발명품이 가까운 미래에 심지어 자기 동족을 학살하는 용도로까지 쓰인 것은 대단히 안타까운 역설이다. 그는 사람을 살린 엄청난 업적에도 불구하고 위인전에는 도저히 오를 수 없게 되었으며, 오늘날까지도 과학자의 연구 윤리를 논할 때 빠짐없이 거론되는 씁쓸한 사례가 되었다.

4.
이스라엘 건국 얘기가 나왔으니 우리나라의 건국도 다시 좀 복습하고 글을 맺겠다.
1948년 5월 10일에 우리나라에서 남쪽만 국회의원 총선거가 있었다.
그리고 14일에 이스라엘이 건국됐고, 같은 날 낮에 한반도에서는 북으로부터 대남 송전이 끊겼다.
그 달 말일인 31일엔 그 국회의원들을 바탕으로 제헌국회가 개최됐고, 당시 의장이던 이 승만의 요청으로 이 윤영 목사의 감사 기도가 이때 행해졌다.
이어 그 해 7월 17일엔 잘 알다시피 헌법이 제정되었고, 8월 15일 광복절에 맞춰서 약 3년간의 미군정이 끝나고 대한민국 정부가 수립되었다.

그러나 이보다 전인 1948년 3월에 이북에서는 이미 자기만의 국기와 국가도 다 정하고 분단은 기정사실이 된 상태로 북조선로동당 제2차 대회가 열리고 있었다. 악의 무리들은 서로 동무 동무 하면서 비판과 삿대질이나 일삼으면서 어떻게 백성들의 재산과 자유를 빼앗고 몽땅 착취하고, 서로 감시하고 통제하고 믿질 못하는 생지옥을 만들까, 어떻게 남조선까지 몽땅 집어 삼킬까 흉계를 꾸미고 있었다.

그 반면 우리나라 대한민국은 "하나님께서 오랜 시일 동안 이 민족의 고통과 호소를 들으시고 정의의 칼을 빼셔서 일제의 폭력을 굽히시고 ... 우리 민족의 염원을 들으심으로 이 기쁜 역사적 환희의 날을 우리에게 오게 하심을 감사합니다." 이렇게 시작되었다. 이것은 개인의 종교관을 떠나서 매우 다행이고 자랑스럽고 고마운 일이 아닐 수 없다.

Posted by 사무엘

2015/09/05 08:38 2015/09/05 08:38
, , , , ,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1135

Windows XP에서부터 내가 생성하는 exe 바이너리의 내부에 xml 문서 리소스 형태의 메타데이터를 집어넣는 게 필수 관행이 됐다.
가장 대표적인 용도는 (1) 내가 사용하는 시스템 DLL의 버전을 지정해서 로딩 방식을 시스템 디렉터리 말고 딴 곳으로 강제로 바꾸는 것이다.

이 방식으로 (1-1) 공용 컨트롤을 6.0 버전을 사용한다고 명시해야 각종 컨트롤에 XP의 새끈한 테마가 적용되어 나왔다. 테마 기능을 추가하는 과정에서 comctl32.dll이 XP 이전과 XP 이후 것은 하위 호환성이 없이 서로 단절됐기 때문이라 한다.
내 프로그램의 비주얼이 시대에 뒤떨어진 구닥다리처럼 보이지 않게 하려면 이거 지정은 선택의 여지가 없는 필수이다.

XP 이후로 지금까지 comctl32.dll이 7.0으로 올라간다든가 해서 또 breaking changing을 겪지는 않았다.
Windows 8부터는 명목상 고전 테마와 표준 테마의 구분이 없어지긴 했지만, 그래도 공용 컨트롤 6.0 지정을 안 해도 되는 건 아니다. 구닥다리 비주얼 자체가 호환성 때문에 완전히 없어진 건 아니기 때문이다.

뭐 comctl32가 가장 대표적이긴 하지만 이 외에 (1-2) GDI+ (gdiplus.dll)와 비주얼 C++의 CRT DLL, 그리고 MFC DLL이 지난 200x년도에 이 방식을 사용해 로딩된 적이 있다.
Windows XP 시절엔 WinSxS 디렉터리에 파일이 몇 개 없었지만 Vista 이후부터는 도대체 뭐가 들어갔는지 여기에 디렉터리 수가 무려 수천~만수천 개에 달할 정도로 많아졌다. 199x년대에 한번 DLL hell을 겪은 뒤, 너무 난장판이 돼 가는 시스템 디렉터리를 이런 식으로 정리를 하려 했던 모양이다. 같은 DLL이라도 버전별로 쫙 따로 분류를...

하지만 DLL을 배포하기가 너무 불편하다는 원성이 빗발치면서 VC++ 201x부터는 CRT와 MFC DLL 로딩 방식이 다시 재래식 시스템 디렉터리 기반으로 복귀했다.
또한 GDI+도 오늘날은 기존 GDI만큼이나 재래식 유물로 전락했고... 요즘은 딱히 이 WinSxS 기반 DLL 로딩이 활발히 쓰이고 있는지 모르겠다.

DLL 버전 설명이 좀 길어졌는데, 이것 말고도 xml에 들어가는 정보로는
(2) 내 프로그램이 고해상도+가변 DPI를 인식한다는 플래그
(3) 반드시 관리자 권한이 필요하다는 식의 권한 플래그

가 Vista에서 추가되었다. 시스템 차원에서의 고해상도 DPI 설정이야 더 말할 것도 없고 Windows 8.1부터는(8도 아님) 실행 중에 on-the-fly로 모니터 단위 DPI 설정이 변경되는 것에도 추가로 대비가 돼 있어야 한다. 그런 표식이 없으면 그냥 그래픽 카드의 힘으로 프로그램 화면이 그대로 기계적으로 확대 축소된다.

먼 옛날, Windows NT 3.x 내지 95 시절엔 화면 해상도를 재부팅 없이 on-the-fly로 바꾸는 것만 해도 굉장한 혁신이었는데 참 격세지감이다. 시스템 DPI도 예전에는 재부팅이 필수였지만 그래도 Windows Vista쯤부터는 그냥 재로그인만 하면 되게 규제가 완화됐다.

그리고 Vista부터인지 7부터인지는 모르겠지만 (4) 이 프로그램이 인식하는 운영체제 목록도 xml에다 명시하게 되었다. PE 실행 파일 포맷에 명시된 OS 버전의 역할을 어느 정도 대신하게 됐다.
Windows 8.1부터는 GetVersionEx가 알 수 없는 이유로 인해 봉인되어서, 프로그램이 인식하는 걸로 등록되지 않은 최신 운영체제의 버전은 Windows 8 이상으로는 알려주지 않게 바뀌었다. 도대체 이런 만행을 왜 무슨 이유 때문에 저질렀는지 난 모르겠지만.. 도대체 버전을 숨겨서 뭐 하게?

그리고 Windows 7도.. 자기 버전이 명시되지 않은 EXE 프로그램이 이름이 setup이라거나 하면, 실행 후에 "이 프로그램은 혹시 설치 프로그램인가요? 뭔가가 제대로 설치/제거되지 않았을 수 있습니다" 이런 꼬장을 부린다. 무슨 호환성과 관련된 조치인 듯하다.

결국 처음에는 공용 컨트롤 때문에 사용하기 시작한 xml인데 이제는 무슨 실행 프로그램을 제대로 만들려면 메타데이터 xml을 집어넣는 건 거의 필수가 되었다. 이 프로그램이 미래에 운영체제에서 새로 도입되는 시스템이나 기능을 받아들일 준비가 됐다는 것을 나타내는 증서 역할을 하다 보니, 들어가는 내용이 점점 증가하고 있다. 저 네 가지 아이템 말고 내가 또 빠뜨린 게 있는지 모르겠다.
그리고, PE 헤더에 운영체제 버전과 서브시스템 버전은 왜 따로 존재하고 둘의 차이가 무엇인지도 본인은 궁금하다.

* 추가 설명

사실, 메모장이나 워드패드처럼 Windows에 포함되어 있는 기본 프로그램들은 내부의 매니페스트 XML을 열어 보면 공용 컨트롤, 고해상도 DPI, 실행 권한 같은 설정은 있지만 굳이 운영체제 정보가 들어있지는 않다. 특정 버전의 운영체제에 포함되어 있는 프로그램들이 또 그 운영체제 GUID가 내장되어 있다거나 하지는 않다.

이때는 PE 헤더 차원에서 명시된 운영체제 버전이 활용된다. 이 버전이 Windows 8.1에 달할 정도로 높은 값이 들어있으면 GetVersionEx 함수도 Windows 8.1의 버전도 정확하게 되돌려 준다. 다만 이 경우, 그 실행 파일은 Windows 8.1 미만의 운영체제에서는 전혀 실행되지 않는다는 것을 감안해야 한다. 심지어 7에서도 실행이 거부된다.

Posted by 사무엘

2015/09/03 08:30 2015/09/03 08:30
, , ,
Response
No Trackback , 3 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1134

몇 가지 C++ 이야기

1. 람다 함수와 내부 클래스 사이의 관계

본인은 몇 년 전엔 Visual C++ 2010으로 갈아탄 기념으로, <날개셋> 한글 입력기의 소스 코드 내부에서도 한 함수 안에 임시로 사용되던 잡다한 매크로 함수들을 대부분 람다나 템플릿 함수로 바꿨다. 이건 무식한 #define의 사용을 최소화한다는 코딩 컨벤션과 부합하는 리팩터링이었다. #define은 조건부 컴파일이나 ##처럼 정말로 컴파일러의 영역을 초월하여 전처리기의 도움이 필요한 영역에서나 제한적으로 사용할 것이다.

그 당시엔 매크로가 함수 안의 지역변수들을 건드리는 건 대부분 캡처로 기계적으로 치환해서 집어넣었다. 허나 무분별한 캡처 난발도 지금 보니 무척 지저분하게 보인다는 것을 깨닫는 데는 그리 긴 시간이 걸리지 않았다.
스케일만 한 함수 안으로 좁아졌을 뿐, 그 안에서 또 온갖 전역변수들을 덕지덕지 참고하여 결합도가 개판이 된 함수를 보는 듯한 느낌이어서 말이다. 소프트웨어공학 용어로는 common coupling에 해당한다.

여러 람다 함수가 비슷한 지역 변수들을 참조하는 경우, 그건 데이터와 함수를 몽땅 묶어서 함수 내부에 있는 local 클래스 형태로 떼어 내 버렸다. 어차피 람다의 캡처가 내부적으로는 그렇게 가상의 클래스 멤버 형태로 구현되니까 말이다.
그런데 클래스의 멤버 함수 내부에 있는 람다 함수가 지역 변수들도 참조하고 this 포인터까지 참조하는 경우.. 이건 좀 소속을 어디에다 둘지 좀 난감하긴 했다.

Visual C++ 2012부터는 드디어 캡처가 없는 람다에 한해 일반 함수 포인터로 typecast도 가능해졌다.

2. 템플릿 인자의 성격 분류

다음으로 C++ 템플릿 얘기를 하겠다.
지금까지 템플릿을 매크로 함수의 대체 용도로 사용했지만 한편으로는 이것을 공용체의 대체품으로도 잘 활용하고 있다.
예를 들어 클립보드의 내용을 type-safe하게 액세스 해 주는 클래스를 이런 식으로 사용한다.

CClipboard<WCHAR> cb(CF_UNICODETEXT);
CClipboard<DROPFILES> cb(CF_DROP);

예전에는 CClipboard라는 한 클래스 안에
union { PCWSTR pszText; DROPFILES *hDropFiles; };

라고 union을 쓰던 것을 typename T *pData 요렇게 바꾼 것이다.
어차피 한 클립보드 포맷 하에서 다양한 타입을 섞어서 쓸 일은 없으므로, 꼭 공용체가 필요한 상황이 아니기 때문이다.

그리고 템플릿 인자의 명칭을 용도별로 통일하고 있다. 크게 다음과 같은 네 가지가 있더라.

(1) 저것처럼 일반적인 임의의 type은 T이다.
(2) 참조 타입은 R이다. 이건 T 자체는 아니지만 call by value로도 전달할 수 있을 정도로 가볍고 T의 값을 온전히 나타낼 수 있는 key이다. T의 생성자에 단독 인자로 들어오는 게 가능하다.
가령, T가 String이라면 R은 const char*가 될 수 있다. 혹은 그냥 복사 생성자 격인 const T&도 상관없고.
R은 컨테이너 클래스다 추가하거나 검색하는 값을 지정할 때 쓰일 수 있다.

(3) 그리고 정수 인자는 N. 클래스에 소속된 static 배열의 원소 개수나 enum 값을 정의할 때 쓰인다.
(4) 끝으로, 람다든 functor든 함수 포인터든.. 어쨌든 실행 코드가 들어가는 부분은 O이다. F를 쓸까 하다가 기분 탓에 O가 됐다.

template<typename T, size_t N> class CStaticArray { T m_dat[N]; };
template<typename T, typename R=const T&> class CLinkedList { };
template<typename O> void EnumData(O func);

같은 식이다. 이것 말고 템플릿 인자의 용도는 또 뭐가 있을지 궁금하다.

다만, C++이 언어 문법 차원에서 템플릿 인자를 명백히 구분하는 건 정수형(N) 아니면 typename(T, R, O) 이렇게 둘뿐이다. 그러니 완전히 귀에 걸면 귀걸이이고 코에 걸면 코걸이이다. 템플릿 코드 자체만으로는 컴파일러가 문법 오류를 잡을 수 없으며, 그 템플릿에다 실제로 인자를 줘서 타입을 인스턴스화한 뒤에야 문제를 발견할 수 있다. 이것보다는 쓰임이 제한적이더라도, 좀 덜 와일드하고 통제 가능하고 쓰임을 예측 가능한 템플릿을 만들 수는 없나 싶은데 아직까지는 갈 길이 요원해 보인다.

아, 그나저나 템플릿 선언은 오로지 global scope 안에서만 가능하다. 한 함수 안에 있는 지역 클래스는 템플릿 형태로 선언될 수 없으며 일부 멤버 함수만이 템플릿 형태로 선언되는 것조차도 불가능하다.
람다 함수도 템플릿 형태로 선언될 수 없다. 미래의 C++ 문법에서는 이 정도 한계는 없어질 수도 있지 않겠나 하는 생각이 든다.

3. 전처리기에서 sizeof 연산자 떡밥

전처리기의 #if 조건식에서는 어지간한 정수 연산이 가능한 반면, 잘 알다시피 sizeof 연산자는 사용할 수 없다. sizeof의 값에 따라 곧장 조건부 컴파일이 가능하면 참 좋겠지만 그건 순리에 어긋나는 일이다. 컴파일러에게 넘겨 줄 코드를 전처리 하는 중인데, 임의의 구조체의 크기처럼 소스 코드를 컴파일해야만 값을 구할 수 있는 연산자를 전처리기에다가 요구할 수는 없기 때문이다.

과거에 C++에서 컴파일러와 링커 사이의 순리를 거스르는 시도를 하다 템플릿 export 흑역사가 발생했듯, sizeof도 전처리기와 컴파일러 사이에서 "닭이 먼저냐 계란이 먼저냐" 싸움이 될 수 있다.
전처리기를 이용한 조건부 컴파일러는 소스 코드의 이식성에 도움이 되는 기능인데, 정작 기계 종속적인 이식성 관련 정보를 무작정 표준 매크로 심벌로 집어넣을 수는 없다니 이거 참 역설이 아닐 수 없다.

물론 int나 void*의 크기 정도야 전처리기에다가 곧장 박아 넣을 수도 있다. 그러나 근본적으로 전처리기는 코드의 의미나 타겟 플랫폼 따위는 전혀 모른 채 시종일관 lexical한 치환만 하면서 완전 동일하게 동작하는 물건이며, 포인터 같은 기계 종속적인 사항에 대해서는 완전히 아오안이어야 한다.

이런 이유로 인해 포인터의 크기나 비트 endian-ness 같은 타겟 플랫폼 정보는 있으면 유용할 것 같음에도 불구하고 표준 predefined 매크로로 제공되지 않는다. 조건부 컴파일을 위해 그런 정보가 필요하다면 필요한 사람이 해당 매크로 심벌을 별도의 헤더나 컴파일러 옵션을 통해 지정해 놔야 한다. 전처리기가 월권 행위를 저지르지 않아도 되게 해 주기 위해서이다.

다만, 전처리기가 아닌 컴파일러의 입장에서는 sizeof는 컴파일 타임 때 값이 결정되는 아주 static하고 깔끔한 연산자이다. sizeof의 피연산자로는 타입 이름과 값이 모두 올 수 있는데, 값은 '직접 실행이 되지 않는다'. 쉽게 말해 sizeof( *((int *)NULL) )을 해도 뻑이 안 난다는 뜻.
그렇기 때문에 sizeof의 값은 static 배열의 크기를 결정하는 데 쓰일 수 있고, 또 case 문이나 템플릿의 정수값 인자에도 얼마든지 들어갈 수 있다.

Posted by 사무엘

2015/08/31 08:39 2015/08/31 08:39
,
Response
No Trackback , 6 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1133

Windows 10 사용기 외

1. Windows 10

그 이름도 유명한 Windows 10을 본인도 드디어 입수했다. Mac OS와 Windows 모두 10을 최종 메이저 버전으로 설정했다는 게 무척 흥미롭다.

개인 컴은 물론이고 회사 컴도 평소에 활발하게 쓰던 물건은 "Windows 10 다운로드 준비가 끝났는데 설치할까요?"가 진작부터 뜬 반면,
평소에 잘 안 쓰고 "여기에나 한번 10을 깔아 볼까?"라고 정작 비워 놨던 컴은 한참을 기다려도 Windows 10 설치 말이 없었다. "준비되면 알려 주세요"를 몇 번이나 클릭했는데도 감감 무소식. 이것도 평소에 로그인 횟수나 네트워크 트래픽을 감안해서 업데이트 순서를 짠 건지는 모르겠다.

참다못해 Windows 10 설치 프로그램을 직접 다운로드 해서 실행한 뒤에야 운영체제를 7에서 10으로 바꿀 수 있었다. 다운로드와 설치는 물론 금방 끝난 건 아니지만, 그렇다고 Windows 8.1을 설치하던 시절보다 터무니없이 오래 걸리지는 않았다.

설치 직후에는 바탕 화면의 personalize가 되지 않았다. 인증이 필요하대서.. "으잉? Windows 10은 완전 무료 아니었나? 자동 업데이트를 안 하고 수동 설치를 해서 그렇나?" 어리둥절했는데 재부팅을 한번 하고 나니 인증은 저절로 패스 됐고, 까맣던 배경 그림은 10을 설치하기 전의 모습으로 되돌아왔다.

비주얼에 대한 소감은..
프로그램의 제목이 가운데가 아니라 왼쪽 정렬로 돌아왔으며, 글씨 크기도 약간 더 크다가 다시 메뉴 글씨 크기와 동일하게 돌아왔다. 또한 화면을 부분만 차지하는 시작 메뉴가 되돌아왔으며 프로그램 창 주변에 그림자 그러데이션이 생긴 것은 일면 과거의 Windows Vista/7 시절로의 회귀를 떠올리게 한다.
창의 최소/최대화와 닫기 버튼이 굉장히 커지긴 했는데 정작 _ □ X 모양은 너무 대충 그려 넣은 듯. -_-;;

명령 프롬프트가 가로폭 조절이 가능해진 것이 무척 인상적이다. 하지만 글꼴은 여전히 제대로 customize가 안 된다. 하다못해 먼 옛날 9x 시절에는 코드 페이지가 무엇이냐에 따라 Courier New나 Lucida Console이라도 볼 수 있었는데 너무 칙칙한 글꼴은 오히려 NT 계열이 9x보다도 퇴보했다.

운영체제를 업데이트 한 직후, 이전까지 사용하던 프로그램들은 10에서도 거의 그대로 곧장 사용이 가능했다. 그러나 <날개셋> 한글 입력기는 편집기만 남아 있고 외부 모듈은 운영체제의 IME 목록에서 사라졌다.
허나 이건 프로그램을 재설치만 하면 해결되니 그리 심각한 문제는 아니다. 또한 지금까지 파악한 바로는 Windows 10은 문자 입력에 관해서 딱히 기술적으로 크게 바뀐 게 보이지 않는다. 심지어는 세벌식 파워업도 10의 MS 한글 IME를 대상으로 잘 동작한다.

2. <날개셋> 한글 입력기에서 발견된 문제

다만, <날개셋> 한글 입력기가 Windows 10에 대비하여 개선해야 할 사항은 크게 두 가지가 발견됐다.

(1) 첫째, Windows 10은 Metro 앱도 데스크톱에서 뭔가 일체형으로 연계하며 동작하게 된 듯하다. Windows 10의 상징이라 해도 과언이 아닌 엣지(Edge) 브라우저도 기술적으로는 Metro 앱이다. Metro 모드에서는 클래식 데스크톱 GUI를 사용하는 기능들이 동작하지 않는다. 고로 <날개셋> 제어판이나 About 대화상자 같은 것도 못 띄운다. (그걸 시도하면 그냥 씹히거나 프로그램 전체가 그냥 튕긴다)
8 시절에는 메트로 앱들은 데스크톱의 입력 도구모음줄에 접근을 할 수 없으니 신경 쓸 필요가 없었는데, 이제는 메트로 모드에서는 이런 기능들을 건드릴 수 없도록 도구모음줄 버튼이나 메뉴를 흐리게 처리해 줘야겠다.

날개셋 말고 다른 IME들은 이 문제를 어떻게 해결했느냐 하면 한글 IME는 아예 대화상자가 출력되는 명령들을 모조리 없애 버렸다. 심지어 8에는 있던 About 명령조차도 없앴다. 일본/중국어 IME는 GUI가 나오는 기능들은 몽땅 다른 프로그램을 통해 실행되게 되어 있다.

사실, 한글 IME도 부수/획수 한자나 필기 인식 같은 보조 입력 도구는 별도의 프로그램을 통해 구동한다. 그러나 내 프로그램은 이런 것들이 다 in-process 형태로 구동된다. 그래서 Metro 모드 같은 데서는 여러 제약이 걸리는 것 같다. 금방 해결 가능한 문제는 아닌 것 같고 프로그램 구조를 앞으로 어떻게 유지할지 생각을 해 봐야겠다.
참고로, 엣지 브라우저 자체는 크롬의 마소 버전이라고 생각해도 좋을 정도로 "빠르고" 산뜻해서 느낌이 굉장히 좋았다. 그거 하나는 인정한다.

(2) 둘째, 엣지에서 페이스북에 접속해서 댓글을 써 보니, 한참 글자를 입력하다가 비한글 문자를 입력하는 순간, 예전에 입력 중이던 글자가 몽땅 사라지는 문제가 있었다. "가을에." -> "에."만 남는 식.
또한 명령 프롬프트에서도 내 프로그램으로 한글을 입력해 보면, 조합하던 글자가 덮어써진다. "가" "가을" "가을에"가 되는 게 아니라 "가" "을" "에". 신기하게도 MS IME로 한글을 좀 입력하다가 다시 날개셋으로 돌아오면 명령 프롬프트는 이 문제가 없어짐.

100% 재연 가능하고, MS IME는 안 그런데 내 프로그램만 그렇고.. 현상 자체는 완벽하게 파악이 됐지만 이건 또 MS가 무슨 농간을 부린 건지 허무한 생각이 든다. 아마 둘 다 같은 원인 때문일 거라고 추측만 하는데.. 제일 골치 아픈 부류의 문제이며 해결이 쉽지 않을 수도 있다.

3. key의 인식 방법과 관련된 customization

이건 Windows 10과는 관계가 없는 다른 얘기이다.
<날개셋> 한글 입력기는 한글을 생성하기에 앞서서 key 입력을 인식하는 방식 자체를 사용자화 가능하다. 크게 다음과 같은 시나리오가 있다.

(1) 원래는 먹던 특정 key를 먹지 않게 할 수 있다: 표준 두벌식의 경우 오로지 A~Z 26개 key만 사용하기 때문에 나머지 숫자와 기호는 따로 IME가 가로채는 게 아니라 그냥 응용 프로그램으로 넘겨서 숫자나 기호를 입력하게 한다.

(2) 원래는 먹지 않던 특정 key를 IME 입력으로 바꿀 수 있다: space의 경우, 굳이 IME가 처리할 필요가 없는 key이다. 하지만 인디자인 버그 같은 걸 해결하기 위해서 IME가 굳이 가로채어 공백을 되돌리게 할 수 있다.

(3) 특정 key를 IME 입력 대신 다른 key로 바꿀 수 있다: 내 프로그램으로 드보락 글쇠배열을 사용하는 경우, 보통은 드보락 방식대로 IME가 알파벳을 보내게 한다. 하지만 글쇠 누름 날개셋문자를 사용하면 아예 해당 알파벳 key 입력을 응용 프로그램에다가 보내게 할 수도 있다.

쉽게 말해 비한글 알파벳이나 공백 같은 문자를 IME 방식으로 보내느냐, 그렇지 않고 더 원초적인 key 메시지 형식으로 보내느냐를 제어할 수 있다는 뜻이다.
단축키 같은 것은 key 입력 메시지 형태로 온 것만 인식되지 IME 방식으로 전달된 문자로는 인식되지 않는 경우가 많기 때문이다. MS Excel의 경우, 영문을 key 입력 형태로 입력했을 때에만 함수의 목록 자동 완성이 처리되지만 IME 방식으로 입력된 것에는 반응하지 않는다.

(1)과 (2)는 6.5 버전에서 기본 입력 스키마에 해당 기능이 추가되고 구현됐다. 한편, '글쇠 누름' 날개셋문자는 비교적 최근인 7.9 버전에서 추가되었다.
현재 개발 중인 8.2 버전은 (3)이 소개하는 '글쇠 누름' 날개셋문자의 사용을 홍보하기 위해, 제어판의 글쇠배열 편집 창에서 숫자/문자를 입력하는 '일반 문자' 날개셋문자를 그에 상응하는 '글쇠 누름' 날개셋문자로 자동으로 모두 바꾸는 기능을 추가했다.

그리고 더 간단히, 사용자가 누른 key에 해당하는 글쇠 누름 날개셋문자를 자동으로 입력시키는 모드도 추가했다. 예전에는 세벌식 한글, 두벌식 한글, 이동, 영문 알파벳 같은 모드가 있었는데 그런 것처럼 새로운 모드를 넣었다는 뜻이다. 아주 자연스럽게 기능 확장이 가능하다.

또한 (2)를 더 쉽게 설정할 수 있게 하기 위해, 단축글쇠를 입력받는 대화상자에다가는 지금 누른 가상 키코드의 문자값에 해당하는 '일반 문자' 날개셋문자를 자동으로 배당하는 기능도 추가했다.
알파벳이나 숫자를 key 입력으로 보내는 것과 IME 문자열로 보내는 것의 차이에 대해서는 도움말에다가도 더 자세한 설명을 넣을 예정이다.

4. 고기 먹고 싶음 -_-

아직 어쩔 수 없는 여름이긴 하지만 그래도 날씨가 예전보다 덜 더워져서 무척 좋다.
난 어릴 때부터 왜 태양이 긍정적인 심상이고 그늘이 부정적인 심상인지를 이해를 못 했을 정도로 몸에 열이 많고 더위를 싫어했다.

이제 좀 가을이 되고 나면 날씨 탓할 일 없이 더 집중해서 코딩을 진행하고 싶은데.. 프로그램 완성의 꿈은 요원하기만 하다.
도깨비불 현상 없는 입력 방식이 심리적으로 무척 도움이 된다. 세벌식은 없어질래야 없어질 수 없고 없어져서는 안 되는 한글 입력 방식이다. 뭐 그건 그렇고..

사용자 삽입 이미지
나만 저렇게 생각하는 게 아니었구나.
돼지는 훌륭한 단백질 공급원이고, 단백질은 훌륭한 스트레스 해소원이다.

사용자 삽입 이미지
그래서 위대한 령도자 세종대왕도 약을 빨거나 한 건 아니고 고기를 드시면서 한글을 창제하시였다. 한글이 없었으면 내 프로그램도 없었겠지.
(다만, 그 덕분에 저분은 세자 시절부터 굉장한 비만이었으며, 당뇨 같은 성인병도 평생 달고 살았다고 함. 본인도 키에 비해서는 좀 과체중인 상태..;;)

Posted by 사무엘

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

C++의 클래스에는 여느 객체지향 언어와 마찬가지로, 정적 바인딩이 아닌 실행 시간 동적 바인딩을 거쳐 호출되는 가상 함수라는 개념이 있다.
일반 함수들은 선언만 해 놓고 정의를 안 했다면, 그 함수를 실제로 호출한 곳이 있을 때만 링크가 시도되고 링크 에러가 난다. (물론 DLL을 만들 때처럼 외부로 export된다고 명시된 함수라면, 우리 모듈 내부에서 당장 안 쓰이더라도 당연히 몸체가 존재해야 함. 이건 논외로 한다.)

이런 일반 함수와는 달리 가상 함수는 해당 클래스에 속하는 개체가 생성되어 가상 함수 테이블이 만들어질 때 이미 참조가 발생한다. 그렇기 때문에 일단 선언을 한 이상, 코드 내부에서 직접적으로 호출을 안 하더라도 반드시 정의가 돼 있어야 한다. 그래야 링크 에러가 안 난다.
가상 함수이지만 자기 몸체가 존재하지 않아도 되는 예외적인 경우는 단 하나, 순수 가상 함수뿐이다.

순수 가상 함수가 존재하는 클래스는 반쯤은 불완전한 타입과 비슷하다. 불완전하기 때문에 그 클래스의 인스턴스를 직접 만들 수 없다. 누군가가 얘를 상속하여 파생 클래스를 만든 뒤, 모든 순수 가상 함수들에 대한 몸체를 구현해 줘야만 한다. 몸체를 안 만들고 선언만 해 놓으면 컴파일은 되지만 그제서야 링크 에러가 나게 된다. 즉, 순수 가상 함수는 가상 함수의 링크와 관련된 문제를 파생 클래스로 보류하는 역할을 한다.

순수 가상 함수가 들어있는 추상 클래스의 인스턴스를 직접 만드는 것은 컴파일러에 의해 원천 봉쇄되고 금지되어 있다. 그런데 아주 특수한 상황에서는 이렇게 몸체가 없는 추상 클래스에 대한 직접 호출이 일어날 때가 있다. 예를 들어 아래와 같은 경우이다.

class CDerived;
class CBase {
    CDerived *m_pt;
public:
    CBase(CDerived *p);
    virtual void Pure() = 0;
};

class CDerived: public CBase {
public:
    CDerived(): CBase(this) {}
    void Pure() { puts("Ahh"); }
};

CBase::CBase(CDerived *p): m_pt(p) { p->Pure(); }

int main() { CDerived obj; }

생성자에서 자기 자신이 아직 완전히 초기화되지 않은 상태일 때 Pure()을 호출해 버리니, 마치 열차가 탈선한 것처럼, 지뢰찾기에서 지뢰를 밟은 것처럼 허를 찔리는 것이다.
사실 forward 선언까지 동원해 가면서 굳이 m_pt를 CDerived의 포인터로 지정하지 않아도 된다. 그냥 기반 클래스와 동일한 CBase *로 지정해도 에러가 나는 건 마찬가지이다.

참고로, CBase의 생성자에서 저렇게 번거롭게 p->Pure()을 하지 않고 그냥 this에 대해서 Pure()을 호출하려 시도하면 그건 순수 가상 함수임에도 불구하고 동적 바인딩이 아니라 정적 바인딩이 일어난다. CBase에 Pure 함수가 정의돼 있지 않다고 링크 에러가 난다. 그걸 별도의 포인터 값으로 억지로 우회함으로써 아직 몸체가 없는 순수 가상 함수에 도달할 수 있다. 위의 코드는 굉장히 인위적인 예이지만, 멀티스레드 race condition 같은 데서도 드물게 이런 일이 벌어질 수 있다.

C#은 생성자에서도 동적 바인딩이 잘 처리되는 게 보장되는 반면, C++은 옛날에 만들어지기도 해서 성능 보전을 위해서인지 설계 관점이 다소 보수적이다. 기반 클래스의 생성자는 자신이 파생 클래스의 생성 과정의 일부라 하더라도 파생 클래스에 대한 단서를 전혀 얻을 수 없고 언제나 기반 클래스의 형태로만 동작한다.
여러 모로 생성자에서 가상 함수를 호출하는 건 좋지 않다는 걸 알 수 있다. DllMain 안에서 또 DLL을 로딩하지 말고 가능한 한 거기서는 몸을 사리고 있어야 하는 것과 비슷한 맥락이다.

초기화가 되기 전에 가상 함수 테이블이 가리키는 주소값이 NULL이었다면, 그냥 더 생각할 것도 없이 운영체제 차원에서 '잘못된 연산' 에러가 나고 그걸로 끝이 날 것이다. 그러나 그렇게만 하는 건 재미(?)가 없고 데이터를 조작하다가 발생한 여느 null pointer 에러와 구분도 어려우니 컴파일러는 가상 함수 테이블에다가 순수 가상 함수에 대한 디폴트 핸들러의 주소를 넣어 준다. 주소를 한 번만 넣어 주면 끝이니 딱히 성능에 영향을 받을 일이 없고, 따라서 debug뿐만 아니라 release 빌드에도 못 넣을 이유가 없다.

개체가 정상적으로 초기화됐다면 그 주소는 사용자가 작성한 파생 클래스의 함수로 당연히 대체된다. 그러나 그게 아직 바뀌지 않았다면 핸들러 함수로 간다. 얘는 assert(0)과 비슷한 급의 예외를 발생시키는 것 말고 딱히 하는 일은 없다. 다만, 이 일이 벌어졌을 때 사용자가 지정해 준 함수가 호출되게 할 수는 있다.

가상 함수가 몸체가 온전하지 않으면 컴파일 에러(순수 가상 함수에 대한 클래스 선언)와 링크 에러(...)뿐만 아니라 이렇게 런타임 에러까지 드물게나마 발생할 수 있다는 걸 알 수 있다. 런타임 에러라니 왠지 C++답지 않아 보이지만, 이건 그래도 운영체제나 컴퓨터 차원으로 갈 런타임 에러를 언어 시스템 차원에서 수습 가능한 런타임 에러로 바꿔 주는 체계까지는 갖춰져 있다. 배열 첨자 초과나 division by 0 에러는 전자로 바꾸려면 매번 값을 사전에 점검해야 하기 때문에 오버헤드가 큰 반면, 순수 가상 함수 호출은 그냥 디폴트 함수 주소만 설정해 주면 되니까 말이다.

Posted by 사무엘

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

« Previous : 1 : ... 117 : 118 : 119 : 120 : 121 : 122 : 123 : 124 : 125 : ... 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:
3053690
Today:
1997
Yesterday:
2713