« Previous : 1 : ... 132 : 133 : 134 : 135 : 136 : 137 : 138 : 139 : 140 : ... 221 : Next »

* 에구. 나 완전 고전 게임 덕후 인증이다. ㅎㅎ

1.
옛날의 액션/아케이드 게임 중에는 주인공을 죽게 하는 각종 트랩들이 적(몬스터)에게도 동일하게 적용되는 게 있고, 그렇지 않은 게 있다. 동일하게 적용되는 게 더 공정하고 현실 고증에 더 충실한 시스템이겠지만, 그 경우 적의 AI를 더 똑똑하게 만들어야 게임성이 성립할 테니 개발자에게는 더 큰 난관이 된다. 안 그러면 적을 정당하게 싸워서 죽이는 게 아니라 AI 헛점을 이용해서 트랩으로 죽이는 꼼수가 너무 횡행하여 게임 밸런스가 무너질 것이다.

이런 한계로 인해 id에서 개발한 둠, 퀘이크 등의 몬스터는 용암이나 화학 용액 같은 데에 들어가도 체력을 잃지 않으며 물에 들어가도 익사하지 않는다. 그 대신 잘 알다시피 자기끼리 팀킬을 벌이는 몬스터 내전(monster infighting)이 있을 뿐이다. 둠에서는 몬스터들이 정말 무식한지라 내전이 정말 잘 벌어졌지만, 퀘이크에서는 몬스터와 주인공 사이에 다른 몬스터가 일직선으로 있을 때는 공격을 안 하게 일말의 AI 개선이 이뤄졌다.

위험한 데이브에서는 몬스터는 트랩 같은 건 쌈싸먹으며 잘만 날아다니고..
과거의 툼 레이더 게임들은 주인공이 혼자 트랩 퍼즐을 풀어야 하는 구역과 몬스터와 싸우는 구역을 완전히 철저하게 분리하여 논란의 여지를 차단한 사례에 가깝다.
Rick Dangerous 2는 이 점에서 독특하다. 몬스터도 미사일, 전깃줄 같은 트랩에 걸리면 얄짤없이 죽을 뿐만 아니라, 이렇게 죽이는 게 전기총(50점), 폭약(100점) 같은 주인공의 일반적인 공격으로 죽이는 것보다 점수도 더 높게 준다(150점).

자, 서론이 너무 길어졌는데.. 페르시아의 왕자는 잘 알다시피 로토스코핑 기법으로 스프라이트를 만들었을 정도로 극도의 현실성을 추구한 게임이다. 악당도 딱히 초현실적인 괴물이 아니라 그저 검을 든 똑같은 인간이며, 이들을 상대로도 가시와 톱날 같은 트랩은 똑같이 동작한다. 악당 역시 트랩에 걸리면 피투성이가 되어 끔살당한다.

악당을 죽이는 방법으로는 (1) 칼 공격으로 HP를 다 깎아서 죽이는 가장 평범한 방법 외에도,
(2) 2층 이상의 높이에서 추락사시키기. 주인공은 이 경우 HP 하나만 잃지만, 악당은 의외로 즉사한다. 그 대신 악당은 1층 높이에서 떨어졌을 때 주인공처럼 무릎을 굽혀 엎드리지 않으며 바로 자세를 잡는다. 일당일단? 그리고 악당이 지금보다 아래 화면으로 떨어진 경우, 시체가 남지 않는다.
(3) 가시 꼬챙이가 있는 곳으로 떨어뜨리기. 한 층 높이에서만 떨어져도 주인공이든 악당이든 다 죽는다.
(4) 허리 자르는 쇠톱날.. 더 이상의 자세한 설명은 생략한다.

악당을 죽이고 나면 '빰 빠밤 빰' 하면서 승전 멜로디(?)가 흘러나온다. 칼로 찌르든, 떨어뜨리든 어떻게 죽이든지 말이다.
그런데... 페르시아의 왕자에서 악당을 (3)번, 즉 가시에다 밀어넣어 죽인 뒤에 승전 멜로디를 들은 적이 있으신 분 손..??
난 한 번도 없다. 20년 전부터 지금까지 이걸 대수롭지 않게 여기고 넘어가곤 했는데, 갑자기 문득 이상한 점이 느껴진다.

페르시아의 왕자 레벨에서 악당을 (3)번처럼 죽이는 건 레벨 2, 4, 8, 9(두 번), 11에서 총 6군데가 가능하다. 특히 마지막 레벨 11의 경우, 아예 왼쪽과 오른쪽에 모두 가시 트랩과 절벽이 존재하니 악당을 재미있게 요리하는 맛이 더욱 쏠쏠하다.

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

악당을 정상적인 (1)번 방식으로 죽였을 때는 승전 멜로디가 무조건 나온다. (2)나 (4) 같은 트랩으로 죽였을 때는 아주 가끔 음악이 안 나오기도 했던 것 같다.
그 반면 (3)은... 지금까지 한 번도 나온 적이 없었다.
어떤 방식으로 죽든 악당의 HP가 0이 되어 전투가 끝나고 주인공이 칼을 집어넣을 때 승전 멜로디를 연주하면 될 텐데.. 로직을 상황별로 다 따로 처리했나? 그리고 저기서만 if문이 하나 실수로 빠진 건지? 진실은 그 당시 코딩을 했던 프로그래머만이 알 수 있을 것으로 보인다.

2.
자, 이제부터는 가시 말고 톱날 얘기가 줄곧 나올 것이다.
페르시아의 왕자의 일부 던전에는.. 톱날을 통과해 들어간 뒤에 곧바로 칼을 뽑고 악당과 싸워야 하는 곳이 있다. 레벨 4에서 처음으로 등장한다.
그런데 적과 싸우기 시작했을 때는 게임 진행이 조금 느려지고, 심지어 톱날의 톱질 주기도 약간 길어지는 것 같다.

이것은 시스템 성능 같은 다른 외부적인 문제일 뿐, 게임 메카닉 자체가 느려지는 건 아니다.
페르시아의 왕자는 참 좋은 게, ESC를 눌러서 게임을 일시 정지시키고 나서 계속 ESC를 누르면 게임을 한 프레임 단위로 천천히 진행시킬 수가 있다.
이걸로 측정을 해 보면, 톱날의 톱질 주기는 언제나 15프레임으로 동일하다. 전투 중일 때든, 평시든 말이다.

그리고 심지어 톱날이 여러 개 연달아 동작할 때도 동일하다.
각각의 톱날이 한 번씩 연달아 톱질한 뒤에 첫 톱날의 다음 주기가 시작되기 때문에 주기가 좀 길 것처럼 느껴지기 쉬운데, 그렇지 않다.

원작 게임에서야 톱날이 한 층에 가장 많이 등장하는 게 레벨 3의 대형 물약이 있는 방이다. 3개짜리가 최다이다.
유튜브 같은 데서 톱날이 5개가 넘게 있는 이상한 방을 가 보면, 모든 톱날들이 15프레임 안에 한 번씩 순회를 하는 게 불가능하다. 이런 데서는 뒤쪽의 톱날이 미처 톱질을 하기 전에 15프레임을 다 채운 앞쪽 톱날이 또 톱질을 시작한다.
게임 메카닉이 이러하다는 걸 알 수 있다.

3.
또한, 톱날은 주인공이 톱날과 같은 층에 진입한 경우 곧장 동작한다.
그런데 주인공이 그 층에서 다른 이유로 인해 죽어 버리면, 톱날은 일반적인 경우 동작을 멈춘다. 가령, 그 층에 있는 악당과의 전투에서 져서 죽거나, 칼을 뽑지 않은 상태에서 악당의 칼빵을 맞아 죽은 경우 말이다. 톱날이 있는 층에 주인공이 추락사를 했다면 톱날은 역시 더 동작하지 않는다.

하지만 주인공이든 악당이든 누군가가 그 톱날 자체에 찍혀 죽었다면 톱날은 계속 동작한다. 다시 말해 누군가를 한번 죽인 적이 있는 톱날은 그 층에서 주인공이 추락사하든 악당의 칼에 맞아 죽든, 주인공이 그 층에 어떤 형태로든 있다면 계속 동작한다.

사용자 삽입 이미지
내가 치트까지 써 가면서 다양한 상황에서 테스트를 해 보니 대략 그러하다. 알고리즘 차원에서 이런 미묘한 차이도 존재한다는 게 흥미롭지 않은가?

4.
그리고.. 주인공이 톱날이 존재하는 층에 있긴 한데, 추락하느라 잠시 지나는 형태라면 톱날은 어떻게 동작할까?
톱날은 이때도 반응한다. 레벨 9에서는 심지어는 주인공이 아니라 악당이 떨어지는데도 톱날이 한번 동작하니, 참 놀랍지 않을 수 없다. 아래 그림을 보시라.

사용자 삽입 이미지

그 반면, 주인공이라 해도 이렇게 지나갈 때는 톱날이 동작하지 않는다. megahit 치트를 써서 천천히 떨어지게 하는 낙하산 효과를 줬는데도 톱날이 동작하지 않는다.

사용자 삽입 이미지사용자 삽입 이미지
이런 걸 보면, 톱날의 동작 여부에는 우리가 흔히 생각하는 것보다 더 복잡한 로직이 들어간 건지도 모른다. 심지어 던전의 지형별로 톱날의 동작 여부를 제어하는 메타데이터가 수작업으로 들어간 건 아닌지?

5.
아까도 잠깐 얘기했던 레벨 3으로 돌아간다. 여기는 알다시피 최대 HP를 늘려 주는 대형 물약이 있지만, 그 길목을 저렇게 톱날이 무려 3개가 가로막고 있다.

사용자 삽입 이미지

페르시아의 왕자에서 레벨 3은 중간 waypoint가 존재하는 유일한 레벨이기도 하다. 죽으면 얄짤없이 처음부터 시작하는 게 아니라, 타임어택 절벽 관문은 통과한 뒤의 시점부터 시작한다는 뜻. 페르시아의 왕자 2야 각 레벨이 워낙 방대해진 관계로 waypoint가 존재하는 레벨이 더 생긴 편이지만, 1에서는 레벨 3이 유일했다.

레벨 12에도 그림자 인간과 합체하고 나서 Jafar를 만나기 직전 위치에 일종의 waypoint가 있긴 하지만, 이건 내부적으로는 완전 별도인 레벨 13으로 간주된다. 그렇기 때문에 레벨 3의 waypoint와는 약간 성격이 다르다.
관문을 통과하기 전에 대형 물약을 먹었다면, 그렇게 해서 늘어난 HP도 다음에 waypoint에서 게임을 다시 시작할 때 반영된다.

그런데, 여기에 약간의 버그 내지 exploit가 있다.
waypoint에서 게임을 다시 시작하면, 레벨 3의 모든 요소들이 원래대로 되돌아간다. 딱 하나, 그 타임어택 절벽 관문의 한쪽에서 우리가 도움닫기를 위해 밟아 떨어뜨려 없애던 발판만 계속 없는 채로 남아 있다.

그것만 빼고 나머지는 전부 원상복귀. 심지어 타임어택 절벽을 넘기 전에 먹었던 대형 물약도 다시 생긴다.
그렇기 때문에 다음 레벨로 넘어가는 관문을 열고 해골도 처지한 뒤, 다시 그 방으로 돌아와서 대형 물약을 먹으면.. 이론적으로 레벨 3에서 대형 물약을 두 번 먹어서 HP를 2개나 확장하는 게 가능해진다.

레벨 3 시작 → 대형 물약 → 타임어택 관문 통과 → 그 뒤 Ctrl+A 눌러서 waypoint 지점부터 게임 재시작. 예전에 대형 물약 먹은 게 반영됨 → 되돌아와서 대형 물약 또 먹음 → 클리어

물론 실제로 이렇게 하는 건 시간이 너무 많이 걸리는 노가다이기 때문에 현실성은 별로 없지만..
이건 아마 조던 메크너(오리지널 게임 설계자, Apple II용 개발자)와 랜스 그루디(도스용 게임 포팅 개발자)조차 그 당시 예상을 못 했던 꼼수일 것이다.
차라리 waypoint 이후에 도달하는 위치에다 대형 물약을 놔 뒀다면 이런 exploit가 틈탈 여지가 없었을 텐데.

자, 이런 글을 보니 나도 도스박스 깔아서 페르시아의 왕자를 실행해 보고 싶은 생각이 드시지는 않는가?

Posted by 사무엘

2014/06/29 08:21 2014/06/29 08:21
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/979

영화 <테이큰> 관련 소감

OCN인지 뭔지 영화만 하루 종일 상영해 주는 케이블 TV 채널을 보면.. 한때는 계속 유명 액션 영화만 틀어 주는 경우가 있었다. 그래서 본인은 원빈이 너무 멋있게 나온 <아저씨>, 또 B급 영화 오마주로 가득하면서 웬 인간 흉기 금발 백인 누님이 일본도 들고 싸우는 <킬 빌>을 TV를 통해 우연히 봤다. 그리고 이에 덧붙여 하나 더 본 게 있었는데 그게 바로 <테이큰>이었다.

사용자 삽입 이미지

본 소감은..
역시 흥행하는 영화는 뭐가 달라도 다르구나 싶었다. 리암 니슨 아저씨 너무 멋있다.
특히 딸 유괴범을 전기고문하면서 딸이 있는 곳을 알아내는 장면은 너무 통쾌한 권선징악 장면인지라 몇 번이고 다시 반복해서 봤다. 다같이 한번 살펴보도록 하자.

저 때 Wake up! I need you to be focused!로 시작하는 대사가 나온다.
다만, 인터넷에 굴러다니는 자막 파일은 그 문맥에서 대충 의미만 통하지 영어 원문의 정확한 의도를 다 전하고 있는 것 같지는 않다. 그 뜻은 대략 이렇다.

“(기절한 마르코를 의자에다 묶어 놓은 뒤) 어이, 일어나! 너를 심문을 좀 해야 하니 정신 바싹 차리고 있어라. 어금니 꽉 깨물어라, 자 간다~ (쇠꼬챙이를 양 허벅지에다 푹~ 박아 넣은 뒤) 자, 기절할 정도로 졸라 아프겠지만 고문은 아직 시작도 안 했다. 여전히 정신 괜찮지?”

이런 뉘앙스를 제한된 화면에다 문장으로 일일이 다 표현할 수가 없으니 Are you focused yet?을 “이제 정신이 좀 드나?”로 보통 번역하는 편이지만.. 원래 의미는 “아직 괜찮지?”에 더 가까운 게 아닌가 한다.

