« Previous : 1 : ... 146 : 147 : 148 : 149 : 150 : 151 : 152 : 153 : 154 : ... 221 : Next »

우리나라 철도의 역사에 관심이 많은 철덕이라면 반드시 짚고 넘어가야 할 중요한 주제가 하나 있는데, 그건 바로 여객 열차의 이름의 변천사이다. 열차의 이름은 그 열차의 차종을 식별하는 동시에 등급을 식별하기도 하기 때문에 그 위상이 조금 모호하다. 철도는 고속버스나 비행기처럼 출발지와 도착지만이 중요한 point-to-point 수송 교통수단이 아니라 중간 정차가 차지하는 비중이 높으며, 정차 빈도에 따라 속도의 편차가 큰 여러 열차 등급이 존재할 수 있다.

1899년에 우리나라에 최초의 철도인 경인선이 개통하고 1905년에 경부선이 개통했을 때는 고유명사라 불릴 열차의 이름 같은 건 딱히 없었다. 그냥 빠르다는 수식어가 붙은 ‘급행열차’라는 용어만이 쓰일 뿐이었다. 프랑스의 떼제베(TGV)가 거창한 뜻이 담겨 있는 게 아니라 그냥 ‘아주 빠른 열차’가 전부이듯이 말이다. 증기 기관차로 경인선 제물포-노량진이 1시간 40분 가까이 걸렸고 지금의 서울-부산뻘인 경부선 서대문-초량이 17시간이나 걸렸지만, 그 시절엔 그것만으로도 속도 혁명이라 불리기 충분했다.

그 해 5월부터는 서울-부산이 14시간대로 단축된 특급 열차가 운행을 시작했지만, 아직 그것만을 식별하는 명칭은 없었다. 조선 침략의 원흉인 이토 히로부미가 원 태우 의사에게서 짱돌을 맞아 얼굴을 크게 다친 게 1905년 11월이니, 그건 바로 이 열차의 탑승 중에 발생한 사건일 것이다. 열차의 표정 속도가 아직 시속 30km를 채 못 넘어서 지하철보다도 느리던 시절이다. (그나마 요즘 지하철은 1km를 채 못 달리고 정차를 반복하면서도 그런 표정 속도를 내는데!) 그러니 그 시절엔 열차 밖에서 돌을 던져서 열차 안의 승객을 맞히는 게 가능했다.

한국 철도에서 최초로 고유명사 이름이 붙은 열차는 1906년 4월 16일부터 경부선을 달리기 시작한 ‘융희호’이다. 이것은 망해 가던 대한제국의 연호에서 따 온 명칭이다. 서대문-초량을 11시간 만에 주파했으니 경부선 개통 직후의 열차 운행 시간인 17시간에 비하면 상당히 빨라진 것이고 사실 KTX 개통 전까지 다니던 청량리-부전 전역정차 통일호보다도 빨랐다 (12시간 반이나 걸리던 1221 열차)! 표정 속도는 30km/h를 드디어 돌파하여 지하철을 따라잡았고, 최고 속도는 60km/h 정도에 진입했다.

융희호의 중간 정차역은 KTX 개통 전에 정차를 좀 많이 하던 경부선 새마을호와 얼추 비슷한 수준(8~9개역?)이었다. 여객 취급뿐만 아니라 물과 석탄 보충을 위한 정차도 불가피했다. 그러나 가감속이 병맛인 증기 기관차로 통일호만치 정차를 많이 했다간 그 속도를 절대로 낼 수 없을 것이다.

그때는 ‘융희’라는 이름을 반으로 쪼개서 서울 방면 상행은 ‘융호’라고, 부산 방면 하행은 ‘희호’라고 불렀다고 한다. 이때는 경인선과 경부선이 두 말할 나위가 없이 단선이고 열차 운행도 몹시 드물었기 때문에 특정 열차에 곧바로 고유한 이름이 붙는 것이나 마찬가지였다.

그 당시엔 물가 대비 열차 운임이 지금보다 훨씬 더 비쌌음은 자명한 사실이다. 서민들은 장거리 여행을 하려면 지금으로 치면 고속버스나 KTX가 아니라, 비행기 정도는 타는 각오를 하고 열차를 타야 했다. 박리다매를 할 수 있을 정도로 사람들의 이동이 빈번한 것도 아니었을 뿐더러, 지금도 일본은 본토의 열차 운임이 사철 위주이고 비싼 걸로 악명 높은데 그 시스템이 식민지라고 예외가 아니었다. 실제로 일제가 조선 땅에서 철도를 운영하여 벌어들인 수익은 굉장한 흑자를 냈다고 한다.

융희호가 첫 운행한 건 한강 철교가 완공되고 서울에서 신의주까지 가는 경의선이 개통한(1906년 4월 3일) 거의 직후였다. 다만, 지금과 같은 서울 역은 없었고 공덕, 서강으로 가는 오늘날의 용산선이 그때의 경의선 본선이었으니 그 길을 통해 열차는 서울 이북의 신의주로 갔다. 융희호는 1908년부터 부산-서울이 아니라 부산-신의주를 몽땅 직통 운행하기 시작했다.

자, 그 후 조선이 망하고 일제 식민지가 되고부터는 열차 이름도 대놓고 하카리(빛), 노조미(소망) 같은 일본어가 등장했다. 그리고 스케일은 더 커져서 부산에서 아예 만주까지 열차가 다니기 시작했다. 일제는 애초에 대륙 침략의 발판을 닦으려고 철도를 놓기도 했으니 말이다.

그러다 1936년 12월 1일부터는 ‘아까스키(여명)’ 호라는 특급 열차가 다니기 시작했는데 이것이 일제 강점기를 통틀어 한반도에서 가장 빠른 열차였다. 경부선이 전구간 복선화되기도 전에 그것도 증기 기관차로 서울-부산 무려 6시간 45분을 달성했다는 건 사기에 가깝다. 나중엔 6시간 반으로 더 단축!

일제 강점기 때 이 정도로 인프라가 구축됐으니 그 당시엔 육지에서 철도보다 더 빠른 교통수단은 없었고, 6· 25 때도 대통령과 참모진은 열차를 타고 피난을 갔다. 자동차는 서울을 벗어나면 빠르게 달릴 만한 포장 도로가 없어서 서울-대전이 과장 좀 보태면 8시간씩 걸리는 지경이었다. (사실 지금은 북한이 평양만 벗어나면 이 지경이기도 하고. ㄲㄲ)

우리나라가 일제로부터 해방된 뒤인 1946년 5월 27일, 시대가 시대인 만큼 ‘해방자호’라는 이름의 증기 기관차가 경부선을 다니기 시작했다. 그냥 해방호도 아니고 왜 ‘자’가 붙었나 하면 이건 者를 뜻하기 때문이다. 영어로는 Korean Liberator. 이 열차는 고급 컨셉을 표방하지 않았고 일본인 철도 경영자가 물러나서 그런지 서울-부산 운행 시간이 9시간으로 크게 늘었다.

그리고 한국 철도는 이 승만 정권의 말기인 1960년 초가 돼서야 ‘특급 무궁화호’를 통해 옛날 아까스키 호의 표정 속도를 회복하게 되었다. 동력원은 증기가 아닌 디젤이다.

자막: 특급 무궁화호 등장
경부선에 또 하나의 특별 급행열차가 등장했습니다.
새로운 특급열차는 우리 이 대통령 각하께서 '무궁화호'라고 명명해 주셨는데, 2월 21일 아침부터 운행했습니다.
종래의 통일호보다도 30분이나 빠른 무궁화호는 서울-부산간을 6시간 40분에 달리고 있는 것입니다.


‘호’라는 접미사에서 알 수 있듯이 이때까지 열차의 명명 방식은 배의 명명 방식과 비슷했다. 경부선을 다니는 열차와 호남선을 달리는 열차의 호칭이 달랐다. 이때의 무궁화호는 지금의 무궁화호와는 전혀 관계 없는 경부선 열차였고, 호남선에는 동급의 열차인 삼천리호나 태극호가 달리는 식이었다. 마치 옛날에 타이타닉 호에도 올림픽, 브리타닉 같은 동급의 자매선이 또 있었듯이 말이다.

또한 옛날에 증기 기관차는 오늘날의 디젤이나 전기 기관차와는 달리 외형적인 차륜 배치가 동력비 변환 방식에 직접적인 영향을 끼쳤기 때문에, 여객용 기관차와 화물용 기관차의 구분이 더욱 분명했으며 차륜 형태를 식별하는 이름이 존재했다는 것이 특이점이다. 미카, 901호, 파시 같은 이름이 바로 그 예이다. 이미 아시는 분도 있듯이, 우리나라에서 증기 기관차는 1967년 8월 31일을 끝으로 현역 운행을 완전히 종료한다.

자, 1960년대 이후로는 시대가 시대이다 보니 재건호, 맹호호, 청룡호, 백마호처럼 호가 아니라 ‘부대’를 붙여도 될 것 같은 북한/군대스러운 명칭도 열차에 부여되었는데.. 실제로 박통 시절엔 월남전 참전 부대 이름들이 전부 열차 명칭으로도 의도적으로 쓰였다. 군사 정권 아니랄까봐. 그것 외에도 배에 이름 붙이듯이 열차에도 노선별로 다양한 이름이 난립(?)하기 시작했으니, 상록호, 풍년호, 부흥호까지. 비둘기호와 통일호도 옛날부터 명칭 자체는 존재했다. 단지 이름의 용도 내지 의미가 지금과는 완전히 달랐을 뿐이다.

그러면서 열차의 속도는 특급열차를 위주로 점차 빨라지기 시작했고, 1969년 6월 10일에 등장한 초호화 특급 열차인 관광호가 드디어 서울-부산을 5시간대도 극복한 4시간 50분 주파를 달성했다. 경부 고속도로도 아직 없던 시절에 속도도 속도이거니와, 그 옛날에 객실에 천장 선풍기 대신 에어컨이 달려 있었을 정도면 얼마나 호화로웠을지 상상이 된다. 단지 관광호의 물가 대비 운임은 일본의 신칸센보다도 더 비쌌다는 점 역시 감안하시길. 진짜 돈지랄용이었다.

이 열차는 훗날 1974년 8월 15일, 서울 지하철 1호선이 개통한 날부터 ‘새마을호’라는 새로운 명칭으로 바뀌었으며 이것이 그로부터 30년 뒤에 KTX가 개통할 때까지 대한민국 최고급 열차의 혈통을 이어 나갔다. 서울-대전-대구-부산만 찍는 그 고매한 열차 라인 말이다.

1977년 8월부터는 새마을호를 제외한 모든 열차들은 그냥 등급만으로 우등-특급-보통으로 바뀌게 정리되었다. 일일이 이름을 붙이기에는 열차의 운행 노선과 횟수가 크게 늘어서 이렇게 단순화가 이뤄진 셈이다. 우등열차가 오늘날의 무궁화호의 전신이며, 통일호가 특급이라고 불렸다니 믿어지지 않을 것이다.

1984년 1월 1일이 돼서야 드디어 새마을-무궁화-통일-비둘기 체계가 정립되어서 열차의 이름은 오로지 등급만을 나타나게 바뀌었다. 새마을을 제외한 나머지 이름들은 국민 공모를 통해 뽑은 거라고 하지만, 결국 옛날에 한 번씩 쓰인 적이 있는 명칭들을 재사용한 셈이다.

그로부터 얼마 되지 않아 새마을호는 잘 알다시피 1985년 11월 16일에 서울-부산 운행 시간이 4시간 10분으로 단축되어 표정 속도가 드디어 100km/h를 돌파하였으며, 이것이 한국 철도 역사상 기존선에서 이뤄진 최후의 표정속도 향상 기록이다. 기관차의 출력 증대를 통해 최대 시속 150km 주행 자체는 관광호 시절부터 가능했지만, 선로/선형 개량과 신호 시스템 개선을 통해서 고속 주행 가능 구간을 늘린 덕분에 가능했던 결과이다.

지금까지 과거 얘기가 길어졌으니 이제 미래 전망을 하고서 글을 맺겠다. 1984년 이래로 거의 30년간 쓰여 온 재래식 ‘-호’ 체계는 오늘날 심하게 문란해지고 의미가 퇴색해 있기 때문이다.
일단 지난 2000년 말에 비둘기호가 멸종하였으며, 고속철이 개통하면서 통일호 역시 문서상으로는 사라지고 객차형은 전량 퇴역했다. 통일호 중 통근형 디젤 동차만 통근열차라고 명맥을 잠시 유지했지만, 그나마 얘도 이제 경의선/경원선의 극소수 구간에만 남아 있지 다 멸종이다.

문제는 여기서 그치지 않는다. KTX에 밀려 콩라인이 된 새마을호마저도 사망이 임박했다. 2013년 1월에는 전후동력형 디젤 동차가 드디어 전량 퇴역했고 2014년 말을 끝으로 지금의 새마을호는 객차형까지 죄다 역사 속으로 사라진다.
그럼 ‘-호’ 열차는 무궁화호 하나만 남으니 기존 ‘-호’ 체계가 다 붕괴되는 셈이다.

무궁화호도 디젤 동차(NDC)는 진작에 다 퇴역하고 없기 때문에, 무궁화호는 그냥 재래식 기관차 견인형 일반열차를 총칭하는 상징적인 명칭으로만 남을 것이다. 요컨대 오로지 통일호만이 새마을호와 무궁화호와는 달리 객차형이 동차형보다 먼저 없어졌다. 등급이 등급이다 보니까 말이다.

이런 재래식 열차를 대신하여 꿰차고 들어온 것은 KTX부터 시작해 누리로, ITX-청춘 같은 신형 전동차들이다. KTX는 워낙 특별한 물건이고 누리로는 어차피 무궁화호와 거의 같은 위상과 운임 체계를 계승했다지만, ITX 청춘은 새마을호를 꿰차고 들어와서 새로운 등급을 만들어 냈다. 거기에다 새마을호의 후속 열차로는 ‘ITX 새마을’이라는 이름이 정해졌다고 한다. 1974년 이래로 40년을 이어 가는 ‘새마을’의 명줄은 참 길기도 하다!

오늘날 철도계의 높으신 분들이 생각하는 새로운 명명 전략은, 열차 명칭을 ‘등급-차종’으로 이원화하는 것이라 생각된다.
등급으로는 고속열차를 뜻하는 KTX, 그 다음으로 장거리 특급 간선을 뜻하는 ITX가 있으며, 이보다 낮은 등급에 대한 이름도 정해져야 할 것이다.

다음 차종으로 말할 것 같으면 ‘KTX-산천’이 있으니 재래식 떼제베 열차를 나타내는 ‘KTX-TGV’ 같은 차종명 짝이 있어야 한다. 그리고 경춘선에 ITX-청춘이라는 2층 열차가 다니듯이 기존 경부선이나 호남선에는 ITX-새마을이 다닐 것이고 중앙선에는 틸팅 열차가 다니게 될 수 있다. ‘새마을’이 이제는 등급명이 아니라 차종명으로 쓰이는 셈이다.

그보다 더 아래의 무궁화급라면 ‘누리로’는 등급명이 될지 차종명이 될지 확실치 않으나, 아마 차종명이 될 가능성이 높다. 그리고 새마을(ITX)급이든 무궁화급이든 재래식 기관차-객차형 열차는 ‘클래식’(?)이나 그에 준하는 차종명이 붙지 않을까 싶다. 선박의 명명 스타일에서 유래되었던 한국 철도의 열차 명명 방식이 앞으로 어떻게 바뀔지가 기대된다.

이렇게 열차 이름을 중심으로 우리나라 철도의 역사를 처음부터 끝까지 쭉 읊어 보니 참 훈훈하고 기쁘다. 독자 여러분에게도 철도가 희망과 동경, 기쁨과 평안을 주는 존재이기를 본인은 원한다. May the railroad richly bless you!

Posted by 사무엘

2013/04/22 08:33 2013/04/22 08:33
, , , , ,
Response
No Trackback , a comment
RSS :
http://moogi.new21.org/tc/rss/response/821

세상의 무신론자 중에서
“세상에 신은 존재하지 않으며 내세도 심판도 없다. 내 마음대로 얼마든지 상대적인 잣대로 살아도 된다. 그걸 모르고 하나님이나 찾는 무능하고 어리석은 인생들이 너무 불쌍하다. 나는 그들을 너무 사랑하기 때문에, 무신론이 진리임을 알리기 위해 어떤 희생도 감수하고 내 생명이라도 내어 놓겠다
이렇게 말하고 행하는 사람은 없습니다.

킹 제임스 성경을 알고도 받아들이지 않는 구원받은 크리스천 중에서
“내게는 개역성경/NIV가 최종 권위인 하나님 말씀이다. KJV야말로 6만 구절의 단어를 변개하고 13구절을 후대에 ‘추가’하여 하나님 말씀을 뜯어고친 무시무시한 죄를 저질렀다. 나는 이 엄청난 사실을 정반대로 알고 있는 KJV 지지자들을 계몽하고, 진짜 절대무오한 다른 성경을 대안으로 내놓겠다.
라고 말하는 사람은 없습니다.

제가 무슨 말을 하려는지 아시겠죠?
두 진영은 서로 계산 결과만 다른 게 아니라 계산 과정과 초기의 변수, 생각하는 전제 조건부터가 완전히 다릅니다.

* 평소의 내 블로그 스타일답지 않게 무지하게 짧은 글이 돼 버렸는데..
그래도 내 생각의 핵심은 다 담겨 있으니..ㅎㅎ

Posted by 사무엘

2013/04/20 08:27 2013/04/20 08:27
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/820

마인크래프트 단상

* 마인크래프트를 보면서 떠오르는 것:

  • 이건 “집마다 지은 사람이 있으되 모든 것을 지으신 분은 하나님이시니라.”(히 3:4)를 매우 쉽게 떠올릴 수 있는 게임이다.
  • 비록 그래픽 디테일은 진짜 딱 1990년대 중반의 퀘이크+툼 레이더 1~2 수준이지만, BSP처럼 고정불변 맵에 딱 최적화된 자료구조가 아니라 임의의 광활한 지형을 실시간으로 생성하고 중간 로딩도 거의 없이 실시간으로 3D로 표현하는 게 굉장히 신기하다.
  • 블록의 단위 크기가 1m라는 특성상, 마인크래프트가 제공하는 철도는 762mm짜리 협궤와 비슷하다.
  • 철덕의 기상. 코레일과 KTX CI를 새겨 놓은 용자가 있다! 존경스럽기 그지없다. (첨부 그림 참고. 단, 마인크래프트 실제 게임은 1인칭 3D 시점이 지원된다. 저런 3인칭 2D 시점이 아님.)

사용자 삽입 이미지


Posted by 사무엘

2013/04/18 08:20 2013/04/18 08:20
,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/819

본인이 예전에 글로 썼듯, 비주얼 C++ 201x의 IDE는 소스 코드의 구문 체크 및 인텔리센스를 제공하기 위해 백그라운드에서 완전한 형태의 컴파일러를 실시간으로 돌린다. ncb 파일을 사용하던 200x 시절에는 불완전한 모조 컴파일러였지만 201x부터는 그렇지 않다. 컴파일은 그걸로 하고, 자료 저장은 아예 별도의 DB 엔진으로 하니 계층이 전문화된 셈이다.

그런데 실시간으로 돌리는 컴파일러는, MS가 자체적으로 빌드를 위해 구동하는 컴파일러하고는 다른 별개의 종류이다. 이 개발툴로 오래 개발을 해 본 분은 이미 아시겠지만 같은 문법 에러에 대해서도 메시지가 서로 미세하게 다르고 심지어 문법 해석 방식이 불일치하는 경우도 있다. 마치 MS Office의 리본 UI와 MFC의 리본 UI는 구현체가 서로 별개이고 다르듯이 말이다.

그럼 이 보이지 않는 백그라운드 컴파일러의 정체는 뭘까? 이건 ‘에디슨 디자인 그룹(Edison Design Group)’이라고 유수 프로그래밍 언어들의 컴파일러 ‘프런트 엔드’만 미들웨어 형태로 전문적으로 개발하여 라이선스를 판매하는 어느 벤처기업의 작품이다. MS에서는 이 물건을 구입하여 자기 제품에다 썼다.

컴파일러를 만드는 것은 오토마타 같은 계산 이론부터 시작해서 어려운 자료구조와 알고리즘, 컴퓨터 아키텍처 지식이 총동원되는 매우 까다롭고 어려운 과정이다. 그렇기에 컴파일러는 전산학의 꽃이라 불리며, 대학교 전산학과에서도 4학년에 가서야 맛보기 수준으로만 다뤄진다.

그리고 컴파일 메커니즘은 프런트 엔드와 백 엔드라는 두 단계로 나뉜다. 소스 코드의 구문을 분석하여 문법 오류가 있으면 잡아 내고 각종 심벌 테이블과 parse tree를 만드는 것이 전자요, 이를 바탕으로 각종 최적화를 수행하고 실제 기계어 코드를 생성하는 건 후자이다.

굳이 코드 생성까지 하지 않아도 구문을 분석하여 인텔리센스를 구현하는 것까지는 프런트 엔드만 있어도 충분할 것이다. 프런트 엔드를 담당하는 쪽은 언어의 문법을 직접적으로 다루고 있으니, C++11 표준이 뭐가 바뀌는 게 있는지를 늘 매의 눈으로 감시하고 체크해야 한다. 그리고 그런 엔지니어들이 역으로 표준의 제정에 관여하기도 한다.

에디슨 디자인 그룹은 5명의 베테랑 프로그래머들로 구성된 아주 작은 회사이다. (홈페이지부터 디자인이 심하게 단촐하지 않던가?) 하지만 세계를 움직이는 굴지의 IT 회사들에 자기 솔루션을 납품하고 있다. 작지만 기술이 강한 이런 회사야말로 컴퓨터 공돌이들이 꿈꾸는 이상적인 사업 모델이 아닐 수 없으니 매우 부럽다. 개인이 아닌 기업이나 교육 기관이 고객이며, 한 솔루션의 소스 코드를 납품하는 라이센스 비용은 수만~수십만 달러에 달한다.