마르코는 처음에는 브라이언의 얼굴에다 침까지 뱉으면서 의기양양하게 반항하지만.. 전기로 10초간 지져지는 고문을 두 번 당하고 나니 기세가 완전히 꺾였다. 우리의 멘탈갑 브라이언은 표정 하나 안 변하고 태연~하게 이런 이 근안스러운 말을 해 댄다.

“이런 일은 말야, 원래는 외주를 주곤 했어. 그런데 문제는 외주 준 나라들이 대체로 못사는 개도국이어서 전력 공급이 불안했단 말이야..?? 스위치를 켰는데 전기가 안 들어와. 그러니 고문기술자들은 빡쳐서 사람 손톱을 뽑거나 생살에다 산성 용액을 부어 버리곤 했지. 일이 여러 모로 능률이 떨어지곤 했는데.. 여긴 전류가 아주 원활해서 좋아.”
“난 지금 바쁜 처지야. 마르코, 너 순순히 대답 안 하면 전기세 밀려서 단전될 때까지 스위치가 켜져 있을 거다.”

나중에 정보를 얻을 만치 다 얻은 브라이언이 다시 스위치를 켜러 가자 마르코는 완전 겁에 질려서 브라이언에게 눈물까지 글썽이면서 애원한다. “I don't know!! PLEASE..!! not that.. please ㅠ.ㅠ” 이 부분 연기를 처절하게 잘했다.
그래 봤자 브라이언은 “I believe you. But it's not gonna save you.”와 함께 스위치를 켜 놓고 나가 버린다. 마르코의 자백은 자기 수명을 불과 몇 분 남짓밖에 더 연장시키지 못했다.
허나, 부모가 수십 년간 피땀 흘리고 갖은 애정을 쏟아 키운 딸애를 창녀촌에다 팔아 버리고 돈은 자기가 챙긴 사악한 악당이라면.. 정말 저 정도 고문은 인과응보가 아닌가 싶다.

테이큰은 여타 액션 영화와는 달리 주인공이 친구의 마누라(악역이 아닌 여성!)까지 팔을 쏴 버리는 장면이 나오며,
또 최종 보스와 대면한 뒤에도 일말의 타협 없이 주인공이 그냥 곧바로 악당의 미간을 날려서 사건을 종결짓는다. 사건 전개가 참 자극적이고 짜릿하다.
사실, 브라이언이 친구를 다그칠 때도 “너 자꾸 고집 부리면서 협조 안 해 주면 니 애들은 고아가 될 거다. 아까는 생명에 지장이 없는 팔을 쐈지만 다음엔 급소를 쏠 거야?”라는 요지로 자막이 나왔는데, 이것도 정확하게는 단순히 급소가 아니라 '미간'이다. 영어 대사엔 eyes라는 단어가 들렸던 걸로 기억한다.

위의 장면들을 다 제치고 테이큰에서 리암 니슨이 남긴 제일 간지 넘치는 대사는, 역시 딸이 납치당한 직후 전화로 납치범에게 남긴 경고일 것이다. 딸이 외국에서 납치 당했지만 조금도 당황하지 않고 오히려 이 타이밍을 기다리기라도 한 듯이 납치범들을 상대로 나지막한 말투로 협박한다. 아아..;;

I don't know who you are. I don't know what you want. If you're looking for a ransom, I can tell you I don't have money (....)
If you let my daughter go now, that'll be the end of it. (...)
But if you don't, I will look for you. I will find you, and I will kill you.

..... good luck.

30초가 넘는 분량의 대사인데.. 난 다 외워 버렸다.

역시 사람은 자기 마음이 가는 곳에 역량이 발휘된다.
매주 교회에서 짤막한 성경 구절을 외운 건 길어야 그 날 저녁까지밖에 안 가고 세부적인 단어와 표현은 하루 이틀 정도 뒤면 까맣게 잊어버리는데.. 저건 그냥 머리에 확...

take는 성경에도 굉장히 자주 등장하는 동사인데, 저 영화를 보고 나니 take의 뜻조차도 좀 다시 생각하게 된다.
그래서 갑자기 똘끼를 발휘하여, 저 사건과 대사가 만약 흠정역 성경에 기록되었다면 어떨까 상상을 해 봤다. ㅋㅋㅋㅋ

... 그녀의 아버지가 이르되, 나는 네가 누구인지 알지 못하며 네 혼이 무엇을 원하는지(thy soul desireth) 알지 못하노라. 만약 네가 대속물(ransom)을 원한다면, 너는 확실히 알지니(of a surety) 내게는 돈이 없느니라. (...) 만약 네가 내 딸을 가게 하면 잘하는 것이려니와 만약 가게 하지 아니하면 내가 너를 쫓고 너를 찾아내어 너를 반드시 죽이리라, 하니라.
잠시 후에 그녀를 취한(took/taken) 자가 대답하여 이르되, 잘해 보라, 하니라.


그러고 나서 나중에 그런데 그것이 실제로 일어난지라 “너 나 기억 안 나? 우리 이틀 전에 서로 전화 통화 했었지? 내가 너 찾아낼 거라고 예고했잖아.” 이 말을 들었을 때 마르코는 얼마나 소스라치게 놀랐을까? 하지만 이미 때는 늦었다.. =_=;;;;

테이큰은 잔인한 폭력뿐만 아니라 창녀촌 배경도 있어서 그런지 국내에서는 생각보다 수위가 높은 19금 등급을 받고 개봉했다.
아무리 자기 딸을 구하려 한다지만 브라이언은 남의 나라에 들어가서 거의 30명 이상의 사람을 죽였다. 모 건설 현장을 완전히 작살을 냈으며 남의 자동차를 최소한 3대를 탈취하고, 고위 공직자의 부인을 총으로 쏴서 다치게 했다.

이 정도면.. 선한 의도라고 해도 브라이언은 법적으로 프랑스를 절대로 곱게 빠져나갈 수 없는 신세다. 그러나 영화에서는 그딴 시시콜콜한 디테일은 전혀 반영되지 않았다.
하긴, <킬 빌>에서도 키도 누님이 시퍼런 핫토리 한조 일본도를 비행기 기내에 버젓이 반입한 채 일본 본토로 날아가는 걸 보고, 본인은 피식 웃었다. 영화는 영화일 뿐.

<아저씨>에서는 그래도 최소한 차 태식이 체포되는 걸로 끝난다. 아무리 나쁜 조폭들을 죽인 거라지만, 일반인이 혼자서 다른 사람을 그렇게 많이 학살했다면, 현직 변호사의 자문에 따르면 아무리 명분을 참작하고 봐 준다 해도 무기징역감이라고 한다.;;;
하지만 태식의 경우 원래 특수부대 요원이었고, 아직 능력이 출중해 보이니 도로 국가를 위해 현업 복직하는 것을 조건으로 검찰에서 기소조차 하지 않고 학살극을 유야무야하는 쪽으로 갈 것이다. 조폭들이 죽은 건 자기들이 팀킬 벌인 거라고 적당히 위장하고 말이다.

말초신경을 자극하는 폭력 액션 영화에 너무 심취하는 건 사람의 정신 건강에 그다지 좋다고 볼 수는 없다.
그러나 국가가 흉악 범죄자에게 권선징악을 속 시원하게 집행을 안 하고 되도 않은 인권 핑계로 직무유기를 저지르니, 사람들이 현실적으로 영화에서 대리만족을 얻게 된 것도 부정할 수 없을 것이다.
괜히 종교색 표방하면서 교묘하게 성경이나 하나님에 대해 왜곡된 이미지를 전달하는 매체보다는, 차라리 종교색 따윈 싹 잊고 말초신경만 자극하는 게 '덜' 해로운 건지도 모르고 말이다. 성경 용어로 설명하자면 전자는 마귀적(반성경적)이며 후자는 육신적(비성경적)이라고 표현할 수 있겠다.

Posted by 사무엘

2014/06/26 19:29 2014/06/26 19:29
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/978

1.
내 자신의 마음과 행동에 대해서 스스로 판단할 때는 절대로 남 따위와 비교하지 말고 성경과 비교하고 하나님의 법과 '절대적인 잣대로' 비교한다.
그 반면, 위의 권위와 위정자에 대해서는 “이게 그나마 불신자가 불신자를 통제하고 죄의 결과를 제어하려는 최선의 방법이구나. 비록 멍청하거나 사악하거나 혹은 둘 다일 때도 왕왕 있지만, 이거라도 없으면 세상은 더 망가질 수밖에 없으니, 내 신앙을 가로막는 것만 아니면 최대한 긍정적으로 보고 순종해야지”라는 '상대적인 잣대'로 접근하면 된다.

이 생각이 딱 정립돼 있으면 정신 건강에 여러 모로 좋다.
큰 절대악에 대해서는 절대 침묵하고서 불가피한 필요악의 작은 폐해만 자꾸 부각시키면서 없애고 뒤집어엎자고 드는 선동질, 반골 기질, 쓸데없는 세상 비관과 피해의식, 하나님보다 더 자비로운 인권 드립, 그리고 인간의 죄성상 절대로 가능하지 않은 사회 제도가 존재 가능하다고 속삭이는 속임수 등등에 넘어갈 일이 없게 되기 때문이다. 저건 전부 성경과 도저히 어울릴 수 없는 잘못된 사고방식이다. 내가 가끔 정치색 띤 글을 쓰는 건(특히 종북들 까는) 전부 이 카테고리에 해당하는 아이템들로 한정해서이다.

2.
신약 성경에 나온 긍정적인 얘기들, 대표적으로 빌 4:13 (나를 강하게 하는 그리스도), 롬 8:28 (모든 것이 합력하여 선을 이룸) 같은 것들은...
쉽게 말해 너도 성령의 능력을 힘입어 환경 여건에 구애받지 않고 예수님을 닮고 그분의 열매를 맺는 게 '이론적으로' 가능하다는 얘기다. 세상적으로는 오히려 바보 되고 손해 보더라도 말이다. 빌 4장 전후 문맥을 보면 아주 쉽게 유추 가능한 얘기임. 무슨 예수 버프를 받아서 세상적으로 성공하고 내 야망을 다 이룰 수 있다는 얘기가 절~대로 아니다!

그리고 롬 8:28도 당신이 육신적으로 절대로 원하지 않는 중간 과정과 결말을 다 포함할 수도 있는 얘기다. 신약 성경은 단순히 “차카게 살자” 수준을 넘어서 흔한 통념보다 굉장히 영적이고 고차원적인 주제를 다루고 있는 책이다. “하나님의 왕국과 그분의 의”가 무엇인지, 그런 문맥에 익숙해지는 훈련을 요한복음을 읽을 때쯤부터 미리 해야 한다.
그래야만 우리도 “제발 복 좀 주시옵소서”에 앞서 “우리가 이미 받은 복이 얼마나 큰지부터 알 수 있는 안목을 주시옵소서” 기도부터 먼저 한 에베소서 1장의 바울의 심정을 이해하게 된다.
신약 성경을 제대로 읽으면 이상한 은사주의 기복 신앙 같은 데에 빠질래야 빠질 수가 없다.

3.
신구약 성경 전체의 핵심 주제는 인간의 구원이나 크리스천의 양육 같은 게 아니다. 겨우 그게 전부라고 생각하기에는 성경엔 나머지 잉여스러운 내용이 분량이 너무 많고 그쪽 묘사들이 “쓸데없이 고퀄”이다.
성경에는 예수님의 초림보다 재림 예언이 더 많고, 이뤄진 예언보다 아직 안 이뤄진 예언이 더 많이 적혀 있다. 특히 이스라엘, 유대인의 문자적인 회복을 거듭해서 강조한다. 이 이스라엘과 유대인이 문자적인 이스라엘과 유대인이 아니라고 가르치거나 교회가 유대인을 대체했다거나 영적 유대인 드립 친다거나, “예수님을 죽인 나쁜 민족” 운운하면서 반유대주의를 조장한다거나, 14만 4천 명이 자기 교단이라고 가르치는 것들은 전부 성경을 잘못 가르치는 이단 교리다. 그런 데서는 당장 떠나고 나오시라.

성경 내용을 영적으로 적용하더라도, 누구에게나 동일하게 읽히는 문자적 1차 의미가 무엇인지 알기는 하고서 “그 다음에” 내 개인에게 유익이 될 수 있는 영적 교훈을 찾아야 한다. 도대체 어느 문맥에서는 “눈에는 눈, 이에는 이”이고 어디서 “원수를 사랑하고 왼뺨 맞으면 오른뺨도 대라”가 적용되는지를 제대로 분간할 줄만 알아도 최하 95%가 넘는 이단에는 안 빠질 수 있으며, 성경 읽는 기본 자세의 반은 마스터한 게 아닐까 싶다.

4.
세상에 복음과 구원 말고 공짜란 없다. 어디 하나가 공짜라면 다른 한쪽에서는 반드시 바가지나 착취나 희생이 존재한다. 아니, 구원이라는 공짜마저도 예수님의 보혈 덕분에 가능한 것이니 거시적으로는 공짜가 아닌 셈이다.
여기에 대해서는 본인이 예전에 경제관 쪽으로 글을 쓴 적이 있고 성경 교리 쪽으로도 글을 길게 쓴 적이 있다. 중요한 주제이니 관련 글을 반드시 참고하시라.

5.
크리스천의 윤리관은 그야말로 완전 보수 수구 꼴통급이다. 여기에 대해서는 역시 예전 글을 참고하시라.
그리고 역시 위의 예전 글에서 언급한 내용이다만, 크리스천은 이 세상에서 사는 게 끝이 아니라는 걸 알며, 죽음에 대한 두려움, 죽은 자에 대한 각종 이상한 미신(귀신 따위), 필요 이상의 신세 한탄, 트라우마, '천추의 한' 같은 게 (일단은) 없다. 이것도 사람의 멘탈을 굉장히 건전하게 만드는 데 기여하는 가치관이다.

6.
끝으로..
요즘 같은 세상에서 성경대로 살기란 도저히 불가능하다는 생각이 드는가? 신이 대체 존재하기는 하는지 의구심이 드는가?
예수 믿느라 나 혼자만 잔뜩 손해 보고 생존 경쟁에서 뒤쳐지고 부당한 일, 너무 억울한 일을 당한다는 생각이 드는가? 도대체 이것도 하지 말고 저것도 하지 말고 어떻게 살라는 건지 감이 안 오는가?
내가 인간적인 논리를 동원해서 그 질문에 대한 납득할 만한 답을 줄 수는 없다. 크리스천이라고 해서 마냥 동네북, 호구처럼 로봇처럼 살라는 말도 당연히 절대 아니다. 다만 난 이런 말은 해 줄 수 있다.