마이크로소프트 컴파일러는 인텔리센스만 이 회사의 솔루션으로 구현한 반면,
Comeau C++ 컴파일러는 프런트 엔드가 이것 기반이다. Comeau라 하면, C++의 export 키워드까지 다 구현했을 정도로 표준을 가장 충실하게 따른 걸로 유명한 그 컴파일러 말이다.

굳이 백 엔드와 연결된 컴파일러가 아니어더라도, 프런트 엔드가 만들어 낸 소스 코드 parse tree는 IDE의 인텔리센스를 구현한다거나 소스 코드의 정적 분석, 리팩터링, 심벌 브라우징(browsing), 난독화 등의 용도로 매우 다양하게 쓰일 수 있다. 나름 이것도 황금알을 낳는 거위 같은 기술이라는 뜻이다.

한편, 전세계 유수의 컴파일러들에 C++ 라이브러리를 공급하는 회사는 Dinkumware이라는 걸 난 예전부터 알고 있었다. 헤더 파일의 끝에 회사 설립자인 P.J. Plauger 이름이 늘 들어가 있었기 때문이다. 난독화가 따로 없는 그 암호 같은 복잡한 템플릿들을 다 저기서 만들었다 이 말이지?
비주얼 C++이라는 그 방대한 제품은 당연한 말이지만 모든 부품이 MS 독자 개발은 아니라는 걸 알 수 있다.

그나저나, 비주얼 C++ 201x의 백그라운드 컴파일러는 C 코드에 대해서도 언제나 C++ 문법을 기준으로만 동작하더라.. ㅎㅎ

Posted by 사무엘

2013/04/16 08:40 2013/04/16 08:40
, , , ,
Response
No Trackback , 3 Comments
RSS :
http://moogi.new21.org/tc/rss/response/818

다음 버전 개발 근황 ㅋ

<날개셋> 한글 입력기 6.8이 나온 지 벌써 두 달 정도 시간이 지났다. 이 버전은 잘 알다시피 외부 모듈까지 Windows 8을 정식 지원하기 시작한 첫 버전이라고 선전... 은 했는데, 그 후로 Win8 사용자들로부터 역시 여러 미흡한 점들이 보고되었다..

  • IE의 주소 입력란 말고, 웹페이지 폼의 입력란에서 글자를 입력하는 중에 한/영 상태 버튼을 우클릭하면 메뉴 항목들이 disabled되어 나오는 것: 무척 괴이한 현상이지만 어쨌든 해결함
  • Modern(Metro) UI의 IE에서는 데스크톱 모드에서 맞춰 놓은 입력 설정이 제대로 반영되지 않고 동작하는 것: 파일 읽기에 문제가 있는 듯
  • 날씨(Weather) 같은 일부 자바스크립트 기반 앱에서는 <날개셋> 한글 입력기 커널 자체가 제대로 구동되지 못하고 영문만 입력되는 것: 역시 커널 DLL 파일에 접근하는 과정에 문제가 있는 듯. 권한 문제?

저것 말고 여전히 Windows 8의 Modern UI에서 <날개셋> 한글 입력기의 사용에 문제가 있는 분은 운영체제의 부팅 이후로 문제를 재연하는 모든 step을 마우스 클릭 단위로 상세하게 알려 주시기 바란다. 난 Windows 8 안 써서 그쪽 UI를 잘 모른다..;;더구나 데스크톱 앱과는 달리, Modern 앱들은 디버깅을 위해서 꼭 인터넷 접속을 해야 한다는 게 개인적으로 굉장히 불편하다. 정작 내 프로그램은 인터넷 같은 건 전혀 사용하지 않는데...

또한 근본적으로 Win8은 기존 데스크톱 환경과 Modern(메트로) 환경 사이에 장벽을 너무 많이 쳐 놨다. 그래서 데스크톱을 근간으로 하고 있으면서 Modern용 프로세스의 안에서도 서식해야 하는 외부 모듈에게 보안상 걸리는 제약이 너무 많다. 서로 memory mapped-file도 공유가 안 되고, Modern 프로세스 안에서는 대부분의 디렉터리에 접근도 안 되고.. 내 문서, ProgramData 다 안 된다.

Program Files와 Windows 디렉터리만 접근을 허용한다고 하는데, 전자는 32비트와 64비트가 따로 존재하기 때문에 사전이나 테이블 같은 공용 데이터를 놔 두기에는 적절하지 않은 위치이며 더구나 관리자 권한이 없으면 파일을 쓸 수도 없다. Windows\IME는 공식 설정상으로는 애초에 운영체제의 보급 IME들만이 사용하는 위치이다. 도대체 IME는 뭐 어떻게 동작하면서 Modern와 데스크톱 사이에 설정을 공유하라는 건지 모르겠다. 결국 레지스트리를 파일처럼 정보 공유 매체로 다루는 수밖에 없어 보인다.

뭐, 다음 버전을 개발하는 과정에서 이 이슈 말고도 다른 쪽으로도 <날개셋> 한글 입력기는 6.8 이래로 소스 코드가 많이 바뀌었다. 6.8은 다행히도 그 버전 자체만의 예기치 못한 버그가 들어있지 않으며 그럭저럭 잘 만들어졌다. 그래서 이 버전에 대한 유지 보수를 따로 할 필요가 없이 다음 버전인 7.0이 잘 개발되고 있는 중이다. 본인으로서는 다행스러운 점이다.

다음 버전 개발 근황을 좀 마이너한 아이템 위주로 늘어놓자면 이렇다.

1. 한컴 2바이트 코드와 한양 PUA 코드 변환과 관련된 모든 기능들은 드디어 <날개셋> 커널에서 완전히 삭제되었다. legacy 문자 코드에 대한 지원은 이미 4.8x대에서부터 차츰차츰 줄어들고, 커널에 있던 코드가 플러그 인 변방으로 이동하는 식으로 리팩터링이 진행되고 있었는데 그게 다 끝을 본 것이다. 이제 커널인 ngs3.dll에는 그런 문자 코드의 처리와 관련된 일체의 코드(프로그램)가 들어있지 않다.

2. 유니코드 문자열로부터 한글을 읽거나 쓰는 알고리즘을 미세하게나마 좀 더 최적화하고, 문자 인코딩을 자동 판단하는 알고리즘도 더 똑똑하게 개선했다. 한글이 없이 특수문자만 가득한 2바이트 인코딩을 제대로 판단을 못 하거나, 1바이트 아스키 문자 나열을 UTF16으로 오인하는 경우를 대폭 줄였다.
이 프로그램은 예나 지금이나 유니코드 UTF16, UTF8, 완성형(CP949), 그리고 조합형 코드(CP1361)을 자동 인식할 수 있다.

3. <날개셋> 편집기는 지난 3.0 시절부터 ‘기타 가져오기’ 기능을 통해 콘솔 프로그램의 출력 결과를 그대로 가져오는 기능이 있는데, 이 기능이 먼 옛날 버전부터 지금에 이르기까지 무척 비효율적으로 구현되어 있었음을 발견하여 대대적으로 개선했다.
언제든지 ‘취소’를 누르면 작업이 즉시 취소된다. stdout뿐만 아니라 stderr의 출력 결과도 가져온다. 그리고 프로그램의 실행이 끝난 뒤에도 작업 스레드가 정상적으로 끝나지 않고 강제 종료되고 있었던 것을 고쳤으며, 이 때문에 heap과 stack 메모리에서 발생하던 숱한 메모리 누수들도 덩달아 해결했다..

4. <날개셋> 편집기는 MFC를 쓰지 않고 자체 개발된 이래로 '창' 메뉴를 보면, 현재 선택되어 있는 문서 창의 항목에 체크가 표시되지 않는 버그가 있었다.. =_=;; 이걸 뒤늦게 인지하여 고침.

5. 외부 모듈의 경우 잘 알다시피 아이콘이 Windows 8 스타일의 흑백 배색으로 바뀌었는데, 표준 가이드라인에 따르면 겉의 테두리가 회색이 아니라 사실은 50% 알파가 적용된 검정이었다. 그것을 고쳤다.
그리고 사용 중인 글자판의 종류를 판단할 때, 비록 알파벳과 한글을 모두 입력할 수 있는 모호한 글자판이라도 한글(가/한) 판정이 후하게 나도록(A) 알고리즘을 살짝 고쳤다.

6. 외부 모듈은 제어판을 열어서 ‘확인’을 눌러서 종료하면 새로 바꾼 입력 방식이 모든 프로그램에서 곧바로 적용되어야 한다. 하지만 32비트 프로그램과 64비트 프로그램 사이에서는 이것이 동기화가 되지 않던 문제가 있었다. 새 버전은 이것을 해결했다. <날개셋> 한글 입력기가 64비트 플랫폼을 지원한 건 4.x시절 말기부터이고 시기적으로는 무려 5~6년이 지났는데 지금까지 이 점에 대해서는 전혀 생각을 못 하고 있었다.

7. 한글 로마자 입력 방식에서 표준 방식은 O+A로는 ‘ㅘ’가 되지 않고 오로지 W+A로만 ‘ㅘ’가 되게 규칙을 수정했다..

8. 일반적인 세로 스크롤용 휠뿐만 아니라 가로 스크롤 휠도 이제 드디어 지원한다. 일부 노트북 PC에서 터치패드 한쪽 끝을 가로로 드래그하면 이 메시지가 가는 경우가 있는데, 덕분에 편집기나 화면 인쇄 등 주요 화면에서 가로 스크롤이 가능해졌다.

<날개셋> 한글 입력기는 글쇠배열이나 오토마타 같은 걸 자유롭게 사용자 정의 가능하고 한글 입력과 관련된 거의 모든 아이디어들을 한데 기술할 수 있는 기반을 마련한 것으로 잘 알려져 있다. 하지만 그것 못지않게 이 프로그램의 독특한 면모는 바로 다양하고 개성 있는 구현체들이다. 문자 입력 기능을 제공할 수 있는 모든 형태의 구현체를 제공하기 때문이다.

편집기는 자체 한글 텍스트 에디터로, 문서 편집 창이 뜨는 일반적인 응용 프로그램과 가장 비슷한 형태이다. 전용 환경이다 보니 제공되는 기능이 가장 많고 특히 텍스트 필터를 써 볼 수 있는 사실상 유일한 구현체이다.
흔히 IME라고 불리는 외부 모듈은 EXE가 아니라 DLL이다. 범용성과 존재감이 가장 큰 구현체이다. 제공하는 기능의 양은 편집기보다 적지만, Windows 95부터 8까지의 모든 운영체제들의 특이사항을 커버하느라 코드의 양은 이게 편집기의 그것보다 더 많다.

변환기는 문자를 입력하는 기능은 없지만 한글의 표현과 관련된 호환성 유지를 위해 필요한 기능들을 한데 담은 유틸리티로, 간단한 대화상자 형태이다.
끝으로 입력 패드는 포인팅 장비를 이용한 문자 입력 기능만 제공하는 작은 프로그램으로, EXE 형태이지만 IME 내부 자료구조에 대한 훅킹을 통해 동작한다.