먼저, 바로 그런 이유 때문에 하나님은 인간에게 정말로 필요한 구원 조건, 하나님을 찾는 통로로.. 인간의 다른 그 어떤 스펙이나 외모, 능력도 모조리 제끼고.. 제일 하찮고 나약하고 바보 같아 보이는 '믿음'이라는 것만을 남겨 놓았다는 것이다. 이걸 기회로 삼아야 한다.

왜 하나님이 세상을 그런 원리로 만들어 놓았는지 제대로 이해는 못 하겠지만, 그렇기 때문에 하나님은 모든 사람들에게 정말로 공평해야 하는 것은 진짜 공평하게 돌아가게 해 놓으셨다.
그게 아니라면, 당신보다 더 잘났고 더 똑똑하고 더 부유한 사람들이 진작에 하나님을 당신보다 먼저 만났을 것이며 게임 다 끝났을 것이다. 그리고 하나님을 만나는 데 필요한 그 수단을 인간에게 너무 불공평하게 배분해 놓으신 하나님이 불공평하고 잘못된 꼴이 된다. 다른 능력자들이 다 안 믿을 때 당신이 믿어야 인생의 최후의 승리자가 될 수 있다.

그리고 부당한 일, 억울한 일이라고?
이 세상은 하나님께서 악한 카인을 벌을 내려 일찌감치 죽여 버린 게 아니라 반대로 의인 아벨이 카인에게 살해당하는 걸 허락하실 때부터.. 애초에 그 시절부터 불공평하기 시작했다. 저건 전혀 새삼스러운 현상이 아니다.
예수님의 죽으심 사건도 얼마나 추악하고 황당무계한 비리와 부조리 속에서 벌어진 일이었는지 역시 설명이 필요하지 않을 것이다. 하나님조차 그 악한 시스템을 한시적으로나마 인정하고 그 시스템을 역이용하여 자기 구원의 사역을 수행하셨으니 우리 역시 너무 피해의식 갖지 말자.

또한 우리의 모든 마음속 생각과 일거수일투족이 다 훗날 심판석 앞에서 회계보고가 될 텐데, 정산되지 않고 숨겨진 죄가 드러나서 하나님 앞에서 쪽팔림을 당하는 것만큼이나.. 그렇게 의로운 행실 때문에 손해 보고 부당함과 고난을 당한 것도 “똑같은 맥락으로” 그때 다 드러나서 보상받는 날이 온다는 걸 생각해 보자. 그거.. 영구적인 손해가 절대 아니다.

성경이 말하는 믿음이란 건 아Q 같은 근자감 정신승리법이 아니다. 영적 배후가 걸린 각종 문제들은.. 그 문제 자체가 물리적으로 제거됨으로써 해결되기보다는
내가 문제를 바라보는 발상을 바꾸고 안목을 바꿔서 성경이 약속한 모든 이해를 초월하는 평강(빌 4:7)을 얻음으로써 해결되는 경우가 많다. 그래서 욥기만 봐도 하나님은 욥의 고난과 직접적인 관련이 있는 말은 단 한 마디도 안 하셨지만 욥이 알아서 데꿀멍하게 된 것이다.

또한 악한 마귀의 통치하에 있는 현 세상은.. 사람이 그 믿음을 행사를 못 하게 시스템을 착착 만들어 놨다는 점을 잊지 말아야 한다.
성령 충만한 크리스천하고는 아무 상관 없는 이상한 사람들, 잘못 믿고 성경을 잘못 적용하는 사람들의 바보짓, 병크를 잔뜩 부각시키면서 이래서 종교에는 너무 빠져들어서는 안 된다는 식으로 영적으로 연약한 사람들의 믿음을 파괴한다. 하나님의 뜻을 오· 남용하는 것, 교회와 유대인을 구분 못 하는 것이 대표적인 예.
이러니 바른 성경 원천을 토대로 바른 믿음을 보기가 갈수록 어려워지는 게 오늘날의 모습이다.

“저런 사람이 믿는 예수라면 나도 한번 믿어 보고 싶다” 정도의 엄청난 선한 간증이 있는 크리스천이 세상에 과연 얼마나 있을까? 그런 평판은 나조차도 감당 못 하며 기대 안 한다.
그러나 그렇다고 해서 자괴감 가질 필요도 없고, 내가 예수님을 위해서 내 힘으로 이를 악물고 뭔가 엄청난 극기과 선행과 고행을 해야 한다는 식으로 생각할 필요는 더욱 없다.

난 딱 하나가 목표이다. 오로지 교리만을 있는 그대로 정확하게 전해서, 누가 그걸 안 믿고 반대하더라도 뭐가 기독교인지 정확하게 알긴 하고서 제대로 반대하게 만드는 것이다. 그들에게는 안 믿을 권리는 있어도, 기독교가 아닌 걸 기독교라고 주장할 권리는 없기 때문이다. 굳이 긍정적인 변화가 아니더라도 부정적인 편견을 막는 것도 인정받는 것 맞다.

나일롱 신자인 건 하나님 앞에서 겸손도 아니고 자랑도 아니다. 교회사에 등장하는 순교자나 각종 '성인'(?)들의 행적이 자기와는 완전 별개 딴판이라고 생각하는 것은 매우 잘못된 생각이다. 성경이 압수되고 성도들이 화형을 당하던 시대에 치러지던 영적 전쟁이 있고, 성경이라 불리는 물건이 넘쳐나지만 그게 죄다 변개되는 오늘날 같은 시대에 치러지는 영적 전쟁도 따로 있다. 난 그걸 추구하며 지낸다.

Posted by 사무엘

2014/06/18 08:33 2014/06/18 08:33
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/975

하루는 본인은 회사 업무를 위해 인터넷에 굴러다니는 어느 암호화 알고리즘 소스를 프로젝트에다 붙여 쓴 적이 있었다.
그런데 곧장 문제가 발생했다. 본인이 맡은 부분은 Windows용 클라이언트인데, 같은 소스를 사용하는 다른 플랫폼 클라이언트 내지 서버와 교신이 제대로 되지 않고 있었다.

결국은 문제의 코드를 별도의 콘솔 프로그램 프로젝트로 떼어서 따로 돌려 보니, 문제의 원인은 그 암호화 알고리즘에 있음이 밝혀졌다. 같은 소스를 빌드해서 돌렸는데 결과가 서로 차이가 나는 것이었다.
게다가 Visual C++로 빌드하는 같은 Windows용 프로그램도, 알고 보니 debug 빌드는 결과가 옳게 나오는데 release 빌드만이 문제가 있었다!

debug와 release가 서로 다르게 동작하는 프로그램은 십중팔구가 멀티스레드 race condition 아니면 단순 초기화되지 않은 변수 때문이다. 물론 이 코드는 스레드를 따로 만들지는 않으니 의심 부분은 응당 후자. 이거 또 남이 짜 놓은 복잡한 코드에서 꼭꼭 짱박혀 있는 버그 찾느라 무진장 고생하겠다는 생각과 함께 몇 시간 동안 디버깅을 진행했다.

release 모드로 빌드된 프로그램은 함수 인라이닝과 각종 최적화 때문에 debug 빌드처럼 한 라인씩 엄밀하게 step in이 되지 않으며 변수값 조회도 안 되는 경우가 종종 있다. 그러니 도대체 언제부터 두 빌드의 변수값이 달라지는지 printf 신공을 펼치면서 꽤 어렵게 문제 원인을 추적해야 했다.

문제의 범위는 많이 좁혀졌다. stack이나 heap 메모리를 초기화하지 않고 쓴 경우는 눈을 씻고 찾아도 없었다. 마치 난수 씨앗처럼 초기의 동일한 input으로부터 일련의 output들이 계산을 통해 파생되는데, 언제부턴가 두 빌드가 생성해 내는 변수값이 미묘하게 서로 달라지는 게 보였다. 저 동일한 input 말고 계산에 영향을 끼치는 요소는 정말 없는데? 왜 값이 달라지지..?

그리고 결국은 설마 하던 녀석이 사람을 잡았다는 걸 알게 됐다. 문제의 함수는 바로.. 이것이었다!

unsigned long Rol(unsigned long x, long y)
{
    if (y % 32 == 0) {return x;}
    else {return ((x << y)^(x >> -y));}
}

저 간단한 함수의 실행 결과가 release 빌드와 debug 빌드가 서로 달랐다. 비주얼 C++ 2012, 2010, 2003 전부 공통으로.
암호화 알고리즘에서 절대 빠지지 않는 그 이름도 유명한 비트 회전(bit rotation)을 구현한 함수인데..
비트를 음수 shift하는 연산은 좀 생소해 보였다.

본인은 15년 가까이 C/C++ 프로그래밍을 해 오면서 지금까지 막연히 A<<-B = A>>B, A>>-B = A<<B이지 않으려나 생각해 왔다.
그런데 실상은 전혀 그렇지 않았다.
컴퓨터의 구조적인 특성상 나눗셈에서 피연산자의 부호에 음수가 섞이면 몫과 나머지의 부호가 수학에서 생각하는 직관적인 형태로 구해지지 않는다는 건 어렴풋이 알고 있었다만, 비트 shift에도 그런 특성이 있구나.

음수 shift의 결과는 언어 스펙 차원에서 undefined인 모양이다. 진짜 말 그대로 A=A++처럼 '그때 그때 달라요'인 듯.
중의적인 코드를 컴파일러마다 제멋대로 번역하는 것 자체를 모조리 막을 수는 없겠지만, 그건 최소한 '이식성'에 문제가 생길 수 있다고 경고라도 띄워야 하지 않나 싶다.

실제로 위의 함수를 실행하면

Rol(0xBE9F8300, 1);
Rol(0xEC6BFC33, 1);
Rol(0xFC58371A, 1);

의 함수값은 release 빌드에서는 각각 0x7D3F0600, 0xD8D7F866, 0xF8B06E34이 나온다.
그러나 debug 빌드에서는 0x7D3F0601, 0xD8D7F867, 0xF8B06E35가 나오며, 이게 맞는 값이다. release는 무슨 이유에서인지 최하 자리 1비트를 누락하고 있었던 것이다. 그러니 이후의 암호화 결과가 몽땅 틀어지는 건 당연지사.
설상가상으로 xcode에서는 더 이상한 결과가 나왔던 걸로 기억한다.

유명 암호화 라이브러리가 왜 저렇게 이식성 없는 연산을 썼는지 난 잘 모르겠다. 음수 shift의 결과가 어떻게 나올 것을 기대한 건지?
저 문제를 우회하느라 지금까지 머리로만 알고만 있었지 실무에서 쓸 일이 전혀 없으리라 생각했던 테크닉을 쓰게 됐다.
소스 코드의 특정 구간에 한하여 최적화를 잠시 끄는 #pragma optimize("", off) 되시겠다.

bit rotation은 bit shift에다가 한쪽 끝에 있는 비트들을 따로 반대편 끝에다 shift시켜서 얹어 준다는 차이만이 있을 뿐이다. 32비트 부호 없는 정수 기준으로, 작은 자리수가 큰 자리로 이동하는 왼쪽(<<) rotation을 나보고 구현하라면 이렇게 짜겠다.

UINT Rol2(UINT x, int y)
{
    return (x<<y)|(x>>(32-y));
}

32라는 숫자가 보기 싫으면 sizeof 등을 써서 다른 방식으로 바꾸면 되고.
그리고 이렇게만 짜도 컴파일러는 이 연산 전체의 의미를 알아보고 당연히 rol이라는 '비트 왼쪽 회전'이라는 '한 인스트럭션'으로 최적화해서 번역해 준다. bit shift인 shl, shr만큼이나 rotation도 굉장히 기계 친화적인 동작이며, 전용 명령이 있는 것이다. 하지만 정작 저 공개 라이브러리 함수는 Visual C++ 컴파일러가 rol이라고 최적화하지 않는다.

아마 -n shift는.. 전체 비트수에 대한 보수(32-n)만치 shift하는 것과 같다고 전제를 한 듯하다.
그리고 or 대신 xor을 쓴 것은 그게 컴퓨터 구조 차원에서 기계어 코드 길이가 더 짧거나 속도가 조금이라도 더 빨라서 그런 듯하다. 필요하다면 x=0조차도 x^=x로 표현하는 게 컴퓨터 세계이니 말이다.

결국은 음수 처리까지 정확하게 해서 shift든 rotation이든 -n만치 하는 건 반대편으로 n만치 하는 것과 같은 게 보장되는 함수를 만들려면..
if문을 써서 처리를 완전히 따로 하고 <<, >> 자체에는 어떤 경우든 음수 shift가 존재하지 않게 하는 게 이식성 면에서 가장 좋은 해결책으로 보인다. 흥미진진한 경험을 한 날이었다.

Posted by 사무엘

2014/06/15 08:36 2014/06/15 08:36
, ,
Response
No Trackback , 6 Comments
RSS :
http://moogi.new21.org/tc/rss/response/974

오래 전, 본인은 PE 방식이라고 불리는 32비트 Windows 실행 파일의 내부 구조에 대해 처음 알아 가던 시절에 굉장히 신기해한 사실이 하나 있었다. 그건 바로 파일 내부에 자신이 호출하는 API 함수의 이름이 다 나와 있다는 점이었다. 그러면 이 프로그램이 대충 무슨 기능을 활용하며 만들어졌는지도 얼추 분석이 가능해질 텐데? 16비트 바이너리에는 이런 정보가 존재한 적이 없었다. (오히려 EXE가 윈도우 프로시저 같은 콜백 함수 이름을 노출하고 있었음)

static library가 그러한 것처럼 DLL도 프로그래머가 작성한 클래스/함수가 이름이 그대로 외부로 노출된다. 그 이름을 GetProcAddress에다 전달하면 이름에 해당하는 함수 주소를 얻을 수 있다.

그러나 DLL이 제공하는 심벌들은 이름뿐만 아니라 ordinal이라고 불리는 번호도 제각각 다르게 부여받는다. 그렇기 때문에 ordinal로 주소를 얻는 것 역시 가능하다.
이 ordinal은 index나 number이 아니라 ID에 가까운 개념이다. 반드시 0부터 N까지 조밀하게 분포해 있어야 할 필요가 없으며 1000부터 시작해도 되고 중간에 빈 번호가 있어도 괜찮다.

단, 범위는 16비트로 한정이다. GetProcAddress 함수는 인자의 정수값이 16비트보다 크면 포인터로 간주하여 문자열 검색을 하며, 그보다 작은 값이면 ordinal로 간주하여 숫자 검색을 하는 방식으로 동작한다.
다시 말해 Windows의 DLL은 구조적으로 65536개 이상의 심벌을 export할 수는 없다. 물론 그렇다 해도 이것은 현실적으로 아무런 한계가 없는 것이나 마찬가지다.

16비트 시절에는 DLL의 심벌 탐색이 이름이 아닌 오로지 ordinal 방식만 지원되었던 모양이다. (그럼 GetProcAddress 함수도 인자가 PCSTR이 아니라 그냥 UINT였나?)
문자열을 비교하는 것보다는 숫자를 비교하는 게 속도도 더 빠르고 공간도 더 적게 차지하니 좋다. 그러나 ordinal 방식은 두 가지 단점이 있는데, 먼저 보안이 좀 더 안 좋으며, 그리고 ordinal 관리가 매우 까다롭다는 점이다.

보안 이슈는 쉽게 비유하자면 이렇다.
GetProcAddress("My_unique_function_name")은 내가 직접 만들지 않은 DLL 에서는 성공할 확률이 거의 없다. 그 반면, GetProcAddress((PCSTR)5)는 함수깨나 있다 싶은 아무 어중이떠중이 DLL에서도 어지간해서는 성공하게 된다.

즉, 엉뚱한 DLL을 잘못 불러왔을 때, 이후 동작이 안전하고 깔끔하게 실패하는 게 아니라 그 상황을 사전 감지를 못 하고 나중에 crash로 도질 가능성이 높다는 뜻이다.
물론, 여기서 보안이라는 건 프로그램 실행과 관련된 보안이다. ReadFile, CreateWindow 이라는 함수 이름 대신 #35, #107 식의 암호 같은 ordinal은 프로그램의 역공학을 어렵게 하는 보안(?)은 더 뛰어날 수도 있으니 말이다.

ordinal 관리 문제는 생각보다 더 까다로운 문제이다.
어떤 DLL이 개발이 한창 진행 중이어서 수시로 함수가 추가되거나 삭제된다고 생각해 보자. 그렇더라도 한번 번호가 부여된 함수는 번호가 절대 고정불변이어야만 그 DLL을 사용하는 프로그램과의 하위 호환성이 보장될 수 있다.

같은 함수라도 DLL의 다음 버전에서 ordinal이 달라져 버리면 기존 프로그램은 그 DLL을 사용할 수 없게 된다. 그런데 수백, 수천 개의 ordinal간에 결번이 생기고 영역이 추가 할당되는 것, 과연 번호 관리가 그렇게 호락호락 수월하게 가능할까?

이런 이유로 인해 32비트 이래로 DLL 심벌은 ordinal이 아닌 문자열로 import/export하는 게 관행이 되었다. 16비트 시절에는 DLL을 하나 만들려면 DEF 파일을 무조건 반드시 만들어야 했고 export하는 심벌에 대한 ordinal을 수동으로 기입해야 했다.
그러나 32비트부터는 export하는 심벌만 쭉 기입해 주면, ordinal은 그냥 이름들의 ABC순으로 0부터 N까지 자동으로 생성된다. 별로 중요하지 않은 정보가 됐기 때문이다.

그러나 오늘날에도 ordinal이 전혀 불필요하고 쓸데없느냐 하면 그렇지는 않다.
딱히 컴포넌트화를 지향하지 않고 내가 만드는 프로그램에서나 내부적으로 몰래 쓰는 소형 private DLL이라면, export하는 함수의 이름이 전혀 중요하지 않을 테니 그냥 이름을 노출할 필요도 없이 ordinal 직통을 쓰면 된다. 하는 일이 붙박이로 정해져 있고 앞으로 프로토타입이 바뀔 일이 절대로 없는 물건이라면 금상첨화. 훅 프로시저 DLL 같은 게 좋은 예 되겠다.

혹은, 심벌 개수가 수천~수만 개로 너무 많은 대형 DLL의 경우, 로딩 시간을 조금이라도 단축하기 위해서 의도적으로 이름 대신 ordinal 기반 로딩 방식을 고집하기도 한다.
당장 MFC 라이브러리, 그리고 MS Office가 내부적으로 사용하는 공용 라이브러리인 mso.dll도 전부 ordinal 기반이다. MFC를 DLL 링크한 프로그램이라고 해서 export 섹션에 CWnd, CWinApp 이런 클래스 심벌들이 주룩 노출돼 있는 거 아니다.

심벌을 이름이 아닌 ordinal로 식별하게 DLL과 import library를 만들려면 빌드 시에 DEF 파일을 만들어서 심벌에 대한 특성과 ordinal 번호를 수동으로 지정해 줘야 한다.
그런데 C가 아닌 C++ 스타일의 클래스나 함수를 ordinal로 지정하는 법은 잘 모르겠다. 비주얼 C++ 스타일로 복잡하게 decorate된 명칭들을 일일이 다 열거하면서 @번호 NONAME 속성을 다 줬으려나? 그것도 보통일이 아닐 텐데.

Posted by 사무엘

2014/06/12 08:33 2014/06/12 08:33
, ,
Response
No Trackback , 3 Comments
RSS :
http://moogi.new21.org/tc/rss/response/973

다윗, 미갈 이야기

1. 다윗의 조약돌

성경에 나오는 다윗과 골리앗의 싸움 장면을 모르시는 분은 없을 것이다.
그런데 하나 같이 좀 생각해 보자. 다윗은 골리앗과 싸우러 나갈 때 왜 조약돌을 5개씩이나 챙겨 갔을까? (삼상 17:40)

“발사한 돌이 빗나가는 경우 / 골리앗이 한 발 만에 안 죽을 경우에 대비해서” 같은 답변은 말이 되지 않는다는 걸 금방 알 수 있다.
필살의 일격 단 한 발로 미간을 명중시켜서 인간 흉기 골리앗을 즉사 내지 최소한 기절이라도 시키지 않으면, 다윗은 곧바로 반격을 당해서 다음 돌은 쏴 보지도 못하고 죽는다. 이 조약돌은 FPS 용어로 치면 일종의 레일건인 것이다. 골리앗은 BFG로 무장해 있었고 말이다. 그러니 한 발 이후로는 의미가 없다.
 
역사적으로 볼 때, 살아서 돌아오지 못할 비장한 각오를 단단히 한 사람들은... 거사를 치르기 전에 일부러 자기에게 주어진 리소스를 딱 자기 여건에 맞춰 제약하는 퍼포먼스를 행하곤 했다. 일종의 배수진이랄까?
 
안 이숙 여사는 왕복이 아닌 편도 배삯만 치르고 일본에 갔으며,
윤 봉길 의사는 폭탄을 던지러 가기 전에 김 구와 손목시계를 교환하여 자기가 더 저렴한 것을 챙겼다.
옛날 백제의 계백 장군은 마지막 전투를 치르기 전에 자기 처자식부터 미리 죽였다..;;
 
다윗도 만약 그런 식으로 비장하게 행동했다면 필생필사의 각오로 돌을 달랑 하나만 챙겨 가는 게 자연스러웠을 것이다.

그러나 그가 그런 스타일로 행동하지 않은 이유는 간단하다. 그는 하나님이 지켜 주시는데 자기는 죽을 일이 절대로 없으며, 골리앗을 무찌르고 멀쩡히 돌아온다고 확신했기 때문이다. 일이 틀어질 가능성 따윈 전혀 고려조차 하지 않은 것이다. 남들이 보기엔 그건 영락없이 '근자감'처럼 보였겠지만 말이다. 그래서 그는 가진 자의 여유마냥 별 생각 없이 평상시처럼 여러 스페어 조약돌을 챙겼다.

아니, 어쩌면 그는 골리앗 정도를 초월하여 아예 이렇게 생각했을 수도 있다.
당장 현실의 목표물인 골리앗을 원 샷 원 킬 하는 건 너무 당연한 소리이고, 혹시 이 돌발상황 결과에 불복하여 예정에 없던 다른 거인들이 또 튀어나와서 시비를 걸면, 그놈들까지 이 조약돌로 잡아야겠다는 준비까지 한 건지도 모른다!
실제로 성경을 보면 거인이 골리앗만 있었던 건 아니며 당장 골리앗에게도 혈육상의 친동생이 있었다고 나오니까 말이다.
 
이 PvP에서 다윗은 골리앗을 PK하고, 골리앗이 갖고 있던 커다란 검을 득템했다. 참고로 사무엘기상 17장을 읽어 보면, 성경은 골리앗을 골리앗이라고 부르는 걸 극도로 기피하면서 의도적으로 '그 블레셋 사람'이라고 에둘러 가리키는 걸 볼 수 있다.

2. 사울의 둘째 딸 미갈

성경에서 사울 왕의 딸이 본격적으로 등장하는 건 다윗이 골리앗을 죽여서 완전 나라를 구한 영웅이 된 뒤부터이다. 영웅이 된 건 좋은데 다윗이 너무 유명해지고 왕보다도 인기가 올라가자, 그는 왕의 눈 밖에 나 버렸다.

이거 뭐 누명을 씌워 죽일 수도 없고.. 왕은 꼼수 차원에서 다윗을 전쟁터에서 죽게 하려고 높은 군사 직위를 주었으며, 자기 딸을 다윗에게 주어 결혼시켰다. 사실, 왕의 사위로 만들어 주겠다는 건 삼상 17:25에서 이미 약속된 사항이기도 했고 말이다.

그런데, 다윗은 자기 같은 가난하고 천한 사람이 감히 왕의 딸과 결혼할 수는 없다고 제안을 고사했다. 이에 왕은 다윗을 또 전쟁터에서 죽게 할 명목으로, 아무 지참금 따위 안 받을 테니 다만 민족의 원수 블레셋 사람 100명을 죽여서 놈들 포피만 가져오면 둘째딸 미갈을 아내로 주겠다고 제안했다.

그러자 다윗은.. 미갈이 마음에 들었는지, 나가서 블레셋 사람 200명의 포피를 갖고 멀쩡히 돌아왔다. 그래서 결혼에 골인했다.
생각을 해 봐. 사랑하는 마누라를 얻으려고 목숨 걸고 전쟁터에서 사람 수백 명을 죽이는 게 어디 쉬운 일이겠는가.

그러나 이렇게 맺어진 결혼 생활은 그리 단란하지 못했으며 오래 못 갔다.

미갈은 거짓말까지 해 가며 다윗의 도피를 도와 줘야 했으며, 별거 모드에 빠졌던 그녀는 훗날 아버지의 명에 의해 '발디/발디엘'라는 다른 남자에게로 강제 재혼을 당했다. (삼상 25:44) 그 동안 다윗은 타지에서 또 아비가일, 아히노암이라는 아내를 두 명이나 추가했고 말이다.

허나 여기에도 반전이 있었으니...
나중에 다윗은 긴 도피 생활을 마치고 왕이 된 후, 발디에게서 미갈을 도로 뺏어 와 버렸다! (삼하 3:14-16)

아무 영문도 모른 채 하루아침에 마누라를.. 그것도 자기 나라 왕에게 빼앗긴 발디는 엉엉 울면서 미갈을 뒤따라 갔는데.. 군대 대장 아브넬의 “그만 꺼져”(성경에는 그냥 Go return이지만..ㅎㅎ) 한 마디에 “넹.. ㅠ.ㅠ” 깨갱 하고 버로우 타 버린 완전 안습한 남자로 성경에 나온다. 성경에서 처지가 제일 처량한 남자가 아닐까 싶다.

이렇게 다윗과 미갈은 재회를 하였으나, 궁극적인 결말은 또 다시 불미스러웠다.
사사 시절 이래로 방치되어 있던 언약궤가 돌아오던 날, 다윗은 왕의 체면도 다 버리고 너무 즐거워서 백성들과 덩실덩실 춤추고 즐겼는데...

미갈은 그때 무슨 생각을 했는지 남편에게 “품위라고는 안드로메다로 보내 버리면서 당신 참 가관이더군요”라는 요지로 비아냥거리면서 굉장한 악담을 퍼부었다.

다윗도 이것만은 영적인 문제인지라 그냥 넘길 수 없었고, 아내에게 굉장히 실망을 한 듯하다. “나를 왕으로 세우신 하나님 앞에서 나는 지금보다 더 어리광 부리고 기꺼이 더 망가질 수도 있소. (그리고 그러더라도 나는 당신이 언급한 그런 천한 여자들보다는 하나님 앞에서 더 대접을 받을 테니 걱정 마쇼.)”

그 뒤로 미갈은 자녀 없이 쓸쓸한 말로를 보내게 되었다고 한다. (삼하 6:23) 그 시절에 유부녀가 자기 자녀가 없는 것은 거의 죄악에 가까운 굉장한 치욕이었다는 점을 생각하자.

이것이 단순히 금슬에 금이 간 것인지, 아니면 하나님께서 생리학적 불임을 만들어 버리신 것인지는 확실치 않다.그러나 인간의 출산을 굉장히 주관적으로 좌지우지하는 성경의 전반적인 심상으로부터 유추했을 때는, 후자일 가능성이 높다.

그리고 이것이 성경에 등장하는 미갈의 마지막 장면이다. 처음엔 다윗이 미갈을 좋아한 게 아니라 미갈이 다윗을 먼저 사랑했다고 나오는데.. 본의가 아니게 시집을 다시 갔다가 돌아온 뒤, 결국 다윗의 여러 아내들 중 랭킹 끄트머리로 밀려나면서 파경으로 갔구나. 인생 한번 참 파란만장했다.

Posted by 사무엘

2014/06/09 08:37 2014/06/09 08:37
, , ,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/972

1. 운전 중에 수시로: 눈치껏 차선 바꾸고 잘 끼어들고 들이대기 (배짱과 순발력)
2. 운전하는 전체 시간 내내: 한눈팔지 말고 앞차가 갑자기 서 버리거나 길 옆에서 뭔가가 튀어나오는 상황에 대비하기 (멘탈의 지구력이 뛰어나야 함)
3. 목적지에 도착한 후: 이 차가 차지하는 공간과 최소 회전반경을 숙지하여, 좁은 곳에서도 차 안 긁고 주차 잘 하기 (공간 감각)

(0. 운전하기 전 평소에 최소한의 자동차 점검 내지 정비 능력, 그리고 차량 고장이나 사고 발생시 멘붕· 당황하지 않고 대처하는 능력)

이들이 서로 완전히 별도의 독립적인 영역을 차지하는 게 틀림없다.
운전 학원에서 교육하고 면허 시험을 치는 내용도 이런 분야에 맞춰서 편성되어야 하지 않을까 싶다.