이런 모든 경우를 다 생각해서 개발되었다는 뜻이다. 이 구현체들은 심지어 도움말 내지 About 명령조차 서로 전부 제각각인 위치에 있을 정도로 사용자 인터페이스가 천차만별이다. (편집기는 프로그램의 도움말 메뉴, 외부 모듈은 입력 도구모음줄의 도움말 버튼, 변환기는 프로그램의 시스템 메뉴, 입력 패드는 시스템 트레이의 우클릭 메뉴)

개인적인 생각은 이들 프로그램의 아이콘도 마치 MS Office의 Word, Excel 등처럼 뭔가 한 제품에 속한다는 통일성이 느껴지는 형태로 바꾸고 싶다. <날개셋> 편집기의 지금 아이콘도 써먹은 지 벌써 10년이나 됐는데..

가끔은 까마득한 옛날의 1.x와 2.x버전을 꺼내서 실행해 본다. 내가 세상에 이런 완전 캐허접한 프로그램만으로 옛날에 정보 올림피아드 입상을 했구나 하는 생각이 든다. 1은 텍스트 에디터 하나 제대로 만들 기술도 없던 상태에서 그냥 세벌식 자판만을 위한 똘끼어린 최소한의 기술 데모일 뿐이었고 2는 버전 3을 만들기 위한 숱한 시행착오 단계였다.

3에서는 진짜 최소한의 뿌리와 기반이 갖춰지긴 했으나 아직도 허접한 UI와 외부 모듈의 안정성을 갖추기 위해 갈 길은 멀고도 험했다. 4는 버전 3이 경험한 시행착오들을 수습하면서 운영체제에 대한 독자적인 기술과 노하우가 차츰차츰 쌓이던 단계였고, 개발 8주년이 된 버전 5가 돼서야 내가 보기에 슬슬 쓸 만한 물건이 나오기 시작했다. 그리고 그 컨디션이 6에서 계속되는 중이다.

이 정도로 혼자 오래 꾸준히 개발한 프로그램이니, 내가 무슨 게임을 만든 것도 아닌데 이 프로그램에 대한 나의 애착과 중독성은 상당한 수준이다.
일단 결과물 자체부터 내가 매우 애용하고 있다. 비록 현실적으로는 외부 모듈이 가장 대중적으로 쓰이는 구현체일지 모르나 내가 가장 애용하는 구현체는 편집기이다. 자체적으로 문서를 편집하는 기능을 갖춘 일반적인 애플리케이션이며, 가장 먼저 개발되기도 했기 때문이다. 그냥 습관적으로 띄워서 뭐라도 글을 쓰고 한글 오덕질을 하고 싶은 생각이 절로 든다.

결과물뿐만이 아니라 도움말도 계속 읽어보고 싶고, 딱히 코딩을 안 해도 소스 코드를 꺼내서 뭐라도 리팩터링이나 최적화를 하고 싶다. 불행인지 다행인지 이 프로그램에 대한 모든 정체성과 권리는 본인이 혼자서 완전히 꽉 잡고 있기 때문이다. 1인 독재. <날개셋> 한글 입력기의 모든 바이너리들은 100% 자작 코드로만 이뤄져 있다.

그런데 여기에만 매여 있느라 다음 다른 연구도 제대로 못 할 정도인 건 문제인 것 같다.
이것과 관련된 개발 말고 다른 분야에는 도무지 관심이 생기질 않아서, 이걸 못 하고 덕업일치를 못 하느니 프로그래밍은 확실하게 취미 수준으로 접고 차라리 철도 같은 업종 전환도 고려할 정도로 진로가 좀 이상한(?) 방향으로 흘러가고 있다. 난 어지간한 다른 IT 분야 엔지니어들과는 애초부터 입문한 계기도 달랐고, 적성이나 취향도 다른 것 같다.

Posted by 사무엘

2013/04/13 08:30 2013/04/13 08:30
Response
No Trackback , 13 Comments
RSS :
http://moogi.new21.org/tc/rss/response/817

IOCCC라고, 사람이 가장 알아 보기 힘들고 충공깽스러운 형태로 작성된 C 프로그램 코드를 접수받는 공모 대회가 있다.
단순 코더가 아니라 전산학 내공과 해커 기질이 충만한 레알 베테랑 프로그래머라면 이미 들어서 알 것이다.

입상작들은 내가 보기에 크게 (1) 아스키 아트형, 아니면 (2) 크기 줄이기 암호형이라는 두 갈래로 나뉜다. 대회에 공식적으로 이런 식으로 참가 부문이 나뉘어 있는 건 아니지만, 여기 참가자들이 추구하는 오덕질의 목표가 대체로 이 둘 중 한 갈래로 나뉘기 때문이다.

전자는 영락없이 아스키 문자로 사람 얼굴이나 문자 같은 그림을 그려 놨는데 그건 컴파일 되는 올바른 C 코드이다. 그뿐만이 아니라 그걸 실행하면 기가 막힌 유의미한 결과물이 나온다. 간단한 게임이라든가 원주율값 계산 같은 것부터 시작해 심지어 CPU 에뮬레이터나 간단한 컴파일러, 운영체제까지 들어있는 경우도 있다.

후자는 수단과 방법을 가리지 않고 길이를 줄이기 위해 들여쓰기, 주석, 헝가리언 표기법 따위는 다 쌈싸먹고 진짜 정체를 알 수 없는 이상한 숫자와 기호와 문자로 범벅이 된 코드인데, 빌드해 보면 역시 소스 코드의 길이에 비해 믿을 수 없는 퀄리티의 동작이 나온다. 자바스크립트 같은 코드를 난독화 처리한 것과 비슷한 형태가 된다.

어떤 언어에서 소스 코드 자신을 출력하는 프로그램을 콰인(Quine)이라고 부른다. GWBASIC이라면 언어에 LIST라는 명령이 있으니 쉽겠지만, 일반적인 컴파일 기반 언어에서는 그걸 만드는 게 보통일이 아니다. 그런데 이 IOCCC 대회 입상작 중에는 A라는 코드가 있는데 그걸 실행하면 B라는 소스 코드가 출력되고, B를 빌드하여 실행하면 C라는 소스 코드가 나오고, 다음으로 C를 빌드하면 다시 A가 나오는... 중첩 콰인을 실현한 충격과 공포의 프로그램도 있었다. 그것도 A, B, C는 다 형태가 완전히 다르고 인간이 인식 가능한 아스키 아트! Don Yang이라는 사람이 만든 2000년도 입상작이다.

역대 수상작들을 보면 프로그래머로서 인간의 창의력과 잉여력, 변태스러움이 어느 정도까지 뻗칠 수 있는지를 알 수 있다. 그리고 이런 대회는 한 프로그래밍 언어의 극악의 면모를 시험한다는 점에서 전산학적으로도 나름 의미가 있다. 들여쓰기와 긴 변수명과 풍부한 주석이 갖춰진 깔끔한 코드든, 저런 미친 수준의 난독화 코드든 컴파일러의 입장에서는 어차피 아무 차이 없는 똑같은 코드라는 게 아주 신기하지 않은가?

다른 언어가 아니라 C는 시스템 레벨에서 프로그래머의 권한이 강력하다. 그리고 전처리기를 제외하면 특정 공백 문자에(탭, 줄바꿈 등) 의존하지 않는 free-form 언어이며, 언어 디자인 자체가 온갖 복잡한 기호를 좋아하는 오덕스러운 형태인 등, 태생적으로 난독화에 유리하다. 게다가 도저히 C 코드라고 볼 수 없을 정도로 코드의 형태와 의미를 완전히 엉뚱하게 뒤바꿔 버리는 게 가능한 매크로라는 비장의 무기까지 있다!

심지어는 C++보다도 C가 유리하다. 함수를 선언할 때 리턴 타입을 생략하고 함수 정의에서는 리턴 문을 생략할 수 있다. 가리키는 대상 타입이 다른 포인터를 형변환 없이 바로 대입할 수 있으며, 또한 인클루드를 생략하고 표준 함수를 바로 사용할 수도 있다. C++이었다면 바로 에러크리이지만, C에서는 그냥 경고만 먹고 끝이니 말이다. C의 지저분한 면모가 결국 더 짧고 알아보기 힘든 코드를 만드는 데 유리하다는 뜻 되겠다.

현업에서는 거의 언제나 C++만 써 와서 잘 실감을 못 했을 뿐이지, C는 우리가 생각하는 것보다 저 정도로 꽤 유연(?)한 언어이긴 하다. IOCCC 참가자의 입장에서 C++이 C보다 언어 구조적으로 더 유리한 건, 아무데서나 변수 선언을 자유롭게 할 수 있다는 것 정도일 것이다.

그러나 겨우 그 정도로는 불리한 점이 여전히 유리한 점보다 더 많은 것 같다. 생성자와 소멸자, 오버로딩, 템플릿 등으로 더 알아보기 힘든 함축적인 코드를 만드는 건 상당한 규모가 있는 큰 프로그램에서나 위력을 발할 것이고, 긴 선언부의 노출이 불가피하여 무리일 듯.

옛날에는 대회 규정의 허를 찌른 엽기적인 꼼수 작품도 좀 있었다.
이 대회는 1984년에 처음 시작되었는데, 그때 입상작 중에는 main 함수를 함수가 아니라 기계어 명령이 들어있는 배열로 선언해 놓은 프로그램이 있었다(1984/mullender). 이건 기계 종류에 종속적일 뿐만 아니라 요즘 컴파일러에서는 링크 에러이기 때문에, 그 뒤부터는 대회 규정이 바뀌어 이식성 있는 코드만 제출 가능하게 되었다.

그리고 1994년에는 콰인이랍시고 0바이트 소스 코드가 출품되었다(1994/smr). 소스가 0바이트이니, 아무것도 출력하지 않아도 콰인 인증..;; 이건 충분히 참신한 덕분에 입상은 했지만 그 뒤부터는 역시 소스 코드는 1바이트 이상이어야 한다는 규정이 추가되었다. 빈 소스 파일을 빌드하려면 빌드 옵션도 좀 미묘하게 변경을 해야 했다고 한다.

이런 코드를 작성하기 위해서는 모든 변수와 함수를 한 글자로 표현하는 것부터 시작해서 평범한 계산식을 온갖 포인터와 비트 연산자로 배배 틀기, 숫자 테이블 대신 문자열 리터럴을 배열로 참고하기(가령, "abcd"[n]) 같은 건 기본 중의 기본 테크닉이다. 그리고 그걸 아스키 아트로 바꾸는 능력이라든가, 원래 오리지널 프로그램을 기가 막히게 짜는 기술은 별개이다. 이런 코드를 만드는 사람은 정말 코딩의 달인 중의 달인이 아닐 수 없다.

이 대회는 전통적으로 외국 해커 덕후들의 각축장이었다. 그러나 지난 2012년도 대회에서는 자랑스럽게도 한국인 입상자가 한 명 배출되었는데, 본인의 모 지인이다. 그가 출품한 프로그램은 영어로 풀어 쓴 숫자를 입력하면(가령, a hundred and four thousand and three hundred and fifty-seven) 그걸 아라비아 숫자로 바꿔 주는 프로그램(104357). 코드를 보면 저게 어딜 봐서 숫자 처리 프로그램처럼 생겼는가. -_-