* 각종 운전 잡설.
승용차는 내 몸뿐만 아니라 나만의 자그마한 개인 공간을 함께 이동시켜 주는 물건이며, 대중교통과는 달리 차를 타러 가고 기다리고 갈아타는 과정에서 까먹는 시간이 거의 없다는 것만으로도 시간을 굉장히 아껴 준다.

또한 이동 과정에서 급격한 환경 변화나 온도 변화를 야기시키지 않아서 더욱 좋다. 그런 외부 요인으로 인해 몸에 피곤이나 스트레스를 주지 않기 때문에 사람의 업무 능률과 생산성을 올릴 수 있다. 가령, 밖에서는 추워서 옷을 껴입고 있다가 지하철 안에서는 더워서 옷을 벗는 식으로 온도 조절을 해야 할 필요가 없다.

밖에 비가 내리고 있으면 대중교통에 비해 자가용의 아늑함, 안락함과 편리함이 크게 증가한다. 비록 도로 사정 때문에 신속함(속도)은 별로 증가하지 않을지 모르더라도 말이다.

본인도 비 내리는 밤에 차에서 야영을 하는 걸 매우 좋아한다. 그러나 비는 차의 외형을 매우 더럽힌다는 점에서는 악재이다. 그 빗물이 흐르다가 마르면 물방울 모양으로 온갖 더러운 흙먼지 자국이 차의 표면에 남기 때문이다.

본인은 처음에는 “어제 세차했는데 오늘 비 오네”라는 푸념이, 굳이 세차를 할 필요가 없는데 해 버렸다는 말인 줄 알았다. 그러나 실상은 정반대다. 저 말은 어제 기껏 세차를 해 놓은 게 또 아무 소용 없어지게(=차가 더러워지게) 생겼다는 뜻이다.

비 오는 날 밤의 운전은 비와 야간이라는 두 변수가 합쳐져서 매우 까다롭다. 빗물 때문에 도로가 미끄럽고 더 위험하니 평상시보다 감속이 필수인데, 시야 확보도 잘 안 된다. 단순히 전방 시야뿐만 아니라 본인이 현실적으로 가장 절실하게 체험한 애로사항은.. 도로의 차선이나 횡단보도 정지선조차도 제대로 안 보인다는 것이다.

* 에어컨
요즘 날씨가 날씨인지라 요 근래부터는 드디어 전구간 에어컨을 켠 채로 운전을 하기 시작했다.
정체 없는 자동차 전용 도로를 경제 속도로 원활히 주행하고 나면, 평소에 연비는 12km/l대는 거뜬히 나오는 편이었다.
그랬는데 이번에는, 평소와 다름없이 아주 원활하게 주행했음에도 불구하고 찍힌 주행 연비는 10.xkm대.

에어컨이 연비를 10~20% 가까이 깎아먹는다는 말은 사실인 듯했다. 실험으로 입증됐다.
에어컨을 켰다고 해서 차가 딱히 더 힘들어하는 기색이 보이지는 않았으나, 연비는 슬그머니 떨어져 있었다.

힘 좋은 디젤보다는 휘발유 차량이, 그리고 대형차보다는 저배기량의 소형차· 경차일수록 에어컨 틀 때 차가 타격을 받고 휘청이는 정도가 더 커진다.
에어컨을 가동하면 엔진룸 쪽에서 무슨 기계가 추가로 돌아가는 소리가 들리기 시작한다. 옛날에 만들어진 소형차의 경우 차 엔진 회전수가 대놓고 살짝 더 올라가기까지 한다.

자전거를 몰아 보면, 헤드라이트를 켜기 위해 바퀴에다 소형 회전 발전기만 좀 연결시켜도 그 발전기의 오버헤드 때문에 자전거 페달 밟는 게 약간이나마 더 힘들어진다. 하물며 자동차의 엔진에는 발전기가 상시 연결되어 있는데, 거기에다 에어컨 실외기뻘 되는 공기 압축기까지 연결되니 부담이 더욱 가중되는 것이다.

에어컨의 전력 소비량은 자동차에서 최상급으로 전기 많이 잡아먹는 부품인 헤드라이트보다도 수 배 이상 더 많다고 한다.
그러니 헤드라이트에 에어컨을 다 켜고 와이퍼까지 켜는 비 내리는 여름 밤에는, 성능이 시원찮은 소형차의 경우 주행 중에도 배터리에 과부하가 걸리기 쉽다고 한다.

단, 이 에어컨의 전력 소비량이라는 게 안 그래도 엔진 힘까지 쭉쭉 빼 쓰고서 그것도 모자라서 또 전기까지 추가로 그렇게 별도로 쓴다는 것인지는 잘 모르겠다. 설마?
추운 겨울에 히터는 엔진열을 이용해서 송풍기만 가동하여 거의 공짜로 가동할 수 있지만, 반대로 열을 밖으로 빼내는 건 이렇게 어렵고 힘든 일인 것이다.

온도 말고 단순히 송풍기의 세기만을 바꾸는 건 어차피 연비에 그리 큰 영향을 끼치지는 않는 걸로 알려져 있다.
또한, 여러 변수가 있을 수 있겠지만 앗싸리 에어컨 트는 게 나은지, 아니면 창문만 열어서 차라리 공기 저항으로 인해 연비가 떨어지는 게 더 나은지는... 이렇다 할 답이 없는 듯하다. 둘이 어차피 비슷하게 비효율적이니, 차라리 에어컨 틀어서 정숙하게 주행하는 게 대체로 더 낫다는 게 중론인 듯. (물론 당장 차의 동력 효율뿐만이 아니라 지구와 환경까지 거시적으로 생각한다면, 에어컨이 치르는 대가가 더 크겠지만 말이다.)

또한 이건 바꿔 말하자면, 공기 저항이 에어컨에 필적할 정도로 차의 성능을 깎아먹는 주범이라는 뜻이기도 하다.

Posted by 사무엘

2014/06/07 08:24 2014/06/07 08:24
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/971

<날개셋> 한글 입력기 7.4-- 下

* 하편에서는 지난 상편보다 좀 더 실무(?)스러운 세부 기능과 안정성 위주의 얘기가 나올 것이다.

5. 글자판 전환 단축글쇠의 지능화

PC용 문자 입력 프로그램에서는 키보드 연타를 좀 더 똑똑하게 인식하는 기능이 확실히 있긴 해야 하는 것 같다.
지난 7.1 버전에서는 bksp를 연타할 경우, 최초에 선택되었던 낱자/글자 삭제 단위를 그 다음 글자의 조합 상태와 무관하게 계속 적용하는 옵션을 추가했다. 이런 기능을 구현하려면 아무래도 예전 상태를 기억하는 변수가 있어야 하고 모든 key 동작을 감시하는 오버헤드가 불가피하지만, 그 오버헤드 이상으로 그건 사실 편리하고 필요한 기능이긴 했다.

bksp에 이어 이번 새 버전에서는 입력 항목(=글자판) 전환 단축글쇠에도 연타를 인식하는 로직이 추가되었다.
입력 항목 전환 수식은 10년 전의 3.0 이래로 지금 글자판의 번호를 나타내는 변수 A 하나밖에 존재하지 않았는데, 이번에는 연타 카운트를 나타내는 B, 전체 입력 항목 개수를 나타내는 N, 그리고 우리 직전에 사용하던 입력 항목 번호를 나타내는 C라는 여러 변수들이 추가된다.

여기서 연타라 함은 계속 누르고 있거나, 아니면 modifier에서 손을 떼지 않고 main key만 눌렀다 뗐기를 반복하는 걸 말한다. Shift+Space라면 shift는 꾹 누르고 있는 채로 space만 반복해서 누르는 것이다.

그렇다. Windows 8과 맥 OS에서는 이미 익숙한 관행일 것이다. 전자의 경우 Win 키를 누른 채로 space를 눌러서 IME를 고를 수 있으며, 맥의 경우 역시 Cmd+space를 1회만 누르면 직전에 사용하던 입력기와 내 것만 toggle되고, space를 여러 번 누르면 평소에 안 쓰던 다른 입력기를 고를 수 있다. 이 동작이 이제 <날개셋> 한글 입력기로도 가능해지는 것이다. 예를 들어,

B>0||C==A ? (A+1)%N : C

이런 수식을 배당하는 경우, 이 key가 연타 상태이거나(B>0) 글자판 전환을 처음 하는 상태라면 현재 존재하는 모든 입력 항목을 돌아가며 순회한다. 현재 입력기의 바로 다음 입력기(A+1)로 넘어가되, 이 값이 N과 같아지는 경우 도로 0으로 되돌리는 것이다(%N). 그렇지 않으면 내가 바로 직전에 사용하던 입력 항목 번호를 나타내는 C로 돌아간다.

세벌식과 쿼티, 두벌식과 드보락을 한데 배당해 놓고 있었는데 세벌식/쿼티이던 것을 세벌식/드보락으로 바꾸고 싶은 경우, 세벌식 상태에서 Shift를 누른 상태에서 Space를 몇 번 눌러서 드보락으로 이동시킨다. 그 다음부터 Shift+Space를 1회만 누르면 세벌식/쿼티가 아니라 세벌식/드보락이 된다. 마찬가지로 두벌식 전환을 하고 싶은 경우, 영문 자판 상태에서 두벌식으로 돌아가면 그 뒤부터는 두벌식/드보락 toggle이 된다.

이로써 오로지 0과 1 사이만 왕복하고 더 다양한 입력 항목을 사용하려면 별도의 단축글쇠를 추가하거나 불편하게 마우스를 동원해야 했던 번거로움이 사라지게 될 것이다.

6-1. 외부 모듈: 특정 프로그램에서 첫 타가 조합이 끊어지는 문제

이건 굉장히 오래 전에 작업이 완료된 아이템인데, 블로그 옛날 글을 읽어 보니 언급을 한 번도 안 한 것 같다. 그러니 지금이라도 좀 공지를 하도록 하겠다.

<날개셋> 한글 입력기 외부 모듈은 특정 프로그램에서 한글 입력을 곧바로 시작했을 때, 첫 타의 조합이 끊어지는 문제가 있었다. 대표적인 예가 MS Office의 엑셀. 얘만 좀 아래의 한글 IME에다가 특이한 이벤트를 날리는 게 있어서 '나라'라고 입력을 시작하면 'ㄴㅏ라'가 되곤 했다.
이 문제를 당장 피해 가는 건 물론 가능했다. 그러나 그 경우, 다른 프로그램에서 조합이 종료되어야 할 때 종료가 되지 않는 오동작이 발생하니 난감한 상황이 아닐 수 없었다.

그래서 <날개셋> 한글 입력기는 고육지책으로 외부 모듈은 자신이 동작하는 프로그램 EXE의 이름을 살펴서 엑셀 같은 '요주의 프로그램'이면 문제 회피 로직을 쓰고, 다른 프로그램에서는 그 로직을 쓰지 않는... 궁극의 지저분한 꼼수를 굉장히 오랫동안 사용해 왔다.
그런데 그렇게만 하니까 첫 타가 끊어지는 문제가 Paint .NET에서도 발생하고, 다른 듣보잡 프로그램에서도 종종 보고되면서 상황이 더욱 나빠져 갔다.

일단 난 응용 프로그램이 한글 IME를 도대체 어떻게 조작해야 첫 타를 끊어지게 만들 수 있는지, 어떻게 해야 저런 프로그램을 만들 수 있는지를 이해를 못 한다. 하지만 그럼에도 불구하고 7.4에서는 논란의 여지가 있던 부분을 없애고 오랜 연구 끝에, 문제를 일단은 이름 판별이라는 꼼수 없이 완벽하게 해결했다. 이런 미세한 동작 방식 같은 건 제대로 문서화도 돼 있지 않으니 정말 프로그래머가 경험을 알아서 축적하는 수밖에 답이 없다.

참고로 첫 타의 조합이 끊어지는 문제는, 첫 타가 아예 무시되고 씹히는 문제하고는 성격이 다르다. 후자 역시 다른 상황에서 예전에 <날개셋> 한글 입력기 외부 모듈의 버그로 종종 보고되곤 했다. ㅎㅎ

6-2. 외부 모듈: Windows 7의 명령 프롬프트에서 한글이 덧나는 문제

Windows 7에는 한글 IME의 세벌식 지원과 관련하여 이전의 XP/Vista에 없었고, 후대의 8에도 없는 전무후무한 이상한 문제가 하나 있다. 명령 프롬프트에서 한글을 입력하다가 space, 마침표, 숫자 등 비한글 문자를 입력하여 조합을 중단할 경우, 조합 중이던 한글이 덧나는 현상이 발생한다.

MS IME, 그리고 <날개셋> 한글 입력기도 동일하게, 그것도 오로지 윈도 7에서만 발생하기 때문에 이것은 IME 차원에서는 해결 불가능한 운영체제의 버그라고 간주되어 왔다.
단, MS IME로 두벌식을 쓸 때는 문제가 없는데, 두벌식의 경우 비한글 문자는 IME가 글쇠를 가로채어 직접 처리하지 않기 때문에 그렇다.

그랬는데.. 이번 7.4 버전으로 우연히 콘솔에서 한글을 입력해 봤는데.. 덧나는 현상이 없어져 있어서 깜짝 놀랐다. 윈도 7에서 세벌식으로 덧나는 현상 없이 한글을 입력하는 걸 난생 처음 본다. 저게 가능하구나!
구버전(= 현재 공식 최신 버전)인 7.11을 돌려 보니 문제가 발생하는데, 7.4를 돌리니 문제가 사라지는 게 확실하다.

도대체 무슨 변화가 생긴 건지? 저 6번하고는 영역이 다른 문제였을 텐데. 기대도 안 했던 버그가 별다른 작업 없이 저절로 해결돼 있으니 기분은 좋다만, 한편으로 좀 난감하네.

7. 타자연습

자, 입력기가 이렇게 완전히 머리부터 발끝까지 뒤집어 엎어진 동안, 타자연습도 변화가 하나도 없으면 좀 섭섭할 것이다.
입력기와 API 호환성이 다 날아갔으니 7.4 버전에 맞춰 다시 빌드되어야 한 건 두 말할 나위도 없거니와, 외형과 관련된 사소한 개선 사항이 좀 있었다.

프로그램의 16*16 소형 아이콘이 그 크기에 맞는 전용 아이콘으로 나오는 게 아니라 32*32 아이콘을 축소시킨 우중충한 형태로 지금까지 나오고 있었는데, 당장 그걸 개선했다. 개인적으로는 타자연습도 지금의 편집기나 변환기처럼 <날개셋> 한글 입력기 7.0 스타일의 동그란 네모 아이콘으로 바꾸고 싶으나, 그 작업까지 할 여유는 없다.

그리고 프로그램을 고해상도 DPI 모드에서 실행해서 UI 텍스트가 잘린다거나 하는 것을 모두 수정했다. 그 작업의 결과로 페이지의 우측 하단에 있던 “연습 시작” 버튼들이 예전보다 더욱 길쭉해지고 보기 좋아졌다. 이 역시 진작부터 개선할 생각을 왜 안 했나 모르겠다.

다음으로 장문 연습을 시작할 때 "연습을 시작합니다. 준비하세요"라고 메시지 박스가 번거롭게 뜨던 걸 없애고, 단문 연습과 마찬가지로 첫 타를 누름과 동시에 시간 측정과 경쟁 모드가 시작되게 했다. 인터페이스 개선에 기여할 것으로 보인다.

끝으로, 연습글을 상당수 교체했다. 세월을 안 타는 고전을 제외하고는 너무 구태의연하고 지금과 시기가 안 맞는 글은 삭제했다. 예를 들어 한글날이 공휴일에 국경일까지 된 마당에 한글날 국경일 지정을 촉구하는 글을 계속 남겨 둘 필요는 없으며, 월드컵 관련 글도 너무 오래 됐다고 판단하여 뺐다.
그 대신 다른 글을 넣고, 각종 인터넷 유행어 병맛 개그들을 넣었으니 타자 연습할 때 즐겁게 이용해 주시기 바란다. ^^

사실 게임도 업그레이드 시스템을 없애고 시간이 나면 시스템을 다 갈아엎고 싶었으나 도저히 손을 댈 수 없었다. 3.31에서 3.4로 번호를 작업량에 비해 좀 크게 올린 것은 거의 1년 반 만의 버전업이어서 시간 간격이 워낙 길었으며, 또 7.4와 끝자리를 맞춘다는 의미를 더 표현하고 싶었기 때문이다. 올해는 또 2014년이기도 하고.

8-1. 사소한 것: 최종 변환 규칙 UI

다른 카테고리에 분류되기가 뭣한 잡다한 얘기들은 다 여기에다가 집어넣었다.
<날개셋> 한글 입력기는 최종 변환 규칙이라는 게 추가된 무려 2.4 버전 이래로 지금까지..
입력값 from과 to를 접수하는 방식이 좀 괴이했다. 한 입력란에다가 from 문자와 to 문자를 붙여서 입력하고 '추가'를 눌러야 했으나.. 이번 7.4에서는 드디어 from과 to를 별도의 입력란에다 따로 입력하는 방식으로 UI가 직관적으로 개선되었다. 아래 그림을 참고하시라.

사용자 삽입 이미지

8-2. 떡밥 - JSON

이건 새로운 기능 얘기는 아니고 다른 잡설임.
<날개셋> 한글 입력기는 입력 설정 파일을 바이너리 고유 포맷뿐만 아니라 텍스트 에디터로 편집 가능한 XML 방식으로 저장하는 것도 꽤 오래 전부터 지원해 왔다.
그런데 텍스트 기반의 데이터 직렬화(serialize) 파일 포맷으로 XML뿐만 아니라 JSON이라는 물건도 있었구나. 얘도 보아하니 찰져 보이고 XML의 대체제가 될 수 있을 것 같다.

XML처럼 다단계 계층을 당연히 표현할 수 있으며, key-value 방식의 자료구조뿐만 아니라 배열을 통해 테이블 같은 단순 데이터 dump도 모두 손쉽게 표현할 수 있다는 게 마음에 든다. XML은 일단 후자에는 최적화돼 있지 않으니 말이다.
태그가 아니라 프로그래밍 언어의 데이터 초기화 코드에서 모티브를 땄다는 점도 참신해 보인다.

8-3. 떡밥 - 글꼴

<날개셋> 한글 입력기는 1.0 시절부터 내부 입력 프로토콜을 사용하는 자체적인 에디트 컨트롤을 갖추고 있었으며, 구현체들 중 편집기는 이 컨트롤을 기반으로 동작하는 텍스트 에디터이다. 그리고 자체 에디트 컨트롤은 16*16 비트맵 글꼴이라는 굉장히 원시적이고 똘끼 충만한 글꼴 체계를 고집하고 있다.

그것 자체는 이 프로그램의 특징이고 포기할 수 없는 특성이라고 치자. 운영체제에 의존하지 않고, TTF로는 상상도 할 수 없는 작은 크기의 조합형 글꼴로 옛한글과 미완성 한글을 출력하는 것을 애초에 목표로 삼았으니 말이다. 기계식 타자기를 컴퓨터에다 옮겨 놓은 듯한 날씬함을 개발 철학 차원에서 추구한 셈이다.

다만, 이거 하나는 대세를 무시할 수 없는 듯하다. 바로 화면 해상도. 옛날에는 16*16이라는 글자 크기가 운영체제 UI의 기본 글꼴보다 컸지만, 125% 내지 150% 배율을 쓰는 초고해상도 환경에서는 이것은 작은 크기이다.
같은 폰트라도 16픽셀을 18이나 20 정도로 확대해 주는 기능은 있어야 할 것 같다.

기능 자체는 화면에다 글자를 찍는 부분과 마우스 포인터 위치 인식 기능에다 간단한 비례식을 추가하는 정도로 구현할 수 있을 듯한데..
문제는 비트맵 그래픽을 출력하는 부분이다. 정수배 확대가 아니니 그래픽의 품질을 위해 안티앨리어싱은 필수라고 봐야 하는데, 재래식 GDI로는(StretchBlt 함수) 그걸 넣을 수 없다. 당장 <날개셋> 편집기에서 화면 인쇄 명령을 내려서 배율을 바꿔 보면, 이를 확인할 수 있음.

그러니 이것도 최소한 GDI+나 요즘 대세인 Direct2D 같은 API로 작성되어야 할 것으로 보이는데, 그것까지 신경 쓰는 건 <날개셋> 한글 입력기의 핵심 기능과 직접적인 관계가 없고, 개인적인 작업 부담이 너무 심하다. 쉽지 않은 문제다.;;

9. 마치며

(1) 후원금을 보내 주신 분들의 이름은 그 다음 버전의 프로그램 도움말의 '감사의 글' 페이지에 꼬박꼬박 등재되고 있다.
후원자가 아주 많아지면 액수 순으로, 혹은 최근 순으로 잘라서 수록하는 게 불가피하겠지만, 내 프로그램은 벌써 그런 경지에 오른 것도 전혀 아니고 아직까지는 후원해 주신 모든 분들이 명단에 올라 있다.

<날개셋> 한글 입력기는 14년째 개발자가 한글 오덕질 근성을 주체하지 못하여 자기 인생의 상당 부분을 투자하며 개발되어 왔다. 특히 이번 7.4는 개발 역사상 유례를 찾기 어려울 정도로 한글 입력 엔진에 굉장히 많은 기능 추가와 수정이 이뤄졌다. 프로그램의 개발 취지를 이해하고 후원해 주신 분들께 다시 한번 감사드린다.

(2) 단군의 후손들이 어째 라틴 알파벳도 아니고, 한자 같은 그림문자도 아니고, 한글 같은 위상의 문자를 쓰고 있는지.. IME가 필요하긴 하지만 NLP 기술 없이 글자 구조 자체와 관련된 엔지니어링이 개입할 여지가 있는 문자를 쓰는지? 생각하면 할수록 신통방통한 일이다. 거기에 세벌식 글자판까지 생각하면.. 오덕질을 안 할래야 안 할 수가 없다.

본인은 맹목적인 공 병우 빠돌이가 아니며, 맹목적인 세벌뽕도 아니다. 더 나은 한글 기계화 패러다임이 있다면 정말 열린 마음으로 수용할 의향이 있다. 어떤 한글 입력 방식이든 동등한 여건 하에서 구현되고 테스트되어야 한다. 솔직히 <날개셋> 한글 입력기야말로 바로 종류를 불문하고 한글 입력 기술의 공평한 통합을 목표로 개발되고 있기도 하고 말이다. (그러니 세벌식뿐만 아니라 두벌식 관련 고급 기능도 많이 들어있다!)

그런데 그렇게 열린 마음으로 살펴봐도 현실적으로 정말 공 병우 세벌식을 능가하는 한글 기계화 패러다임은 등장하지 않았고 앞으로도 딱히 나올 기미가 보이지 않는다. 그 정도 성능에 그 정도 범용성을 갖춘 최강 가성비를 자랑하는 입력 방식 말이다.
오히려 모바일 환경으로 가면서 굳이 그렇게 빨라야 할 필요가 없으니 의미가 퇴색했을 뿐이지, 동일 환경에서 공 병우 세벌식이 다른 패러다임에 의해 추월당한(beaten) 적은 내가 보기에 없다. 내가 식견이 부족한 것일 수도 있으니 이 명제에 대한 반박은 언제든 얼마든지 환영한다.

본인은 이런 패러다임을 바탕으로 우리나라 고유문자를 컴퓨터에서 완전 변태(?) 수준으로 쥐락펴락할 수 있는 기술을 보유한 것에 자부심을 갖고 있다. 적어도 Windows라는 한 플랫폼에서만은 마스터를 했으니 말이다. 프로그래머 만세다. 언젠가 내 프로그램의 내부 구조와 설계 이념을 강연이나 저술을 통해 지금보다 더 널리 알릴 기회가 있으면 좋겠다.

Posted by 사무엘

2014/06/04 08:27 2014/06/04 08:27
Response
No Trackback , 9 Comments
RSS :
http://moogi.new21.org/tc/rss/response/970

<날개셋> 한글 입력기 7.4-- 上

요 며칠간 개인적으로 잘 된 일도 있었고 잘 안 풀린 일도 있는 채로 다사다난한 시간을 보냈으나.. 그 어느 것도 나의 코딩을 가로막을 수는 없다. 열차는 시각표대로 무조건 달린다. 건널목에서 충돌 사고가 나도 질량과 관성 때문에 장애물을 그냥 밀고 쭉쭉 나아갈 뿐이다.

그래서 드디어 <날개셋> 한글 입력기가 7.11 이래로 무려 7개월간의 수련을 마치고 7.4 버전이 완성되었다.
원하는 기능들을 다 집어넣은 건 아니지만 한번 역에 정차하여 쉬어 가게 됐다. 이 달부터는 학기 마무리 준비를 해야 하는 관계로, 더 작업은 하고 싶어도 할 수 없기 때문이다.

5월은 안 넘긴 걸 기쁘게 생각한다. 의도했던 건 아닌데 5월 31일은 공교롭게도 <날개셋> 한글 입력기 3.0 출시의 딱 10주년 타이밍이기도 하다. 2004년 5월 31일 + 10년이다.

3.0은 최초로 유니코드 API 도입, 입력 스키마와 문자 생성기 계층 구분, 단축글쇠 테이블, 수식 기반의 오토마타, 지금과 같은 64비트 크기의 입력 단위, TSF를 인식하는 에디팅 엔진, 가변 길이 옛한글 등 오늘날 내 프로그램의 근간을 닦은 버전이었다. 2.5 이후로 거의 9개월 동안 프로그램을 밑바닥부터 다시 만들었었다.

물론 지금 보면, 기술적 디테일이나 사용자 인터페이스는 그야말로 내가 겁도 없이 이런 허접한 프로그램을 대회에 출품하고 사용자에게 공개했다 싶을 정도로, 민망할 정도로 허접하기 그지없었다.
그러나.. 포니를 개발한 뒤에야 에쿠스가 나올 수 있었듯이, 그런 개허접한 3.0이 있었기 때문에 그 뒤로 꾸준히 후속 기술이 개발되고 기능이 추가되어 무려 7.4까지 나올 수 있었던 건 자명한 사실이다. 이제 7.4를 바탕으로 올가을쯤에 7.5가 나와서 잔여 과업들을 완수해 준다면, <날개셋> 한글 입력기는 거의 대망의 완전체가 도달하지 않을까 싶다.

1. 입력 엔진 부분의 대대적인 리팩터링

예전에도 한번 소개한 적이 있듯, <날개셋> 한글 입력기에는 한 번에 한 낱자가 아니라 초중종 낱자를 한꺼번에 입력하는 기능이 있다. 그리고 그냥 입력하는 정도가 아니라 두 번에 걸쳐 입력하는 기능이 있다. 예를 들어 "받침ㅆ+다"를 배당하여 '이' 다음에 '있다'를 곧바로 만든다거나, '가' 다음에 '갔다'를 바로 만드는 게 가능하다.

극단적인 예로, 한 글쇠에다 '받침ㅋ+쌰'를 배당한다. 수식으로는 'H12|SS|YA|_K'라고 표현된다. 그 뒤, 허용 한글 범위를 KSX1001 완성형으로 맞춰서 2350자만 입력 가능하게 바꾼다.
이 상태에서 '가' 입력 중에 그 글쇠를 누르면.. '가ㅋ쌰'가 찍히는 게 맞다. '갘'은 조합이 안 되니 ㅋ이 다음 글자로 떨어져 나가고, '쌰'도 완성형에 없는 한글이기 때문에 조합이 더 진행되지 못하고 끊어지는 게 맞다. 그러나 현재 7.11 버전은 'ㅋ가쌰'가 된다. 중첩 입력을 처리하는 로직이 완전하지 못하기 때문이다.

또한 이 경우 원래 조합하던 글자에 이어서 총 2개의 글자가 추가로 완성되는 것이기 때문에 삽입이 아닌 '겹침' 모드에서는 2개의 글자가 추가로 덮어써져야 한다. 그러나 7.11은 그것도 깔끔하게 처리되지 못하고 여전히 삽입만 되고 있다.

이렇듯 NLP 기술이 하나도 없는 단순 한글 입력기 같아도 <날개셋> 한글 입력기는 서로 영향을 끼치는 입력 관련 각종 옵션과 변수들을 제어하는 게 굉장히 복잡하다. 가짓수와 가짓수를 서로 고려하다 보면 가능성이 곱셈이 되어 버려서 통제를 못 하게 된다. 각 변수들을 있는 그대로 각개격파하여 덧셈으로 유지되게 해야 한다.

굳이 저런 극단적인 상황에서의 매끄러운 처리까지 생각하는 게 아니더라도, <날개셋> 한글 입력기의 핵심 엔진 부분은 지난 10여 년 동안 다양한 기능이 추가되는 과정에서 매우 심하게 지저분해졌으며 구조적으로 심각한 한계를 드러내고 있었다. 그래서 대대적인 리팩터링이 불가피했다.