코드를 대충 살펴보면, long long이 바로 등장하는 데서 알 수 있듯, 나름 32비트 범위를 벗어나는 큰 자리수까지 지원한다. 문자열 리터럴을 배열로 참고하는 것도 곧바로 쓰였음을 알 수 있다.
그리고 옛날의 C 시절에 허용되었던 관행이었다고 하는데, 함수의 인자들을 아래와 같은 꼴로 선언하는 게 이 대회 출품작에서는 종종 쓰인다고 한다.

int func(a,b) int a, char *b; { ... }

하긴, C/C++이 기괴한 면모가 자꾸 발견되는 건 어제오늘 일이 아니다.
a[2]뿐만이 아니라 2[a]도 가능하다든가,
#include 대상으로 매크로 상수도 지정 가능하다든가,
C++의 default argument로 0이나 -1 같은 것뿐만 아니라 사실은 아예 함수 호출과 변수 지정도 가능하다는 것..
switch문의 내부에 for 같은 다른 반복문이 나온 뒤에 그 안에 case가 있다던가..;;

정말 약 빨고 만든 언어에다 약 빨고 코딩한 개발자라고밖에 볼 수 없다.
나로서는 범접할 수조차 없는 이상한 프로그래밍 대회에 한동안 엄청 관심을 갖더니 결국 입상해 버린 그의 오덕력에 경의를 표한다. 그저 놀라울 뿐이다. 이 정도로 소개하고 띄워 줬으니, 그분이 이 자리에 댓글로 소환되는 걸 기대해 보겠다. 아무래도 한국인 다윈 상 수상자가 배출된 것보다는 훨씬 더 자랑스러운 일을 해낸 친구이지 않은가. ㄲㄲㄲㄲㄲㄲㄲ

뭐, 입상했다고 당장 크게 부와 명예가 뒤따르는 건 아니겠지만, 팀장이나 임원이 IOCCC에 대해서 아는 개발자 출신인 회사에 지원할 때 “나 이 대회 입상자요!”라고 이력서에다 써 넣으면 그 이력서의 메리트는 크게 올라갈 수밖에 없을 것이다. 실제로 IOCCC 같은 잉여로운 대회에 참가하는 geek 중에는 구글, MS급 회사 직원도 있고, 사실 이런 대회에 입상할 정도의 guru급 프로그래머가 일자리를 못 구해 걱정할 일은 절대 없을 테고 말이다.

이런 대회에 더 관심 있으신 분은, IOCCC의 국내 저변 확대를 위해 애쓰고 있는 저 친구의 소개 페이지를 참고하시기 바란다.

Posted by 사무엘

2013/04/10 19:20 2013/04/10 19:20
, , , ,
Response
No Trackback , 6 Comments
RSS :
http://moogi.new21.org/tc/rss/response/816

열차 좌석 배당 알고리즘

열차의 승차권을 구입하면 좌석은 어떤 식으로 배당될까?
객차 하나당 좌석은 차량에 따라 60~70개 정도가 있으며, 열차 한 편성은 일반실만 생각하더라도 최하 4량부터 시작하고 KTX의 경우 거의 15량에 가깝다. 수백 개의 좌석들은 어떤 순서와 원칙대로 승객에게 팔려 나갈까?

난 철덕후로서 그 알고리즘이 예전부터 굉장히 궁금했다. 여러분은 그렇지 않은가?

버스 정도면 그냥 아무렇게나 랜덤으로 배당해도 별 무리가 없을 것이다.
우등 고속버스는 가장 쉽다. 승차 정원부터가 30명이 채 안 되는 소규모인 데다, 좌석이 구조적으로 2개짜리와 1개짜리로 나뉘어 있으니 말이다.

단독 승객에게는 진행 방향 기준으로 오른쪽의 단독 좌석부터 먼저 배당해 주고, 그게 매진되거나 2인 승객이 있으면 2인 좌석을 준다. 상석인 맨 앞자리는 약간 나중에 팔리도록 다른 가중치를 부여하고, 반대로 최악의 자리인 맨 뒷자리는 최하위 우선순위로 팔리게 하면 될 것이다.

그러나 열차는 단순하게만 좌석을 배당해서는 대략 곤란하다.
1부터 n호차까지, 그리고 진짜 무식하게 1번부터 m호석까지 앞에서 뒤로 순서대로 꽉꽉 승객을 채워 넣어서 뒤의 객차는 텅 빈 채로 달리게 할 리는 없을 테고..

그렇다고 좌석을(특히 단독 승객) 완전 랜덤으로만 여기저기 들쭉날쭉으로 배당하면 좌석의 단편화(fragmentation)가 너무 심해진다. 그래서 승객이 얼마 타지도 않은 상태인데 이따금씩 타는 2인 이상의 다수 승객은 이어진 좌석을 못 구해서 서로 찢어져서 앉아야 하는 일이 벌어질 수 있다.

결국 본인이 추측하기로는 열차의 좌석 배당은 저 양 극단의 중간을 절충하는 방식으로 이뤄질 것 같다.
두세 개의 객차를 묶음으로 나눠서 한 묶음 안에서 좌석을 무작위로 배당한 뒤, 그 묶음의 좌석이 다 매진되면 다음 묶음으로 간다. 각 묶음은 1~3호차, 4~6호차, 7~9호차 같은 규칙으로 만들 수도 있고, 반대로 1, 4, 7호차와 2, 5, 8호차, 3, 6, 9호차 같은 규칙으로 만들 수도 있다.

그리고 각 객차 안에서는 전체의 50~60% 정도는 단독 승객이 무작위로 띄엄띄엄 앉을 수 있게 배려한다. 즉, 2개짜리 좌석이라도 한 자리에 단독 승객이 있으면 거기는 일단 건너뛰고 다른 빈 자리를 찾는다는 뜻이다. 그러나 나머지 자리는 가능한 한 2인 승객이 한꺼번에 찜할 수 있게 비워 두며, 한 객차의 좌석의 10~20% 정도는 마치 KTX 동반석처럼 4인 가족이 연속해서 앉을 수 있게, 가능한 한 1~2인 승객에게 금세 팔리지 않도록 비워 둔다.

단독 승객의 경우 창측 좌석이 내측 좌석보다 먼저 팔리게 하는 건 기본이다. 또한 열차에서는 출입문과 가까운 맨 앞이나 맨 뒤 좌석이 '안 좋은 자리'이므로 이것 역시 다른 좌석이 모두 팔린 뒤에 나중에 팔리게 해야 할 것이다.
단독 승객용 좌석과 2인 이상 승객용 좌석 영역을 정하는 것 역시 '엿장수 마음대로' 무작위로 하면 되며, 그 비율 역시 평소에 승차권이 팔리는 단위 통계를 근거로 합리적으로 정하면 될 것이다.

저런 균형적인 요소에 덧붙여 환승 동선도 고려 대상이 된다.
국내의 예를 들면 KTX 천안아산 역과 장항선 아산 역은 남쪽 끝에서 만난다. 그리고 KTX는 한 편성이 무려 400m가 약간 안 되는 매우 긴 열차이다. 그렇기 때문에 경부선 KTX를 타다가 천안아산 역에서 장항선으로 환승하는 승객은 부산 방면(하행) 열차의 경우 최대한 앞쪽 객차로 좌석이 배당되고, 서울 방면 열차는 뒤쪽 객차로 좌석이 배당된다. 지하철에서 환승을 빨리 할 수 있는 객차의 위치와 정확히 같은 개념이며, 한국 철도도 그 정도 센스는 이미 갖추고 있다.

이 정도면 내가 보기에 열차 좌석 배당 전략을 짜는 건, 마치 열차 시각표를 짜는 것에 필적하는 철도 영업 기술의 결정체가 될 수도 있을 것 같다.
현실성 있는 열차 운행 시각표를 짜기 위해서는 그 나라의 철도 인프라와 지형 특성, 차량 제원, 승객 패턴 등의 알토란 같은 영업 기밀이 총동원되어야 한다. 이런 걸 계획하는 건 인원을 더 투입한다고 신속하게 되는 게 아니며, 핵심 똘똘이 인력 한두 명이 다 도맡아 한다.

좌석 배당도 마찬가지일 거라는 말이다. 철덕이라면 반드시 정복해야 하는 분야 중 하나 되시겠다.
비행기는 무게 배분이(한쪽에만 승객 무게가 지나치게 쏠리지 않게) 좌석 배당에 감안되는 요인이라고 하는데, 철도는 무게 배분 걱정은 할 필요가 없는 대신 길다는 특성상 다른 변수가 존재하는 셈이다.

자, 여기까지만 글을 쓰려고 했는데, 빈 좌석에다 승객을 일정 규칙대로 채워 넣는 과정을 생각하자니 컴퓨터그래픽에서 중요하게 다뤄지는 알고리즘 분야가 문득 떠오르더라.
바로 디더링이다.

디더링은 적은 수의 색깔을 섞어서 더 화려한 색깔을 아쉬운 대로 표현하는 기법이다. 색을 물리적으로 섞을 수는 없으니 결국 서로 다른 색깔을 번갈아가며 늘어놔야 하는데, 한 색깔이 뭉치는 게 아니라 서로 다른 색깔들끼리 최대한 고르게 퍼지도록 픽셀을 배열해야 한다.

본인은 과거에 Windows 3.x 시절에 그림판에서 임의의 RGB 값을 주면 그 색을 16컬러만으로 디더링하여 표현하는 걸 보고 무척 신기해했었다. 가령, 흑에서 백으로 단계를 증가시킬 때, 검은색에서 흰색 점이 차츰 늘어나는 순서가 어떻게 정해지는지가 무척 궁금했다.

그 규칙을 디더링에서 threshold matrix라고 부른다. 일반적인 그래픽 프로그램에서는 8*8짜리를 사용한다. (출처는 위키백과) 저기서 1부터 16까지의 점을 순서대로 채우면 25% 음영이 그려지고, 32까지 채우면 흑백이 딱 반반씩 번갈아가며 등장하는 50% 음영이 되는 식이다.

사용자 삽입 이미지
처음에는 4픽셀 간격으로 띄엄띄엄 점을 그리고, 나중에는 그 사이의 4픽셀 간격을 채우는 식으로, 점들이 뭉치지 않고 어떤 경우에도 최대한 흩어져서 퍼져 있게 한다. 임의의 격자 크기가 주어졌을 때 threshold matrix를 생성하는 프로그램을 만들 수도 있을 법해 보이는데 그리 만만한 일은 아닌 것 같다. 마방진도 아니고 말이다.

더 나아가 임의의 색을 16컬러 디더링 패턴으로 표현해 내는 프로그램을 직접 짜 보면 어떨까? 주어진 색을 가장 가깝게 표현할 수 있는 2색 또는 3색 조합을 구한 뒤, 그 비율만큼 threshold matrix를 각각의 색으로 채우면 될 것이다. 색조합을 구하는 것은 미지수의 개수가 식의 개수보다 더 많아서 답이 하나로 딱 떨어지지 않는 부등식이 될 터이니, LP(선형 계획법) 같은 계산 기법이 동원돼야 하지 않을까 싶다.