한참 옛날에 만들어 놨던 코드의 모든 로직과 의미를 다시 읽으며, 머리를 쥐어뜯고 피말리는 작업이 계속되었다.
그 결과, 단독으로 1천 줄이 넘던 핵심 함수의 일부를 2개의 함수로 떼어내고, 반복적인 패턴이 발견되는 일련의 루틴들을 별도의 클래스로도 빼냈다. 복잡한 입력, 이동, 지우기 동작을 제한된 element만으로 추상화해 낸 것이다.

특히 재귀호출이 필요한 부분과 그렇지 않은 부분을 확실히 분리했으며, 중복 무한순환 재귀호출을 감지하여 막는 부분을 더욱 똑똑하고 논리 오류가 없게 개선했다.

기능 추가도 아니고 동일한 기능을 구현하는 방식만 바꾸는 데 거의 50일이 걸렸다. 이 디자인이 과연 최선의 디자인인지 스스로 확신을 얻는 데도 긴 고뇌의 시간이 필요했다.
새로운 체계 덕분에 각종 지저분한 중복 코드가 없어지고, 지저분한 임시 변수나 비트 플래그가 없어지고, 그럼에도 불구하고 입력기의 논리적인 버그가 없어질 때마다 본인은 거의 엑스터시에 가까운 환희를 경험했다.

결합 축약 테이블에 의한 입력 순서 축약은 입력 타이밍이 아니라 bksp 지우기 동작이 실제로 일어날 때 행해지게 바꿨고,
특히 겹침 모드에서 배경의 글자를 덮어쓰는 개수를 계산하는 건, 입력 동작의 결과를 보고 공통된 post-processing 과정에서 한번에 알아서 계산하게 바꿨다.

이렇게 만들어진 출력 action은 구현체에 따라 IME에서는 WM_IME_*메시지로, TSF 환경에서는 TSF interface 함수 호출로, 자체 에디터에서는 말 그대로 내부 조작으로 seamless하게 변환되어 나간다. Windows 95부터 8.1까지 버전 불문하고 32비트, 64비트 불문하고 모두 똑같이 동작하는 건 물론이고 말이다.

이번 작업 덕분에 <날개셋> 한글 입력기의 코드는 소프트웨어공학적인 품질이 크게 향상되었으며, 이를 토대로 다른 새로운 입력 기능들도 손쉽게 확장해 넣을 수 있게 되었다.

2. 고급 입력 스키마

이번 7.4 버전에서는 종전의 '동시입력 스키마'를 대체하는 '고급 입력 스키마'가 추가되었다. 아직 넣고 싶은 기능이 100% 다 구현된 건 아니지만 어쨌든 이로써 입력 스키마와 문자 생성기가 모두 (1) 빈 (2) 기본 (3) 고급이라는 3단계 계층이 갖춰지게 됐다.

빈 입력 스키마는 아무 글쇠도 스스로 처리하지 않고 응용 프로그램에 그대로 넘겨 주는 잉여이다.
기본 스키마는 우리가 지금까지 써 온 대로, 키보드에서 통상적인 문자 입력용으로 쓰이는 47개 글쇠에다 Shift 조합을 포함한 94개 자리의 keydown을 인식한다. 거기에다 사용자가 별도로 지정한 글쇠의 keydown을 추가로 인식하거나, 기존 47개 글쇠를 부분적으로 인식하지 않게 하는 기능을 액세서리 차원으로 제공한다. 추가 글쇠는 Ctrl/Alt/Shift/Win 같은 modifier 조합을 옵션으로 가질 수 있다.

이에 덧붙여 고급 입력 스키마는 지정한 글쇠에 대해서 keydown뿐만 아니라 keyup(글쇠를 뗀 것)을 모두 인식할 수 있으며, 각 상황별로 이 글쇠를 처리할지의 여부를 모두 수식으로 지정 가능하다. 또한 이 keydown 이벤트가 몇 번째 연타인지, 그리고 이 이벤트가 발생한 시각(밀리초 단위)이 언제인지 같은 정보도 변수로 제공된다(예전에 기록한 시각과의 차이를 계산하는 데 활용 가능). 기본 입력 스키마에는 존재하지 않던 정보들이다.

그래서 이를 이용하면 한 글쇠를 0.n초 이상 오래 누른 것, 혹은 0.n초 이내에 눌렀다가 뗀 것, 어떤 두 글쇠를 연달아 누른 것, 굳이 Shift+X가 아니라 Shift를 한번 눌렀다 떼고 나서 다음 X를 순차적으로 누른 것 같은 복잡한 글쇠 동작을 모두 인식할 수 있으며, 글쇠를 오래 누르고 있어도 연타는 한 번 또는 n회 이내만 인식시킬 수도 있다. 기본 입력 스키마에다가 옵션으로 넣으려고 했으나 이론적인 기반을 마련하지 못해 지금까지 전혀 구현을 못 하고 있던 변칙적인 글쇠 인식은 전부 고급 입력 스키마를 통해 general하게 구현 가능해졌다.

단, 고급 입력 스키마는 기본 입력 스키마처럼 modifier 조합 같은 게 없다. 오로지 어떤 글쇠의 눌렀다 떼는 것에만 초점이 가 있으며, 두 글쇠의 조합은 각각의 글쇠가 눌러졌을 때 사용자가 변수에다 해당 글쇠가 눌렸다는 것을 일일이 판단함으로써 모든 로직을 수동으로 구현해야 한다. 기본 입력 스키마보다 설계 철학이 더 저수준이기 때문이다.

기본 입력 스키마는 날개셋문자를 있는 그대로 차근차근 보내는 것만 가능하다. 그러나 고급 입력 스키마는 사용자가 지정한 수식값에 따라서 지금 조합 중인 문자를 덮어쓰고 조합을 무조건 새로 시작시킬 수 있으며, 지금 조합을 무조건 종료한 뒤에 조합을 새로 시작시킬 수도 있다. 전자는 'ㄱ+ㅏ'를 '가'가 아니라 'ㅏ'로 바꾸는 기능이며, 후자는 'ㄱㅏ'로 바꾸는 것이라고 생각하면 이해하기 쉽다. 자기와 연결되어 있는 문자 생성기의 상태를 무시하고 입력을 보내는 게 가능하다는 뜻이다.

이런 고급 입력 스키마가 고급 입력기라는 문자 생성기와 만나면 활용 가능성은 더욱 커지는 건 두 말할 나위가 없다. 평상시에는 일반적인 방법으로 한 타씩 한글을 입력하지만, 특수한 글쇠 두어 개를 동시에 누르거나 한 글쇠를 오래 누른다거나 하면 미리 지정해 둔 '습니다', '000' 같은 글자 묶음이 지금 조합을 무시하거나 종료시킨 상태에서 곧장 입력되게 할 수 있기 때문이다.

더 자세한 개념과 기능 설명에 대해서는 고급 입력 스키마를 꺼낸 뒤, "고급 글쇠 인식 옵션" 페이지에서 F1 도움말을 참고하면 된다. 앞으로 이걸 이용한 창의적인 문자 입력 방식이 많이 고안되어 나오면 좋겠다. 예제 템플릿 수식 같은 거라도 더 넣어서 고급 입력 스키마에 대한 사용 접근성을 더 개선하는 게 추후 과제로 남아 있다.
또한 지금 만들어 놓은 입력 설정을 그대로 유지하면서 기반 루틴만 '기본'이던 것을 '고급'으로 업그레이드하는 방법이 없는 게 문제라면 문제임을 인정한다. 기반 루틴을 바꾸고 나면 글쇠배열 같은 입력 설정은 다시 세팅을 해야 한다.

다음 버전인 7.5에서는 이번 7.4에서 실험적으로 구현한 기능을 바탕으로, 한글의 동시 입력에 특화된 보정 기능들이 추가될 예정이다.

3. 고급 입력기 -- 한글 출력 치환

입력 스키마에 이어 문자 생성기에도 '고급 입력기'에 신선한 기능이 새로 추가되었다.
잠시 개념을 좀 복습하자면, 빈 입력기는 아시다시피 오토마타, 조합, 후보 변환 같은 게 없이 문자를 있는 그대로 완성된 형태로만 보낼 수 있는 제일 원초적인 문자 생성기이다. 영문 같은 문자에나 적합하다.
기본 입력기는 그야말로 한글 한 글자를 조합하는 데 필요한 온갖 복잡 화려한 <날개셋> 한글 입력기의 핵심 기능들이 모두 구현되어 있는 문자 생성기이다.

그리고 고급 입력기는 기본 입력기의 기능들을 바탕으로, 비한글 문자의 custom 조합과, 한글 입력과 비한글 입력을 서로 연동하는 액세서리 기능이 추가적으로 들어있다. 설계 철학이 이러하다는 걸 염두에 두도록 하자.
이번 7.4에서는 '한글 출력 치환'이라는 기능이 고급 입력기에 추가되었다. 언뜻 보기에 이것은 편집기 계층에 존재하는 '최종 변환 규칙'의 입력기 계층 버전처럼 보이기 쉬우나, 성격이 그것과는 약간 다르다.

한글 출력 치환은 초중종성 낱자별로 동작하는 버전과 글자 전체 단위로 동작하는 버전이 따로 존재한다.
전자는 가상 낱자를 가리면서 동작하고--다시 말해 세벌식에서 겹모음용 ㅗ/ㅜ와 홑모음용 ㅗ/ㅜ를 구분한다는 뜻--
후자는 그걸 따지지 않고 그냥 겉으로 보이는 한글 전체의 모양만 따지며 동작한다.

낱자 버전부터 설명하도록 하겠다.
초중종이 각각 ABC로 구성된 한글이 있고, 초중종 A, B, C에 대해 각각 1, 2, 3이라는 문자열로 출력 치환하는 규칙이 존재한다면.. ABC라는 한글은 대략 1A2BC3이라고 바뀌어 출력되게 된다. 즉, 한글의 앞뒤로 비한글 일반 문자가 삽입되며 특히 중성에 치환 규칙이 존재하면 한글 자체가 초/중종 두 글자로 찢어진다.

이런 기능이 왜 필요하며 무슨 용도로 쓸 수 있을까?
주된 활용 방법 중 하나는, 한글 입력 과정에서 현행 한글 코드에 존재하지 않는 복잡한 겹낱자를 잠시 표현해야 할 때, 이를 여러 개의 기존 낱자로 풀어서 표현하는 것이다. 물론, 123 말고 ABC 자체의 형태를 바꾸려면 기존 가상 낱자 규칙을 쓰면 된다. 따라서 낱자 출력 치환은 가상 낱자 규칙과도 연계해서 활용하면 좋다.

이번 7.4에서는 천지인이나 나랏글 같은 휴대전화 입력 방식 예제가 다 이 기능을 사용하여 다시 만들어져 있다.
종성 부분을 보면, 내부적으로는 받침 ㅃ, ㄸ, ㅉ이지만 겉으로는 초성 ㅃ, ㄸ, ㅉ이 다음 글자에 가 있는 것처럼 화면에 나타나는데, 가상 낱자를 써서 받침 ㅃ, ㄸ, ㅉ을 0으로 치환하여 원래 있던 자리에서는 없애 버리고, 그 대신 출력 치환 규칙에다가 초성 ㅃ, ㄸ, ㅉ을 대신 출력하게 한 것이다.

ㄴ+ㅇ, ㄱ+ㅆ, ㄱ+ㅊ 같은 받침이야 더 말할 필요도 없다. 300 이상의 가상의 받침을 설정한 뒤, 가상 낱자 규칙에다가는 ㄴ, ㄱ 같은 앞부분 받침만 나타나게 하고, 뒷부분 받침은 출력 치환 규칙으로 지정했다. 한글 한 글자를 조합하는 걸로 두 글자 이상의 한글이 한꺼번에 나타나게 하는 걸 이런 이론 기반으로 구현해 냈다.
단, 외부 모듈의 경우 한글 조합이 길이가 한 글자를 넘어가면 응용 프로그램에 따라서는 조합 중인 문자가 제대로 표현되지 않을 수 있으므로 주의가 필요하다.

다음으로 글자 버전은.. 쉽다. 말 그대로 지금 조합 중인 한글을 다른 문자로 바꿔서 보여 주는 것 그 이상도 이하도 아니다. 한글 입력 방식을 한글로 다른 문자를 입력하는 데 고스란히 활용할 수 있으며, 덕분에 사용자 정의 조합 기능을 쓸 일도 크게 줄어든다.

이것 덕분에 아래아한글 97 이래로 지금까지 구현된 적이 없던.. 한글로 일본 문자 입력이 가능해졌다. 이번 버전에서는 히라가나/가타카나를 종전과 같은 로마자 기반 사용자 정의 조합뿐만 아니라, 한글 출력 치환으로 구현한 예제 파일이 새로 추가됐다.

이와 관련하여, "한글 출력 범위(=문자 집합) 제한"에도 유용한 기능이 하나 추가됐다. 지금까지는 KSX1001 2350자, 한컴 2바이트 완조형, 한양 PUA 완성형처럼 완전 legacy 잉여 문자 집합을 생색내기로 흉내 내는 기능만 있었던 반면, 바로 <날개셋> 고급 입력기의 한글 출력 치환 규칙이 존재하는 글자만 허용하는 기능이 새로 추가된 것이다.
한글로 일본어 문자를 입력하는 예제 파일을 써 보면, 일본어 치환이 존재하지 않는 한글은 아예 조합이 되지 않고 낱자가 다음 글자로 튕기는 걸 볼 수 있다.

(다만, 지금까지 사용자 정의 조합으로 구현되어 있던 구결 입력 방식은, 그냥 외장형 "사용자 후보 변환"으로 입력하는 데이터 파일로 형태를 바꿨다. 한 한글에 대응하는 구결 문자가 여럿 있기 때문에 후보 변환이 더 적절하다고 판단되어서이다.)

4. 그 밖에

이번 7.4에서 이뤄 낸 위의 1~3 아이템들은 생각만 해도 후련하다. 왜 이런 기능들이 무려 2014년에 와서야 실현된 걸까. ㅠ.ㅠ 일반 사용자의 입장에서야 <날개셋> 편집기에 다른 에디터에도 있는 기능들이 덩달아 들어가기를 더 원할지 모르고 현실적으로는 외부 모듈의 안정성 개선이 더 중요하게 느껴질지 모르나, 본인의 입장에서는 그런 건 개발 방향과 직접적인 관계가 없거나 최소한 부가적인 요소들이다.