그렇게 threshold matrix만을 정석대로 적용하면 ordered dithering이 된다. 그러나 그것만으로는 그림이 칙칙하고 보기가 안 좋기 때문에, 디더링된 색깔의 픽셀이 인접 픽셀에 시각적으로 끼치는 영향을 감안하여(error diffusion) 더 정교하게 디더링을 수행하는 알고리즘이 실생활에서 쓰인다. 더 깊게 들어가는 건 이 글의 범위를 벗어나므로 자세한 설명을 생략하겠다.

뜬금없이 디더링 얘기를 꺼낸 이유는.. 저렇게 디더링 점을 찍어 나가는 게 마치 열차 좌석을 배당하는 것과 비슷한 심상이 느껴져서이다. 열차 좌석의 점유 여부를 흑백 픽셀로 표현하고 시간이 흐름에 따라 픽셀들의 상태를 표시하는 시뮬레이션을 돌려 보면 재미있을 것 같다. 한쪽은 검은 색이 듬성듬성 있고, 한쪽은 검은 색이나 흰 색이 좀 연속해서 있겠지 아마?

철도의 좌석 배당 알고리즘과 래스터 그래픽의 디더링 알고리즘은 서로 따로 생각하고 있었던 주제인데 이렇게 한 글로 연결이 됐다. 마치 예전에 내가 열차의 급행 등급과 셸 정렬을 한데 묶어서 글을 썼듯이 말이다. 참 신기한 일이 아닐 수 없다. ㅋㅋㅋㅋ

Posted by 사무엘

2013/04/08 08:18 2013/04/08 08:18
, , , ,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/815

아동 유괴 범죄 생각

* 어느 카테고리에다 넣어야 할지가 굉장히 모호한 글이 돼 버렸다.. -_-

1. 여성이 저지른 아동 유괴 범죄

세상에 수많은 흉악 범죄 중에서도 어린이 납치· 유괴 범죄의 죄질은 가히 톱클래스 급이라 할 수 있다. 피해자 부모에게 씻을 수 없는 희망고문과 상처를 안기고 그 후유증 또한 이루 말할 수 없다.

우리나라는 1991년에 개구리 소년뿐만 아니라 이 형호 군 납치· 살해 사건이 유명한 영구미제 사건으로 알려져 있으며 이 이야기는 <그놈 목소리>라는 영화로도 제작되었다. 용의자는 애를 납치 당일에 애초에 죽여 버렸으면서 그 후에 집요하게 집으로 낚시성 금품 요구 전화를 걸었다는 점 때문에 사람들의 분노를 더욱 이끌었다.

그런데 이런 끔찍한 범죄는 꼭 한눈에 보기에도 양아치+싸이코패스 기질이 충만한 젊은 남자만 저지른 게 아니라는 점이 더욱 충격적이다.
1997년, 박 초롱초롱빛나리 양을 공범도 없이 혼자 유괴· 살해한 전 현주는 당시 겨우 20대 후반의 유부녀였고 게다가 임산부였다.

한때 경찰이 용의자가 있다는 단서를 확보한 카페를 급습해서 손님들을 검문했었다. 그러나 다른 손님들과 마찬가지로 용의자인 전 씨도 보내 줄 수밖에 없었다. 임산부지, 아픈 체하지, 이 상황에서 더 조사를 하는 건 100% 공권력 남용으로 여론을 악화시킬 지경이었으니, 이때 용의자를 놓친 것은 절대로 경찰의 무능 탓을 할 수 없었다.

그래도 이 사람은 프로 범죄자가 아니었기에 범행에 여러 허점을 드러내면서 잡히긴 했다. 범행 동기는 간단히 요약하면 그냥 거짓말+허영심을 채우기 위한 돈 때문이었다. 그랬는데 납치한 애가 울고불고 하면서 자기가 통제를 못 할 지경이 돼 가자 살해하게 된 것.

순간의 잘못된 선택으로 인해 가해자의 인생도 완전히 끝났다. 그녀는 무기징역을 선고받고 지금까지 복역 중이다. 남편으로부터는 당연히 이혼 당하고, 배 속에 있던 아이의 양육권도 빼앗겼다.

이 사건 이후, 아이 이름을 너무 튀거나 특이하게 짓는 관행마저 사라졌을 정도라고 한다.
마치 지존파 일당이 검거된 이후 그랜저의 판매량이 잠시 감소한 것과 비슷한 맥락..;; (그랜저급 이상을 굴리는 부유층을 범행 대상으로 삼았다고 그랬으니)

2. 곽 재은 양 유괴· 살해 사건

그런데 박 나리 양 사건은 1990년 6월에 벌어진 곽 재은 양 유괴· 살해 사건과 거의 똑같은 판박이였다. 가해자 홍 순영은 스펙과 직장을 거짓으로 위조해서 대학생 신세를 하고 남자친구까지 사귀었던 20대 아가씨였다. 그랬는데 자신의 정체가 탄로나게 생기고 결혼에도 애로사항이 꽃피게 되자, 이 상황을 돈으로 무마하려고 우연히 이름을 알게 된 어느 유치원생을 꾀어 냈다. 부모를 사칭하면서 집에 급한 일이 생겼으니 애부터 먼저 밖에 내보내 달라고 말이다.

그랬는데 공범도 없이 혼자서 애를 이리저리 데리고 다니는 게 쉬운 일이 아니었다. 아이가 울면서 자기를 집에 보내 달라고 요구하는 등, 상황이 위급해지자 가해자에게도 뭔가 마가 씌였다. 그녀는 아무도 없던 숙명여대 모 건물 안에서 결국 아이를 목졸라 죽이고 말았다. 그리고는 태연하게 아이의 집으로 전화를 걸어(죽이기 전에 먼저 물어 본 연락처) 금품을 요구하였으나, 은행에서 그 돈을 인출하는 모습이 덜미를 잡히는 바람에 결국 잡혔다.

애당초 프로 범죄자들이 하는 것처럼 경찰의 추적을 피하면서 현금만을 교묘히 전달받는 꼼수 따위는 생각할 겨를도 없었고, 대놓고 서울 시내 한복판에서 은행 거래를 할 정도로 홍 순영은 범행 수법도 허술하기 짝이 없었다.

경찰에 잡히고 나서야 그녀는 자기가 얼마나 엄청난 짓을 저질렀는지 깨닫는 듯했고, 이제 멘탈이 완전히 붕괴되고 말았다. 바로 자살을 생각했다. 지하철역에서 공범을 만나기로 약속을 했다면서 경찰에게 거짓말을 하고는 지하철역 승강장으로 진입하는 열차를 향해 몸을 던졌다. 그러나 기관사가 필사적으로 열차를 세운 덕분에 머리를 약간 다치기만 하고 목숨을 건졌다. 이때 그녀가 죽어 버렸다면 아이의 시체도 못 찾게 될 뻔했다.

사용자 삽입 이미지
신 정아처럼 횡설수설과 거짓말을 거듭하던 전 현주와는 달리, 홍 순영의 최후는 더욱 비참했다. 그녀는 이제 걷잡을 수 없는 멘붕과 죄책감에 사로잡혔고, 교도소에서도, 재판 받으면서도 그냥 울부짖으면서 자기를 제발 사형시켜 달라는 말밖에 안 했다. 당시의 기록을 보면 종교인 성직자를 통한 교화 같은 것도 별 효과가 없었던 모양이다.

이때는 그렇잖아도 '범죄와의 전쟁'이 선포되었던 노 태우 정권 시절이었다. 그녀의 원대로 결국 사형 선고가 내려졌고, 그녀는 이듬해인 1991년 말에 겨우 24세의 나이로 형장의 이슬로 사라졌다. 유언도, 장기 기증도 없이 마지막 순간까지도 고개를 저으며 울기만 하면서 정말 고통스럽고 처절하고 허무하게 최후를 마쳤다.

본인은 인간으로서 그녀의 혼에(도) 동정과 연민을 느낀다.
거짓과 허영으로 가득찬 채 빗나간 탐욕을 채우려고 한 어린이의 생명을 빼앗고, 다른 단란하던 가정을 고통의 나락으로 떨어뜨린 그 인생을 동정할 생각은 절대 없다. 사형은 성경적으로도 감정적으로도 정말 정당한 인과응보이긴 했다. 성경에도 있잖은가, “욕심이 잉태하여 죄를 낳고, 죄가 완료되면 사망을 낳는다”고 말이다(약 1:15).

그러나 죄책감에 짓눌린 채 후회만 하는 건 성경이 말하는 회개가 아니고 구원을 이루지도 못한다.
저건 그냥 가룟 유다가 죽듯이 죽은 거다. 이판사판 다 끝났고 부끄러워서 세상 사람들 볼 낯이 없고 꿈이고 희망이고 없는 여건이 됐으니, 이제 살 이유가 없어서 죽겠다는 심정이다.
그런데 그렇게 죽고 나서는, 그럼 하나님은 무슨 낯으로 보려고?

영적으로 좀 날카롭게 진단하자면, 내가 보기에 홍 순영은 애를 유괴하고 살해할 때뿐만 아니라, 나중에 멘붕 상태에서 징징거리는 것도 줄곧 '마'에 씌인 상태에 가까웠다. 자유가 있을 때는 마음껏 나쁜짓을 하게 하다가, 그 자유를 빼앗기고 죄에 대한 대가를 치를 때가 됐을 때는 주체 못 할 죄책감으로 사람을 재기의 여지 없이 완전히 파멸시켜 버리는 것이 마귀의 역사이다. (아니면 죄책감을 아예 안 느끼는 진짜 인면수심 마인으로 바꾸거나.)

둘 다 이성이 마비된 상태인 건 비슷하다. 난 그녀의 “그 상태”가 참 가련하고 불쌍하다는 것이다. 뭐, 가해자의 불우한 성장 배경이 어떻고, 가해자도 사회 시스템의 피해자네 하는 개 풀 뜯어먹는 차원이 아니다. 아시겠는가?
오히려, 홍 순영 같은 일부 '서툴고 여린' 범죄자를 빌미로, 무슨 현행 사법 시스템이 너무 잔인하고 비인권적이네 하면서 사형 제도를 없애네 뭐네 하는 개드립이 일게 하는 건 마귀의 또 다른 역사이다. 이게 오늘날 영적 전투의 실상인 것이다.

민감한 얘기가 또 길어졌으니 다시 본론으로 돌아오자면,
이런 사건을 겪은 나라들은 어린이를 상대로 실시하는 안전 교육 매뉴얼이 바뀌었을 정도였다. 전혀 양아치처럼 생기지 않았고 험상궂은 아저씨도 전혀 아닌 여성조차도 얼마든지 어린이를 유괴· 살해할 수 있다는 게 입증됐기 때문이다.

3. 사형 집행의 부활을 꿈꾸며

우리나라는 잘 알다시피 김 영삼 정권의 말기인 1997년 12월 30일에, 2013년 현재 대한민국 최후의 대규모 사형이 집행되었다. 다음 대통령에게 부담을 안 주기 위해 일부러 집행한 건데 아주 잘한 결정이다.

단, 남아 있던 사형수들을 다 죽인 건 아니고, 자기 정권 전부터 남아 있던 20여 명의 사형수들만 죽였다. 세상에 대한 증오심 때문에 1991년에 여의도 광장에서 칼부림 정도가 아니라 아예 승용차를 질주해서 어린이 2명을 죽게 한 김 용제도 이때 죽은 사형수 중 하나이다.

그리고 김 영삼 정권 시절에 잡힌 지존파 멤버들은 워낙 죄질이 나빠서 그 전에 이미 다 사형이 집행되어 죽었다. 오로지 살인을 목적으로 혈연 관계가 없는 사람들이 똘똘 뭉쳐 전문적인 폭력 조직을 결성한 것은 세계의 범죄 역사를 통틀어서도 드문 사례라고 한다. 중국이 아편 전쟁 때문에 마약에 대한 역사적 트라우마가 있듯, 한국은 '반국가단체'에 대한 트라우마가 있는 듯하다(북한이라든가.. 북한이라든가..). '폭력행위등 처벌에 관한 법률'을 적용하면 사실 조폭을 결성한 것만으로도 우두머리는 최고 사형에 처해질 수 있다.

그 시절 이후로 우리나라는 한 번도 사형이 집행되지 못하고 사법 정의는 땅으로 곤두박질치고 말았다.
그에 반해 전툴루, 전땅크 시절은 비록 다른 흑역사도 많았을지언정 사법 정의에 관한 한은 천국이었다.

약간 인민재판 같은 사례이긴 하지만, 이 윤상 군 유괴· 살해 사건의 경우 아직 살인인지 감금치사인지 확실히 밝혀지지도 않은 상태에서 대통령이 자기 직위를 걸고 항소심을 묵살시켰으며, 재판부에다 압력을 넣어 1~3심에서 모두 피의자에게 사형을 때려서 확인사살을 해 버렸다. 나한테 당해 보지도 않고 말이야. 사전에 “아이를 살려 보내면 너는 살고, 아이가 죽으면 너도 죽는다. (빨랑 자수해라.)”라고 진짜 전땅크스러운 대국민 담화를 대통령이 친히 내린 상태였기 때문에, 그는 약속을 이렇게 지켰다. -_-;;;

살인인지 감금치사인지는 그리 중요하지 않았으며, 대통령의 경고를 씹었다는 괘씸죄 때문에 어차피 사형이 떨어졌다. 마치 군인의 탈영이 나중엔 탈영 자체의 공소시효는 소멸하더라도, 복귀 명령 불복종죄 때문에 처벌 대상이 되듯이 말이다.
피해자 유가족은 이것 덕분에 그나마 얼마나 큰 위로를 받았으며 전툴루에게 개인적으로 감사하게 되었을까? 이게 1983년의 일이다.

그 5공 시절에는 흔히 생각하듯 정치범이나 사상범도 아니고, 심지어 살인을 전혀 저지르지 않은 0 kill 상태에서도 사형이 떨어져서 집행된 적이 있었다.
가정집을 털고 가족들이 보는 앞에서 임산부· 여대생을 강간해 온 3인조 강도 상습범(황 인규, 최 윤성, 최 성훈)은 비록 살인 혐의는 없으나 10수 차례나 저지른 강도· 강간의 죄질이 극히 불량하다는 법무부의 코멘트와 함께 1985년 11월, 얄짤없이 사형을 당했다. 이 판결에 대해 잘못됐다고 이의가 제기된 경우는 지금까지 전혀 없다.

이렇듯, 군사정권 시절에 벌어진 일이 다 나쁘기만 했다는 건 큰 편견이며 오산이다.
내가 광주의 학살자(?.. 뭐 이 표현 자체에도 논란의 여지는 있지만)를 옹호한다고 해서 기분 나빠하는 독자가 있을지 모르겠다. 그러나 그만큼 반대편 성향의 위정자들도 만만찮게 병크를 저지른 게 많으며, 세상 한켠에는 당신과 반대의 견해를 가질 수밖에 없게 만드는 요인도 있다는 것을 독자들은 간과하지 말아야 할 것이다.

특히 우리나라의 높으신 분들이 정말로 저출산을 걱정하신다면,
이 어려운 여건 속에서 애를 낳아서 키우는 부모의 권리를 정말 존중해야 하지 않겠는가?
나라의 미래를 인질로 잡고 장난치고 짓밟고 가정을 파괴하는 범죄자들에게 생명은 생명으로 일벌백계를 내려 주길 간절히 바란다.

피해자의 유가족들은 예수도, 부처도, 공자도 아닌 평범한 일반인들이다. 세상 정부는 무슨 구원이나 내세· 영생을 논하는 조직이 아니라, 이 땅에서의 시민들 생명을 지키고, 질서과 치안을 문란케 한 자에 대한 공공의 보복을 집행할 책임이 있지 않은가?
전땅크를 비판하고 욕하고 싶으면 이런 기초적인 거 하나라도 전땅크보다 잘해 달란 말이다.

Posted by 사무엘

2013/04/05 08:32 2013/04/05 08:32
, , , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/814

지금으로부터 거의 3년 전, 이 블로그가 개설된 지 얼마 되지 않았던 시절에 본인은 C++의 매우 기괴-_-한 문법인 다중 상속멤버 포인터(pointer-to-member)에 대해서 제각각 따로 글로 다룬 적이 있었다.
이제 오늘은, 그 기괴한 두 물건이 한데 합쳐지면 언어의 디자인이 얼마나 더 흉악해지는지를 보이도록 하겠다.
그 내력을 알면, C++ 이후의 객체지향 언어에서 다중 상속이 왜 봉인되어 버렸는지를 이해할 수 있을 것이다. 뭐, 이미 다 아는 분도 있겠지만 복습 차원에서.

클래스의 멤버 포인터는 그 가리키는 대상이 변수이냐 함수이냐에 따라서 내부 구조가 크게 달라진다는 말을 예전에 했었다. 함수일 때는 포인터답게 말 그대로 실행될 함수의 메모리 위치를 가리키지만, 변수일 때는 이 멤버가 this로부터 얼마나 떨어져 있는지를 나타내는 정수 오프셋에 불과하다. &POINT::x 는 0, &POINT::y는 4 같은 식.
그래서 비주얼 C++은 x64 플랫폼에서도 단순 클래스의 멤버 변수 포인터는 뜻밖에도 8바이트가 아닌 4바이트로 처리한다. UNT_PTR이 아니라 그냥 unsigned int라고 본 것이다.

그런데 다중 상속이 동반된 클래스는 '단순' 클래스라고 볼 수가 없어지며, 그런 클래스를 대상으로 동작하는 멤버 포인터는 내부 메커니즘이 굉장히 복잡해진다. 멤버 변수야 오프셋이 바뀌니까 그렇다 치지만, 멤버 함수의 포인터도 데이터 오프셋의 영향을 받는다. 비록 함수 자체는 오프셋을 타지 않고 고정된 메모리 주소이긴 하지만, 멤버 포인터가 어느 함수를 가리켜 부르느냐에 따라 그때 그때 this 포인터를 잘 보정해서 줘야 하기 때문이다.