<날개셋> 한글 입력기의 개발에서 본인이 가장 중요하게 여기는 건 한글 입력과 관련된 기술을 한데 통합할 수 있는 이론 연구와 구현이다. 그러니 편집기는 10년 전이나 지금이나 똑같은 촌스럽기 그지없는 MDI 프로그램 외형이지만, 그 속의 깊이는 갈수록 심오해지고 있다. 이번 7.4가 개발 기간이 괜히 길었던 게 아니며, 7.2나 7.3을 건너뛰고 괜히 바로 7.4로 간 게 아니다.

프로그램 버전이 7.x대까지 가고 나니 프로그램의 완성도는 충분히 정착한 듯하며, 이를 토대로 지금까지 못 하고 있던 long-term 이론 연구를 최대한 진행했다.
고급 입력 스키마와 고급 입력기는 모두 ngs3 모듈이 아니라 ngsx라는 플러그 인 모듈이 담당하고 있는데, 이런 대규모 작업 덕분에 드디어 ngsx의 프로그램 크기가 <날개셋> 편집기 ngsedit의 크기를 근소하게 추월했다.

분량이 벌써 굉장히 길어진 관계로, 이 항목에서는 고급 입력기와 관련된 변화 사항을 조금만 더 얘기하고 나머지 새 버전 자랑은 다음 하편으로 미루도록 하겠다. ㅎㅎ 그러고 보니 타자연습도 빨랑 업데이트하고 저거 얘기도 해야 되는데..

7.4에서는 한글 로마자 입력 방식의 근간인 글쇠 치환 규칙이 동작하는 방식이 살짝 바뀌었다. 새로운 기능 추가가 아니라 변경임. 글쇠 치환 규칙에 존재하던 잡다한 옵션들이 모두 없어지고 이들의 구현 방식이 다른 대체제로 바뀌었다.

caps lock 무시 옵션이 없어졌기 때문에 이제는 기반 영문 글쇠배열이 caps lock을 구분하여 동작하지 않도록 바뀌어야 한다. 이것은 글쇠배열 편집기를 우클릭한 후 "전체 간소화 → 수식 제거"를 선택하면 된다. 하지만 간단히 한글 로마자 입력 빠른설정만 다시 실행해 줘도 7.4 버전 기준에 맞는 로마자 입력 방식이 다시 세팅된다.

shift 음절 강제 구분 옵션도 없어졌으며, 조합을 하는 낱자와 조합을 안 하는 낱자는 두벌식/세벌식 한글 타입으로 오토마타 차원에서 구분을 한다. 비슷한 메커니즘이 이미 네벌식 예제 입력 방식에서도 쓰인 적이 있다.
다만 이것 때문에 현재 한글로부터 글자판 입력 문자열을 구하는 방식이 제대로 동작하지 않고 있는데, 이것은 7.5에서 해당 알고리즘을 싹 다시 구현할 때 문제를 개선할 예정이다.

끝으로, 두벌식 처리 옵션도 없어졌다. 두벌식 한글로 치환되는 글쇠는 언제나 초성과 종성이 현재의 오토마타 상태에 따라 자동으로 구분되어 두벌식으로 처리된다. 번거로운 절차를 없앴다. 이 점 착오 없으시기 바란다.

Posted by 사무엘

2014/06/01 08:27 2014/06/01 08:27
Response
No Trackback , 8 Comments
RSS :
http://moogi.new21.org/tc/rss/response/969

예전에 본인은 windowless 리치 에디트 컨트롤에 대해서 글을 쓴 적이 있었는데, 이번에는 눈에 보이는 컨트롤에 대해서 다루도록 하겠다. 난 일종의 텍스트 에디터 윈도우를 처음부터 끝까지 만들어 본 사람이다 보니, 이런 세부적인 디테일에 눈길과 관심이 간다.
여러분은 PC 사용자로서, 혹은 더 전문적인 프로그래머로서 Windows 운영체제의 에디트 컨트롤에 대해서 얼마나 알고 계신가? 그 이름도 유명한 메모장이 얘를 기반으로 동작하는 걸로 잘 알려져 있다.

얘는 서식이 없는 plain 소규모 텍스트에 대한 아주 기본적인 입력 기능만 제공하라고 만들어진 물건이다.
그래서 전문적인 에디터들이 내부적으로 줄 단위 연결 리스트 자료구조를 사용하는 것과 달리, 얘는 단일 배열 버퍼 기반이라는 게 가장 큰 특징 되겠다. 복잡한 메모리 관리 메커니즘이 전혀 없이 텍스트는 전체가 커다란 배열이며, 삽입이나 삭제는 진짜 직관적이고 단순하게 밀고 당기고 전체 메모리를 재할당하는 식으로 행해진다.

Windows 9x 시절까지만 해도 이 에디트 컨트롤은 64KB가 좀 덜 되는, 6만여 바이트 이상의 텍스트는 불러들일 수 없었다. 아무리 16비트 시절의 잔재라지만 이건 말도 안 되는 제약이었다.

오늘날의 운영체제에서야 그 정도의 막장 제약은 존재하지 않는다. 그래도 단일 버퍼 기반이며 근본적으로 대용량 텍스트를 다루는 데 최적화되지 않은 구조인 것은 변함없다. 그렇기 때문에 메모장에서 수 MB 이상의 파일을 불러들이고 편집하는 건, 불가능하지만 않을 뿐 여전히 무리다. 다른 프로그램을 써야 한다. 가령, 확장판인 리치 에디트 컨트롤은 연결 리스트 기반이며 에디트 컨트롤과 같은 제약이 없다.

간단한 물건답게 실행 취소(undo)는 직전의 동작 딱 하나만을 취소하거나 도로 철회하는 게 가능하다. 요즘 유행인 다단계는 지원하지 않는다.
텍스트 전체를 왼쪽뿐만 아니라 가운데나 오른쪽으로 정렬하여 출력하기, 숫자만 받아들이기, 알파벳은 대문자나 소문자 한 형태로만 받아들이기, 입력되는 텍스트를 '암호'로 처리하여 화면에 숨기기 같은 아기자기한 옵션이 있다. 최대 글자 수 제한을 걸 수도 있다.

얘의 동작 방식을 사소하게 바꿔서 배경이나 글자색을 바꾸고, 특정 문자는 안 받아들이게 하고, 문자열을 자동 완성한다거나 우편번호/시리얼 번호처럼 특정 형식을 만족하는 문자열만 입력되게 하는 것은... 아주 전형적인 Windows 프로그래밍 주제였다. 윈도우 프로시저를 서브클래싱하면 된다.
단일 버퍼라는 특성상 에디트 컨트롤의 메모리 핸들에 곧장 접근하여 조작하는 API도 있긴 하나, 실제로 사용되는 경우는 거의 없다. 사용이 권장되지도 않는다.

multi-line 모드의 경우 줄 바꿈 문자는 오로지 정확하게 \r\n만 지원하는 걸로 잘 알려져 있다. 그래서 유닉스 계열의 \n 텍스트를 불러와 보면 \n 문자가 실제로 보이고 줄 바꿈 처리가 되지 않아 텍스트를 제대로 볼 수 없다.
이 역시 리치 에디트 컨트롤과는 다른 점이다. 텍스트를 불러들이는 과정에서 딱히 줄 바꿈 처리를 전혀 하지 않고 normalize도 전혀 하지 않는 단순함을 추구했기 때문이랄까?

그리고 Windows GUI 프로그래밍을 좀 해 본 사람이라면 경험적으로 아는 중요한 특징이 하나 있다.
multi-line 모드에서 word-wrap(자동 줄바꿈) 옵션은 컨트롤이 생성될 때 한번 지정되고 난 뒤부터는 변경되지 않는다. 스타일을 바꿔도 바뀐 대로 동작하지 않는다.

그렇기 때문에 당장 메모장에도 있는 '자동 줄 바꿈' 옵션은 에디트 컨트롤을 파괴했다가 다시 생성하는 방식으로 구현되어 있다! 물론 창이 갖고 있던 내용을 따로 보관했다가 다시 가져와야 할 테고. 이건 Windows 95 이래로 지금까지 동작 방식이 시종일관 변함없다.

심지어는 닷넷이 제공하는 에디트 컨트롤의 관련 속성조차도 내부 구현은 창을 다시 생성하는 걸 Spy++ 같은 프로그램으로 확인할 수 있다고 한다. 핸들값이 바뀌니까 말이다.
응용 프로그램에다가 꼼수를 추가하면 추가했지, 에디트 컨트롤은 절대로 건드리지 않기로 작정하고 봉인을 시킨 모양이다. 그러니 앞으로 Windows 9, 10이 나오더라도 에디트 컨트롤이 연결 리스트 기반으로 바뀐다거나 하는 일은 없을 것으로 보인다.

한 에디트 창을 single line으로 쓰느냐 multi line으로 쓰느냐 같은 건 프로그램 실행 중에 동적으로 바뀔 일이 거의 없다. 그러니 그런 건 고정불변으로 둘 만도 하다.
하지만 multi line에서 자동 줄 바꿈 여부는 텍스트 에디터를 만드는 사람이라면 누구나 공감하듯이 동적으로 바뀔 여지가 있다. 그런데 그걸 불변으로 굳혔다는 것은, 에디트 컨트롤을 갖고 뭔가 진지하게 대용량 텍스트 에디터를 만드는 건 설계 차원에서 정말로 고려하지 않았다는 걸 의미한다.

뭐, 단순하긴 해도 운영체제가 원초적으로 제공하는 텍스트 입출력 기술의 혜택은 그대로 받는지라, 오늘날 에디트 컨트롤은 마냥 단순하기만 한 것도 아니다. Uniscribe를 사용하여 나름 아랍어 같은 complex script의 입력과 위치 계산도 기본적인 건 그럭저럭 처리해 낸다. 우클릭했을 때 나타나는 메뉴를 보면, 텍스트의 기본 진행 방향을 L2R로 할지 R2L로 할지 지정하는 옵션이 있다.

마지막으로 입력 쪽을 살펴보면, Windows에는 TSF라는 입력 기술이 도입됐는데, 에디트 컨트롤은 기본적으로는 얘를 완벽하게 지원하지 않는다. 문자 입력기가 모든 텍스트를 자유자재로 조작할 수 있는 TSF 프로토콜은 역시나 리치 에디트 컨트롤만이 Windows XP sp1 시절부터 도입했다. 비록 이것도 모든 리치 에디트에 자동 적용되는 건 아니고, 최신 버전의 컨트롤을 사용하고 전용 메시지를 사용해야 하지만 말이다. (리치 에디트는 일반 에디트와는 달리 업그레이드가 쭉쭉 되어 온 대신, 버전 내력이 꽤 꼬여 있다..)

그렇기 때문에 이 에디트 컨트롤을 기준으로는 TSF와 관련된 두 가지 접근이 있어 왔다.
첫째는, 에디트 컨트롤을 사용하는 응용 프로그램이 윈도우 프로시저를 서브클래싱하여, 적절한 시기에 TSF API를 호출하고 TSF 인터페이스를 직접 구현하는 것이다. TSF로부터 특정 문자열을 읽거나 쓰라는 요청을 받으면, 그걸 EM_SETSEL, EM_GETSEL 메시지 같은 걸로 요청해서 결과를 되돌리면 되는 거다. 에디트 컨트롤은 단일 버퍼 기반 구조여서 텍스트 오프셋 계산은 다행히 훨씬 쉬우니까 말이다.

물론 이것은 에디트 컨트롤이 native하게 TSF를 지원하는 것보다는 효율이 훨씬 떨어지며, 오동작의 여지도 많다. 그냥 이런 발상도 가능하다는 걸 시연해 보이는 데 의미가 있을 뿐. 지금도 있는지 모르겠는데 과거에 TsfAPP라는 예제 프로그램이 바로 이걸 구현한 프로그램이었는데, 버그도 많았다.

다음 둘째로는, Windows Vista부터는 응용 프로그램이 아닌 그 밑에서 돌아가는 IME가 특수하게 요청할 경우에 한하여 에디트 컨트롤을 TSF 지원 모드로 바꿔 동작시키는 기능이 도입되었다. <날개셋> 한글 입력기는 TSF 인터페이스가 지원될 경우 기능 활용의 폭이 훨씬 더 넓어지는 관계로, 이 기능을 실제로 사용하는 옵션이 있다.
이 모드를 사용하면 한글 입력 중일 때 cursor가 깜빡이는 네모가 아니라 일반 블록 색깔로 바뀐다. 그리고 에디트 컨트롤을 특수하게 조작하는 프로그램에서 잠재적으로 오동작이 발생할 가능성도 생긴다.

이 TSF 확장 기능은 에디트 컨트롤뿐만 아니라, legacy 리치 에디트 컨트롤(=자체적으로 TSF를 지원하지는 않는 구버전)과 IE 웹브라우저 엔진이 제공하는 에디트 컨트롤에도 그대로 적용된다. 즉, 마이크로소프트가 구현한 표준 에디트 관련 컨트롤에는 거의 다 적용되므로 사용의 폭이 넓은 편이다.

이상이다.
옛날에 MSDN에서 Kyle Marsh 아저씨가 16비트 Windows 3.x 기준으로 에디트 컨트롤의 모든 기술적 디테일을 미주알고주알 늘어 놓은 글을 본 기억이 난다. 얘는 동작 방식과 규격이 20년 전이나 지금이나 완전히 굳어져 버려서 호환성 유지 차원에서 더 바꿀 수가 없고, MS가 신기술 투자는 리치 에디트에다가 집중적으로 한다고 보면 얼추 맞겠다. 그래서 리치 에디트에는 드래그 & 드롭도 있고, 하이퍼링크를 밑줄로 표시해 주는 기능도 있지만, 일반 에디트는 그런 거 없다. Ctrl+Bksp를 눌렀을 때 단어 단위로 지우는 기능 역시 리치 에디트급 이상에만 있다.

아울러, 일반 에디트는 우클릭하면 표준 메뉴가 나타나는 반면, 리치 에디트는 우클릭했을 때 제공되는 기본 메뉴가 없고 그걸 전적으로 사용자의 customization에 맡기고 있다는 차이가 있다.

Posted by 사무엘

2014/05/29 08:40 2014/05/29 08:40
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/968

« Previous : 1 : ... 132 : 133 : 134 : 135 : 136 : 137 : 138 : 139 : 140 : ... 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:
3051150
Today:
2170
Yesterday:
2142