다음 코드를 생각해 보자.
참고로, class 대신 struct를 쓴 이유는 public: 을 따로 써 주는 귀찮음을 해소하기 위해서일 뿐이다. (C#은 struct와 class의 용도가 구분되어 있는 반면, C++은 전혀 그렇지 않으므로.)

struct B {
    int valB; void functionB() { printf("functionB: %p\n", this); }
};
struct C {
    int valC; void functionC() { printf("functionC: %p\n", this); }
};

struct D: public B, public C {
    int valD; void functionD() { printf("functionD: %p\n", this); }
};

그 뒤,

D ob;
void (D::*fp)();
printf("this is %p\n", &ob);
printf("sizeof pointer-to-member is %d\n", sizeof(fp));

fp = &D::functionB; (ob.*fp)();
fp = &D::functionC; (ob.*fp)();
fp = &D::functionD; (ob.*fp)();

코드를 실행해 보면, 놀라운 결과를 볼 수 있다.
이제 fp의 크기가 포인터 하나의 크기보다 더 커졌다.
비주얼 C++ 기준으로, '포인터+int'의 합이 된다. 그래서 x86에서는 8바이트, x64에서는 12바이트.

게다가 중요한 건, functionC를 실행했을 때만 this의 값이 달라져 있다는 것이다.
이건 뭐 다중 상속의 특성상 어쩔 수 없는 면모이며, 멤버 함수를 ob.functionC()라고 직접 호출할 때는 컴파일러가 알아서 처리해 주는 기능이긴 하다.
하지만, 직접 호출이 아니라 멤버 포인터를 통한 간접 호출을 할 때는 이걸 어떻게 구현해야 할까?

결국은 멤버 함수 포인터 자체에 추가 정보가 들어갈 공간이 있어야 하고, 그 정보는 포인터에다가 함수에 대한 대입이 일어날 때 implicit하게 따로 공급되어야 한다.
다중 상속을 받은 클래스의 멤버 함수를 가리키는 포인터는 this 보정을 위한 정수 오프셋이 내부적으로 추가된다. 이제 fp는 단일 포인터 변수라기보다는 구조체처럼 바뀌었다는 뜻이다.

이 fp에다가 functionB나 functionD를 대입하면 그 멤버 함수의 주소만 대입되는 게 아니라, 숨겨진 오프셋 변수에다가도 0이 들어가며(보정할 필요가 없으므로), functionC를 대입하면 그 주소와 함께 오프셋 변수에다가도 0이 아닌 값이 같이 대입된다. 그리고 실제로 fp 호출을 할 때는 this 포인터에다가 보정이 된 값이 함수로 전달된다.

이야기는 여기서 끝이 아니다. 설상가상으로 가상 상속까지 추가된다면?
내가 클래스를 A가 아니라 B에서부터 시작한 게 이것 때문이다. 맨 앞에다가 드디어 다음 코드를 추가하고,

struct A {
    int valA;
    void functionA() { printf("functionA: %p\n", this); }
};

앞에서 썼던 B와 C도 A로부터 가상 상속을 받게 고쳐 보자.

struct B: virtual public A { ... }
struct C: virtual public A { ... }

이것도 물론 추가하고.

fp = &D::functionA; (ob.*fp)();

이렇게 해 보면..
비주얼 C++ 기준 fp의 크기는 더욱 커져서 '포인터+정수 2개' 크기가 된다. x86에서는 12바이트, x64에서는 16바이트.
다중 상속만 있을 때는 함수 말고 변수의 멤버 포인터는 크기가 변함없었던 반면, 가상 상속이 가미되면 변수 멤버 포인터도 이렇게 '크기 할증'이 발생한다. 대입 연산이나 함수 호출 때 몰래 같이 발생하는 일도 더욱 많아지며, 이 현상을 좀 유식하게 표현하면 cost가 커진다.

그 이유는 어렴풋이 유추할 수 있을 것이다. 가상 상속이라는 건 말 그대로 기반 클래스의 오프셋이 클래스의 인스턴스별로 동적으로 변할 수 있다는 뜻이다. this 포인터 보정이 뒷부분 파생 클래스의 정확한 위치를 파악하기 위해서 발생하는 일이라면, 가상 상속 보정은 앞부분 기반 클래스의 위치를 파악하는 것이 목적이다.

이런 사정으로 인해 functionA()도 원래 개체의 주소와는 다른 주소를 받으며, 이것은 functionC()가 받는 주소와는 또 다르다.
다만, pointer-to-member는 가상 함수와는 기술적으로 전혀 무관하게 동작하기 때문에, 가상 함수가 존재하는 클래스라고 해서 오버헤드가 추가되는 건 없다. 함수 멤버 포인터로 가상 함수를 가리키면, 아예 가상 함수 테이블을 참조하여 진짜 함수를 호출하는 wrapper 함수가 따로 만들어져서 그걸 가리키고 있게 된다.

요컨대 비주얼 C++은 단순 클래스, 다중 상속만 있는 클래스, 거기에다 가상 상속까지 있는 클래스라는 세 등급에 따라 멤버 포인터를 관리한다. 다만, 함수가 아닌 변수 멤버 포인터는 가상 상속 여부에 따라 두 등급으로만 나누는 듯하다. 이 정도면, 이 글을 쓰는 본인부터 이제 머리가 핑그르르 도는 것 같다.

이제 마지막으로 생각해 볼 문제가 있다. C++은 클래스의 명칭 선언만 하는 게 가능하다는 점이다.

class UnknownBase;
class UnknownDerived;

굳이 클래스의 몸체를 몰라도 이 클래스에 대한 포인터 정도는 선언이 가능하다. 그렇기 때문에 명칭 선언은 컴파일 때 헤더 파일간의 의존도를 줄이고 모듈간의 독립성을 높일 때 요긴하게 쓰이는 테크닉이다.
다만, 여러 클래스들을 명칭 선언만 하면 이들간의 상속 관계도 아직 밝혀지지 않기 때문에, 실질적인 기반 클래스와 파생 클래스 사이에 암시적인 형변환이나 static_cast, dynamic_cast 따위를 쓸 수 없다는 점도 주의해야 한다.

게다가 이렇게 명칭만 달랑 선언된 클래스에 대해서 멤버 포인터를 선언하면..
컴파일러는 이 클래스가 다중 상속이 존재하는지, 가상 상속이 존재하는지 같은 걸 알지 못한다!
그렇다고 무식하게 에러 처리하며 멤버 포인터의 선언을 거부할 수도 없는 노릇이니,
컴파일러는 가장 보수적으로 이 클래스가 어려운 요소들은 모두 갖추고 있을 거라고 생각하고 가장 덩치 크고 복잡한 등급을 선택할 수밖에 없다.

나중에 사용자가 추가 인클루드를 통해 클래스의 몸체를 선언하여, 이 클래스는 단순한 놈이라는 게 알려지더라도 한번 복잡하게 결정되어 버린 타입 구조는 다시 바뀌지 않는다.
게다가 이렇게 unknown 클래스에 대한 멤버 포인터는 단순히 '가상 상속 클래스' 등급이 아니라, 메타 정보가 추가로 붙는지 비주얼 C++에서는 함수 기준으로 x86에서 무려 16바이트를 차지하며, x64에서는 24바이트를 차지하게 된다. 포인터 둘, int 둘의 합이다.

printf("%d\n", sizeof(void (UnknownDerived::*)() ));

물론, 멤버 포인터부터가 굉장한 레어템인데, 몸체도 없이 명칭 선언만 된 클래스에 대해서 멤버 포인터를 덥석 들이대는 코딩을 우리가 실생활에서 직접 할 일은 극히 드물다. 하지만 딱 machine word와 동일한 크기를 기대했던 멤버 함수 포인터가 3~4배 크기로 갑자기 뻥튀기되고 생각도 못 했던 오버헤드가 추가되는 일은 없어야 하겠기에, 비주얼 C++은 역시 비표준 확장을 통해서 이 문제에 대한 해결책을 제시하고 있다.

그것은 바로 _single_inheritance, _multiple_inheritance, _virtual_inheritance라고 참 길게도 생긴 키워드.
클래스를 명칭 선언만 할 때

class _single_inheritance UnknownDerived;

이런 식으로 써 줌으로써 “이놈은 다중 상속 같은 귀찮은 요소가 없는 클래스이다. 따라서 얘에 대한 멤버 포인터는 추가 오프셋이 없는 제일 간단한 등급으로 만들어도 OK다”라는 힌트를 컴파일러에다 줄 수 있다.
복잡한 놈이라고 예고를 해 놓고 단순한 형태로 클래스를 선언하는 건 괜찮으나, 간단한 놈이라고 예고를 해 놓고 나중에 다중 상속이나 가상 상속을 쓰면 물론 컴파일 에러가 발생하게 된다.

아마 스타크래프트를 만든 사람도 스탑 럴커 같은 전술은 생각을 못 하지 않았을까.
저런 판타지 같은 면모는 C++을 설계한 사람이나 추후에 기능을 확장한 표준 위원회 사람들도 생각을 못 했을 가능성이 높아 보인다.
그렇기 때문에 비주얼 C++처럼 단순, 다중, 가상으로 세 등급을 나눠서 포인터에다 할증 제도를 넣고, 관련 예약어까지 추가한 건 전적으로 표준이 아니라 컴파일러 구현하기 나름이다.

아, 자세한 건 이 사이트 내용을 좀 공부하고 글을 쓰려고 했는데 도저히 다 읽을 엄두가 안 난다.
관심 있는 분들은 알아서 탐독해 보시길.
언뜻 보니, 다중 상속이 멤버 포인터보다 시기적으로 나중에 등장했다. 그래서 둘을 한꺼번에 구현하는 게 이 정도로 복잡하게 꼬인 셈이다.

Posted by 사무엘

2013/04/02 08:33 2013/04/02 08:33
,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/813

교육자가 되기

어느 분야든 제도권의 교육자가 되기란 무지무지 힘들다.
교육자는 자율과 자기 재량이 보장되지, 방학 있지, 생업 전선에 안 뛰어들어도 되고 경기 영향도 안 받는 안정적인 수입 있지, 사고 안 치고 잘 퇴직하면 연금까지 평생 나오지..
그래서 그만큼 이 바닥은 수요보다 공급이 너무 많고 경쟁이 치열한 레드 오션이다.
제자들에게 절대적인 권위를 행사하면서 부와 명예를 보장받는 직업이 아무에게나 주어질 수 있을 리가 없다.

1. 초등학교

극소수 사립 학교에 들어가는 걸 제외하면, 사실상 오로지 교육대라는 전용 양성 기관을 거쳐야만 교사가 될 수 있기 때문에 첫 진입장벽이 높다. 소수정예 합숙 생활, 매우 저렴한 학비, 내부의 폐쇄적인 문화와 텃새 등. 거기서 필터링이 좀 되기 때문에, 교육대생 내부에서의 경쟁은 뒤의 두 분야에 '비해서'는 덜한 편이다.

다만, 언제까지나 '덜하다는' 거지 경쟁이 없다는 건 아님. 교육대 졸업생은 여타 분야와는 달리, 오로지 교사가 못 되면 정말로 사회에서 할 게 없다는 리스크가 더 크다. 어린 초등학생을 지도한다는 특성상, 전공 분야의 전문성보다는 인성· 전인교육의 비중이 더 높기 때문일 것이다. (초등학교는 담임의 비중이 매우 높으며, 영어 같은 일부 특수 과목만 빼고 한 교사가 하루 종일 자기 반의 전과목을 가르친다.)

2. 중등학교(중· 고등학교)

중등학교는 학생의 성적과 진로 지도에 대한 부담이 가장 높은 교육 등급으로, 일단은 사범대 졸업생이 지망한다. 하지만 초등학교와는 달리, 여기는 여타 학과 전공자에게도 길이 열려 있다. 따로 교육 대학원을 나오거나 다른 방법으로 교사 자격증을 취득한 뒤, 공립 학교 교사 임용에 도전할 수 있다. 그래서 진입장벽이 낮다는 특성상, 중등학교 교사 임용 시험은 정말 최악의 경쟁률을 자랑한다.

임용에서 도저히 합격을 못 하면 결국 기간제 내지 사립 중등학교, 혹은 진짜 사교육인 학원 강사를 생각하게 된다. 1순위만치 안정적이지는 못해도, 초등학교 교사 지망생보다는 선택의 폭이 넓은 편. 사립은 잘 들어가면 공립 이상으로 좋은 직장이 될 수 있긴 하나, 채용 절차가 공정하지 못할 가능성이 매우 높다는 게 함정이다.

3. 대학 교수

교사와는 달리 교수는 애들을 잘 가르치고 좋은 성적을 내게 하는 게 일차적인 목적이 아니다. 고등 교육은 학부와 대학원으로 이원화해 있으며, 교수는 평생 논문을 읽고 쓰면서 학문을 업으로 삼는 학자의 삶을 살아야 한다.
이 바닥은 박사 학위라는 희대의 진입 장벽이 있음에도 불구하고, 뽑는 숫자도 교사를 능가하는 수준으로 너무 적기 때문에 레드 오션의 진정한 종결자 분야라 할 수 있다. 지나친 학력 인플레도 한몫 했고 말이다.

책 읽은 양으로만 승부하는 인문계 지망자라면, 학원 강사나 조교로 눈물겨운 고학 생활을 수 년간 하면서 학계에 얼굴도장 찍고 지도교수에게 잘 보여야 한다.

펀드를 받고 프로젝트를 진행하는 이공계 지망자라면 돈 걱정은 인문계보다 상대적으로 덜할지 모른다. 그러나 나름 폐쇄적이고 군기도 존재하는 랩 사람들과 잘 어울려야 하며, 권한은 사장이고 하는 짓은 직속 상사 같은 지도교수에게도 잘 보여야 한다. 박사 과정 내내 논문 출판과 실적 압박에 시달리다, 졸업 후 나중에 교수 채용 때도 날고 기는 쟁쟁한 외국 박사들과 피 튀기게 경쟁해야 한다.
단, 이공계는 취업이 잘 되기 때문에, 굳이 교수가 아니어도 교수보다 더 높은 연봉 받는 대기업으로도 잘 빠진다. 비록 안정성은 교수보다 못하겠지만.

학문적 업적보다 포트폴리오가 상대적으로 더 부각되는 예체능 분야는 사회 경력 n년을 박사 학위와 동급으로 쳐서 석사 출신이 교수가 되기도 한다. 아니면 교육 대학원에서 교육학 박사를 받거나.

이공계나 예체능과는 달리, 인문계는 정말 교수가 못 되면 할 게 없는데 교수 자리가 없어서 열악하게 살고 있는 박사들이 문제이다. 그 학력으로 겨우 학원 아니면 시간 강사, 연구 교수 같은 저임금 계약직이 고작이니, 고학력 실업 문제는 어찌 해결해야 좋을꼬?


Posted by 사무엘

2013/03/30 19:29 2013/03/30 19:29
, , , ,
Response
No Trackback , a comment
RSS :
http://moogi.new21.org/tc/rss/response/812

« Previous : 1 : ... 146 : 147 : 148 : 149 : 150 : 151 : 152 : 153 : 154 : ... 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:
3049402
Today:
422
Yesterday:
2142