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

헷갈리는 개념들 Q&A

어찌 보면 이런 것들을 인제야 깨우친 본인의 무식-_-을 인증하는 아이템들인지도 모르겠는데, 뭐 그냥 재미로 나열해 보았다. 서로 제각기 다른 분야들이다.

1. 스플래시 데미지 + 타격 데미지?

공격이라는 게 존재하는 거의 모든 게임에는.. 그냥 목표물에만 총알의 운동량을 박아 넣는다는 설정인 일반 데미지가 있고, 그에 덧붙여 발사체가 폭발 후 파편을 터뜨려서 주변에 추가적인 데미지까지 입히는 스플래시 데미지가 있다.

난 폭탄을 직통으로 맞은 놈은 데미지가 100, 그리고 폭심지로부터 멀어질수록 데미지는 1/n 내지 1/n^2 등등으로 감소.. 이런 모델만 생각하곤 했다. 스타로 치면 리버나 시즈 탱크, 혹은 핵의 스플래시 데미지 계산 방식처럼 말이다.
그러나 둠 내지 퀘이크 같은 FPS 게임은 로켓 런처의 경우, 로켓을 맞은 것 자체에 대한 타격 데미지를 스플래시 데미지와는 별개로 계산한다. 로켓을 직통으로 맞으면 맞은 데미지 100에다가 파편 스플래시 데미지 100을 추가로 받아서 200을 먹으며, 주변에 있던 놈들은 폭심지로부터의 거리에 따라 100 이하의 데미지를 받는 것이다.

그리고 전통적으로 보스급 대형 몬스터들은 스플래시 데미지를 받지 않아서 로켓 공격을 사실상 절반씩밖에 먹지 않았다. 반대로 플레이어에게도 스플래시 데미지를 받지 않게 하는 파워업 아이템이 꼭 있곤 했다. (퀘이크 3 Arena의 Battle Suit처럼.)

제자리에 가만히 있던 수류탄의 폭발을 직통으로 당한 것이라면 스플래시만 있는 게 맞다. 그러나 로켓 런처의 경우 총알보다는 느리지만 그래도 총알보다 더 크고 무거운 로켓을 맞은 것이니 이놈 자체의 운동량부터 타격 데미지로 치는 것이 가만히 생각해 보니 더 합리적이긴 해 보인다. 지금까지 이런 생각을 안 하고 있었다.

로켓 점프는 스플래시 데미지만으로 점프를 하는 것이다. 게임에서는 구현 가능하지 않지만 로켓을 바닥이 아니라 내 배에다 대고 쐈다면 그건 타격 데미지와 스플래시를 이중으로 받는 것일 테고.

2. 자동차 직진과 후진 평행주차의 차이

평행주차는 주차 중에서도 꽤 어려운 스킬이지만, 정식 주차장이 아닌 길가에다 적당히 차를 세울 때는 반드시 할 줄 알아야 하는 스킬이다.
평행주차는 주차 지점을 지나친 뒤 후진으로 진입했다가 마지막에 핸들을 확 꺾어서 집어넣는 게 정석이다. 그런데 본인은 왜 하필 후진인지를 뭔가 수학적인 증명 수준으로 이해를 잘 못 했다. 후진으로 가능한 것은 전진으로도 똑같이 가능하지 않은가? 평행주차는 왜 전진이 후진보다 어려우며 공간이 더 많이 필요한 걸까?

그래서 머리에다 종이를 펴고 그림을 그려 보고서야 원리를 이해하기 시작했다.
핸들을 완전히 90도로 꺾을 수 있다면 후진 방식은 차 뒷부분부터 주차 지점에 박아 넣은 뒤, 앞부분은 앞바퀴의 회전을 통해 추가 공간 없이도 쏙 집어넣을 수 있다.

그러나 전진 방식은 핸들을 많이 꺾는다고 해서 차를 집어넣는 게 가능치 않으며, 회전 후에 차가 완전히 평행한 방향을 복원할 때까지 추가적인 주행 공간이 필요하다. 구조적으로 더 어려울 수밖에 없게 된다.
또한 발상을 반대로 바꿔서 생각해도 된다. 평행 주차되어 있던 곳에서 차가 “빠져나갈 때는” 전진이 아주 유리한 반면 후진은 완전 어렵다는 걸 알 수 있다.

전진과 후진으로 모두 수월하게 방향을 틀 수 있고 평행 주차가 가능하려면 앞바퀴와 뒷바퀴가 모두 조향 가능해야 한다. 비좁은 실내에서 작업하는 걸 염두에 두고 만들어진 지게차 정도나 이런 조건을 만족한다.

3. 스포츠 사격과 군대 사격

군대 미필자나 여성분들은 잘 모르실 수도 있으니 설명하자면..
군대 사격이 거리가 더 멀고 큰 표적을 쏜다. 스포츠 사격 종목은 수십m대이지 무슨 250m씩이나 되는 거리를 쏘지는 않는다.
스포츠 사격은 가까운 대신 정밀도도 상상을 초월한다. 양궁만 해도 과녁이 얼마나 작은데, 격발이 더 쉬운 총으로는 그야말로 정말 코딱지만 한 표적을 명중시켜야 국제 스포츠로서 밸런스가 유지될 정도다.

그리고 스포츠 사격에서 사용되는 총기는 권총이든 라이플이든 정밀도 향상에 왕창 최적화돼 있다. 반동을 최소화하려고 총이 굉장히 무거우며--군대 돌격소총의 2배 이상--, 방아쇠도 아주 아주 살짝만 건드려 줘도 바로 격발된다. 스포츠용 총이 무슨 행군시의 무게를 고려한다거나 할 필요는 없으니까. 그리고 총의 살상력 내지 대인저지력은 아무래도 군인용 총만치 강하지는 않다.

영점 잡는 건 두 부류의 총으로 각각 어떻게 하는지는 잘 모르겠지만, 여러 정황상 군대에서의 저격수 내지 특등사수가 스포츠 사격 메달리스트하고는 완벽하게 호환되지 않는다고 보는 게 타당하다. 서로 지향하는 바가 다르니까 말이다. 스포츠 사격에 무슨 조준경을 쓰고 탄환 궤도 오차 보정을 해서 수백~1km 밖의 목표물을 맞히는 게 있지는 않다.

4. 스웨덴과 덴마크

북유럽에 서로 가깝다면 가까이 있는 나라이며 3글자짜리 이름에 '덴'자가 있다는 공통점 때문에.. 난 두 나라가 정말 지독하게 헷갈리고 분간하기 어려웠다. 사실, 폴란드와 핀란드의 차이도 지금까지도 잘 모르겠고. -_-

일단 스웨덴은 노르웨이와 접해 있는 큼직한 왕국이며, 스톡홀름 증후군의 본산지이다.
그리고 철덕들에게 친숙한 서울 지하철 5호선의 인버터를 제작한 ABB 사가 스웨덴 국적이기도 하다. (더 정확히는 스웨덴의 Asea와 스위스의 Brown Boveri가 합병하여 ABB라고..)
자동차 제조사 VOLVO가 스웨덴에서 출발한 기업이며, 또한 다이너마이트를 발명한 알프레드 노벨이 스웨덴 출신임.

다음으로 덴마크는 그 밑에 있는 아주 작은 나라이다. 수도는 코펜하겐 되시겠다. 본토는 아주 작지만 그린란드가 덴마크령이다.
덴마크 하면 유명한 사람은 동화 작가인 안데르센이다. 그리고 프로그래밍 언어 분야에서 전세계를 평정한 괴수 컴퓨터 과학자가 두 명이나 미국이 아닌 덴마크 사람인 것은 상당히 의미심장한 일이다.

한 명은 C++ 언어를 고안한 Bjarne Stroustrup (1950~)으로, 더 설명이 필요하지 않을 것이다.
다른 한 명은 Anders Hejlsberg (1960~)로, 왕년에 볼랜드에서 터보 파스칼과 델파이를 개발했다가, 마이크로소프트로 이직한 뒤에는 C# 언어를 설계하고 관리하고 있는 브레인이다.

5. 오르막과 단순 하중의 차이

자전거를 타는데 단순히 뒤에 짐을 많이 싣는 것하고, 짐은 없지만 오르막을 오르는 것 둘 중 “어느 게 더 힘들까? 이걸 정량적으로 수식으로 나타내는 방법은 없을까?”를 생각한 적이 있었다. 자동차로 치면 어느 게 연료가 더 많이 드느냐 하는 것이다.

당장 바퀴와 지면 사이의 마찰계수부터 시작해서 생각해야 할 개념이 많을 것이나, 그래도 중· 고등학교 수준의 고전역학 지식으로도 어느 정도 답이 나올 것이다.
뒤에 백수십 kg 정도 되는 수레를 끌고 가든, 1~2도 정도의 오르막을 오르든 똑같이 힘이 더 많이 필요하고 출발이 더 어려워지는 건 마찬가지이다.
그래도 단순히 하중만 많이 실린 것은 일단 가속을 한 후에는 어느 정도 관성의 덕을 볼 수도 있으며 크게 힘든 게 없다.

그에 반해 오르막은.. 끊임없이 페달을 밟아 줘야 한다. 안 그러면 서 버리는 정도가 아니라 자전거가 뒤로 밀려난다. 단순히 무거운 하중이 걸린 차원이 아니라, 누군가가 약하게나마 뒤쪽으로 페달을 역으로 꾸준히 밟고 있다고 봐야 한다.
그러니 주행하는 거리가 길어질수록 짐보다는 오르막이 확실히 더 큰 장애물이 될 듯하다.

이것과 비슷한 맥락으로, 사진을 찍을 때 대상 물체를 크게 찍기 위해 줌을 당기는 것하고, 그냥 대상에게 가까이 가는 것하고 차이가 무엇인지도 생각한 적이 있었다.
피사체가 단순히 2차원적인 형상일 뿐이라고 생각한다면 둘은 동일하게 피사체를 확대하는 효과를 낸다.
그러나 당연한 말이지만, zoom을 당기는 것은 주변 배경의 원근감을 동일하게 내 주지는 않는다. 그런 차이가 있다. 이것도 오르막과 하중의 차이와 비슷한 맥락인 걸까? ㅎㅎ

6. 럭비와 미식축구의 차이?

스포츠에 완전 문외한이고 관심이 없는 본인으로서는, 둘 다 얼굴에 무슨 펜싱 선수 같은 보호구를 쓰고 손과 발을 모두 동원해서 갈색의 타원형 공을 향해 미친 듯이 쫓아다니는 구기 종목으로밖에 보이지 않는다.
하지만 둘은 규칙이나 체계가 많이 다르다고 한다. 얘는 더 자세한 설명은 패스.. ㅋㅋ

Posted by 사무엘

2014/08/04 08:20 2014/08/04 08:20
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/992

1. 지하철에서 “대형” 화재가 발생했을 때는 차라리 선로로 대피하는 게 낫다

화재 현장에서 목숨을 잃는 사람들은 소사보다는 질식사가 훨씬 더 많다는 게 상식이다.
일반적으로는 깊은 지하가 빛도 안 들어오고 산소도 부족해서 생존에 불리한 게 사실이지만, 지하철은 말 그대로 지하에 뚫린 길이다. 지하가 길이 더 없는 막다른 던전이 아니라는 큰 차이가 있다.

유독가스는 위로 굉장히 빠르게 잘 퍼진다. 대구 지하철 화재 참사 때도, 발상을 전환하여 앗싸리 선로로 대피해서 멀찌기 인접역까지 걸어 간 후 거기서 지상으로 빠져나온 소수의 사람들은 다 별다른 부상 없이 멀쩡히 살아 나왔다.
그 반면, 대부분의 다른 사람들은 당장 지상과 더 가까워 보이는 화재 발생 당역의 출구를 통해 나가려 했으며, 그 결과는 좋지 못했다. 살아서 빠져나가지 못하거나, 생존하더라도 유독가스 흡입으로 인해 몸이 상했다. 후자가 더 안전할 것 같은데 결과는 정반대였던 것이다.

특히나 지하 n층 이하의 매우 깊은 역이라면 정말로 무리해서 지상으로 빠져나갈 생각일랑은 버리고 선로로 대피하는 게 더 훨씬 더 안전할 것이다. 선로가 단선 쌍굴이라면 통행하기가 좀 무섭겠지만, 그래도 지하철에서 그 정도 사고가 났다면 어차피 근처 열차들은 안전 장치 내지 사령부로부터의 지시를 받고 멈추니 열차에 치일 걱정은 안 해도 된다. 단, 요즘은 스크린도어가 역설적으로 이런 선로 탈출에 악재로 작용할 가능성이 있다.

2. 구명조끼는 탈출 후에 부풀려라

육상 교통수단과는 달리 비행기나 배는 사고가 났을 때 사망, 부상뿐만 아니라 실종이 있을 수 있다. 그래서 탑승 전에 신분증으로 탑승객의 신원을 일일이 확인한다.
또한 얘들은 추락이나 침몰로 인해 동체가 수면에 떨어질 수 있다. 안전벨트와 산소 마스크는 비행기에만 있지만, 구명조끼는 두 교통수단이 공통으로 갖추고 있다.

비행기나 배의 위급 상황에서 구명조끼를 잘 착용하는 것까지는 좋으나, 거기에다 공기를 주입해서 부력을 만드는 건 아무리 위급한 상황이라도 해당 동체를 탈출하여 밖에 나온 뒤에 해야 한다.

이미 물에 빠져서 내부에 물이 들어오기 시작한 배나 비행기를 탈출하기 위해서는 일시적으로 잠수를 해야 할 수도 있는데, 너무 일찍 공기를 집어넣으면 이것 때문에 동체에서 탈출도 못 하고 거기서 갇혀 죽을 수도 있기 때문이다.
이것은 1996년의 에티오피아 항공 961편 피랍 사건과 최근의 세월호 침몰 사고에서도 실제로 일어났던 일이다. 선실에서 숨진 채 발견된 사람들이 부풀어 오른 구명조끼를 입고 있던 것은 바르게 행동한 것이 아니었다.

저 비행기 피랍 사건도 마찬가지다. 동반 자살을 유도하던 테러리스트 때문에 비행기는 연료가 고갈되어 추락했다. 기장은 필사적인 노력으로 기체를 바다 위에 최대한 안전하게 착수시켰으며, 적절한 대처를 한 공로를 인정받아 나중에 상까지 받았다고 한다. 그러나 170여 명의 승객과 승무원 중 목숨을 부지한 사람은 50명에 그쳤는데, 사망자들은 구명조끼를 기내에서 미리 부풀리는 바람에 침수되고 있는 동체에 갇혀서 최후를 맞이한 경우가 적지 않았다고 한다.

Posted by 사무엘

2014/07/30 08:34 2014/07/30 08:34
, , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/990

국어, 언어학 잡설

1. '여' 불규칙

ㄱ부터 ㅎ까지
'가다(go), 나다(bring forth), 사다(buy), 자다(sleep), 차다(kick), 타다(get on), 파다(dig)'
라는 용어들을 생각해 보면, 이들은 과거형은
'갔다, 났다, 샀다, 잤다, 찼다, 탔다, 팠다'
라는 아주 규칙적인 패턴으로 활용된다.

그러나 잘 알다시피 '하다'(do)만은..
'하였다' 아니면 '했다'라고 굉장히 이상하게 활용된다. 중등학교 국어 시간엔 이를 '여' 불규칙이라고 배운다.
그런데 어미 '여'가 쓸데없이 붙는 것도 이상한데, 그게 축약되어서 '했다'가 되는 건 또 뭐냐..? '하다' 말고 그 어떤 용언도 활용 시에 ㅏ와 ㅐ가 그런 식으로 연계하여 변하는 경우는 없다.

'가다'의 경우, 다른 'Xㅏ다' 용언과는 달리, 명령형에서 '가거라'라고 생뚱맞은 '거'가 불규칙으로 첨가되기는 한다. 그러나 이 '거'는 명령형에서만 첨가되지 '해서/하여서, 했다/하였다'의 '여'에 비하면 등장이 훨씬 제한적이다.

'갔다', '팠다'처럼 '핬다'라는 단어는 한국어의 역사상 존재한 적이 없었던 걸까? 원래 있긴 했는데 혹시 전설모음 역행동화가 일어나서 '했다'라고 바뀌기라도 한 건 아닐까? 난 잘 모르겠다.

본인은 '바라다'가 자꾸 '바랬다', '바랬는데', '바램'처럼 활용되는 것도 비슷한 맥락의 현상이 아닌가 하고 거의 10년도 넘게 더 전부터 생각해 왔다. '하다'는 '함'이 '햄'으로 바뀌는 건 아니니 둘이 완전히 같은 양상은 아닌지도 모른다.
그리고 이것도 자음 하나만 다른 '자라다'는 활용 과정에서 '라'가 '래'로 바뀌는 현상이 결코 전혀 없으니 참으로 이상하지 않을 수 없다. '자랐다', '자랐는데', '자람' 등.. =_= 신기하다.

2. 지난 학기에 들은 변형 생성 문법 수업의 편린

(1) 아무래도 교재가 영어 원서이고 영어 통사론을 다루는 비중이 적지 않다 보니.. 선생님이 영어 고어 문법 얘기도 종종 하셨다. 그래서 내 머리엔 KJV 영어가 떠오른 적이 적지 않았다.

옛날에는 be + 동사PP가 수동태뿐만 아니라 마치 지금의 have + 동사PP처럼 완료 시제를 나타내기도 했다고 한다. KJV에 "is come"이 왜 이리도 많이 등장하는지 이제 알 것 같다.

(2) have가 의문문으로 등장할 때 Do you have 대신 곧바로 Have가 나오는 거..
난 개인적으로 have ye any meat? (요 21:5)가 곧장 떠오르던데 오늘날에도 이런 패턴이 영국의 일부 방언으로 남아 있다고 한다.
마치 C언어로 치면, C이긴 한데 오늘날 안 쓰는 오리지널 K&R 스타일 C 같은 느낌이다. #include 과감히 생략하고 main 함수에 int나 return 다 생략하고 바로 printf("hello, world!");를 하는... 좋게 말하면 간결하고 나쁘게 말하면 불친절한 스타일 되겠다.

(3) 문법을 설명하는 데도 문장 구조 binary tree를 그려서 노드를 이리 저리 옮기는 게 많다. 마치 빨강 검정 나무의 동작을 다루는 것 같았다. 물론 둘은 개념과 성격은 서로 완전히 다르지만 말이다.
또한, 전산학 자료구조 시간에는 tree 노드를 표현할 때 sibling, child 등 다 중성 어휘를 쓰지만, 언어학에서는 sister, daughter 같은 여성형 어휘를 쓰더라.

프로그래밍 언어와 자연어를 설명하는 이론을 모두 마스터하고 싶다.

Posted by 사무엘

2014/07/28 08:33 2014/07/28 08:33
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/989

C/C++에서 구조체나 클래스는 통상적으로 global scope에서 선언되거나 기껏해야 다른 클래스 내지 namespace의 내부에서 선언된다. 즉, 어차피 비실행문들만 있는 곳에서 선언되는 편이다.
그러나 실행문으로 이뤄져 있는 함수 안에서 이들을 새로 선언하는 것도 문법적으로 가능하다. 다시 말해, 변수를 선언하는 것뿐만 아니라 그 변수들의 type을 결정하는 구조체나 클래스를 즉석에서 선언해 쓰는 것도 가능하다는 뜻이다.

다른 곳에서 두고두고 재사용하는 구조체가 아니라 함수 한 곳에서 튜플 같은 형태로 잠깐만 사용하고 마는 구조체라면, 이런 식으로 함수 안에서 간단히 선언해서 사용하면 좋다. 하긴, 그러고 보니 struct, class, union, enum뿐만 아니라 typedef도 실행문과 비실행문 문맥에서 모두 사용 가능한 물건이다.

함수 안에서 클래스 같은 걸 따로 선언하는 건 C#에서는 가능하지 않으며 C++만의 전유물인 듯하다.
이렇게 함수에서 선언된 자료형은 유효 범위도 마치 지역변수처럼 그 함수 안으로 완전 local하게 한정된다. 그래서 각종 IDE 같은 데에 명칭이 뜨지도 않는다. 지금부터는 이와 관련해서 좀 더 기괴한 이야기들을 풀어 보겠다.

1. 무명 자료형

C/C++에는 '이름 없는' 구조체/클래스/공용체 따위의 개체가 있을 수 있다. '이름 없는' 함수 그 자체만의 선언은 지원되지 않아서 함수형 프로그래밍 패러다임이 도입된 C++0x 이후에서야 람다와 함께 등장한 반면, 이름 없는 복합 자료형이라는 개념은 있었던 것이다.

class {
public:
    int x,y,z;
} obj;

C#이나 자바 스타일이라면 상상도 할 수 없는 일이겠지만, C/C++은 자료형의 선언과 해당 자료형에 속하는 변수의 선언을 동시에 할 수 있다. class OBJ { ... } a,b,c; 도 OBJ a,b,c;나 심지어 int a,b,c;와 개념적으로 같다.
class, struct, enum, union 등을 선언한 뒤에는 닫는 중괄호 다음에 세미콜론을 반드시 붙여야 하는 이유가 바로 이 때문이다.

그런데 이름 없는 자료형은 자료형의 선언과 함께 변수 선언도 같이 해 주는 게 선택이 아닌 '필수'라는 차이가 있다. 그도 그럴 것이, 얘는 이름이 없는 일회용 자료형인 고로 그 자료형을 선언하는 구문이 끝난 뒤에는 그걸 지칭할 방법이 없기 때문이다. 변수가 단 하나라도 같이 선언돼 있어야 나중에 C++11의 auto 라도 써서 그것과 동일한 자료형의 변수를 추가로 만들 수 있을 것이다.

이런 무명 자료형이라는 개념은 대개 한 자료구조 내부에서 구조체와 공용체를 섞어 가며 쓸 때 유용하지만, 그렇잖아도 일회용 성격이 강한 local 자료형에서도 더욱 의미가 있다. 굳이 이름을 생각할 필요 없이 내가 생각하는 복합 자료형을 간단하게 만들어서 쓰게 해 주기 때문이다.
물론 local뿐만 아니라 global scope에서도 무명 자료형을 얼마든지 선언해서 쓸 수 있다. C/C++의 오묘한 면모 중 하나이다.

2. 함수 안에 함수

C/C++은 복합 자료형은 앞서 살펴보았듯이 무명으로 선언할 수 있고, 그 안에 또 다른 복합 자료형을 nested된 형태로 선언하고 집어넣을 수 있다. 그러나 실행되는 코드의 집합인 함수를 그렇게 일종의 값처럼 자유자재로 다룰 수 있지는 않았다.

함수 자체를 다른 함수에다가 전달하는 것은 그나마 함수 포인터가 있으니 불가능하지는 않지만, 그건 자료형, 함수명 등에 대한 작명이 필요하며 기계 중심적이고 융통성이 부족했다. 또한 함수 안에다가 또 일회용으로 간단히 쓰고 마는 함수를 잠깐 선언하는 것도 가능치 않아서 global/class scope 차원에서의 선언이 필요했다. 남는 건 매크로 함수밖에 없지만 이게 얼마나 구조적으로 허접한 물건인지는 역시 설명이 필요하지 않는 수준이고.

void func()
{
    void simple_func(int x) { }

    simple_func(0);
    simple_func(1);
}

nested function은 C와 파스칼의 큰 차이 중 하나이기도 했다. 파스칼은 지원하지만 C/C++ 계열은 지원하지 않았기 때문이다. 마치 가변 길이 배열만큼이나 언어 차원에서 결코 지원되지 않을 금기 봉인 사항이기라도 한가 궁금하다. 다만, 옛날에 gcc던가 극소수 C 컴파일러에서 확장 옵션을 통해서 nested function을 지원하는 걸 본 것 같다.

물론, 중첩 함수를 써서 할 수 있는 일은 중첩 함수라는 개념이 없이도 완전히 똑같이 할 수 있기 때문에 상호 등가 교환이 가능하다. 마치 클래스에서 public과 private 구분을 해 주든, 아니면 전부 싸잡아 public인 struct로 코드를 작성하든.. 이것은 코드의 유지 관리의 편의성 내지 정보 은닉하고만 관계가 있지 프로그래밍 언어의 구조적인 계산 능력과는 무관한 것하고 같은 맥락이다. 그래서 C/C++은 nested 함수라는 개념을 도입하지 않은 듯하다. 정수 타입에 subrange 같은 개념도 없을 정도이니 뭐~

지금이야 람다 덕분에 함수 안에 함수의 선언이 사실상 가능해졌다. 캡처 같은 새로운 개념도 같이 도입됐다. 하지만 이건 일반적인 함수와 개념적으로 같은 물건은 아니다.
C++에서는 (1) 중첩 namespace 안에 들어있는 함수가 얼추 비슷한 개념일 수 있으며, 이것 말고도 좀 더 직접적으로 함수 안에 함수를 만드는 것이 편법 우회 경로로 가능하다. (2) 바로 함수 안에 클래스를 선언하고 멤버 함수를 정의하는 것이다. 이런 식으로.

int main(int argc, char* argv[])
{
    class A {
    public:
        static void Func() { puts("function inside function"); }
    };
    A::Func();
    return 0;
}

특히 static 함수는 this 포인터를 사용하지도 않으니 진짜로 일반 함수와 다를 바가 없다.
함수 안에다 구조체를 정의하는 것으로도 모자라서 완전한 형태의 클래스를 정의하고 멤버 함수를 정의하는 것까지도 가능하다니 놀랍지 않은지?

단, 이런 지역 클래스에서 멤버 함수를 선언할 때는 논리적으로 당연한 제약이 하나 걸린다. 함수의 몸체는 반드시 그 클래스 안에서 저렇게 정의되어야 한다. 안 그러면 아까 무명 자료형에서 변수 선언을 바로 안 해 줄 때처럼 경고가 뜬다.

비주얼 C++의 경우 일단 C4822 경고만 뜨고 그걸 실제로 호출까지 한 경우 링크 에러가 났지만, 요즘은 그 즉시 C3640 에러도 같이 나오는 듯. 링크 에러가 더 친절하게 컴파일 에러로 바뀌었다.
클래스의 밖인 그 함수 몸체 안에서 또 void A::Func() { } 이런 식으로 함수 몸체를 따로 정의하는 건 문법적으로 허용되지 않기 때문이다.

또한, 이런 이유로 인해, 지역 클래스는 static 멤버 함수는 가질 수 있는 반면 static 멤버 변수(=데이터)는 가질 수 없다.
그건 함수 안의 일반 static 변수와 같은 취급을 받으려나 궁금했는데, 만들어 보니 그건 언어 문법 차원에서 허용되지 않으며 곧바로 컴파일 에러가 난다. static const도 허용되지 않는다.

그러고 보니 이름 없는 클래스도 static 멤버 변수를 사실상 가질 수 없을 듯하다. 사실, 이름 없는 클래스에다가 그런 것까지 바라는 것 자체가 변태 도둑놈 심보이긴 하다. ㅎㅎ
멤버 함수야 몸체를 클래스의 선언부 안에다 강제로 집어넣는 식으로 정의할 수 있지만 static 변수는 결국 클래스 밖에서 따로 정의를 해야 하는데, 클래스 이름이 없으니 정의를 할 수 없어서 링크 에러가 나기 때문이다.
이거 정말 복잡한 문제다. C++이 C#/Java하고는 다른 독특 기괴한 면모가 이런 데서 또 발견된다.

Posted by 사무엘

2014/07/25 08:32 2014/07/25 08:32
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/988

라벨, 에디트, 리스트 박스, 콤보 박스, 일반 버튼, 라디오/체크 박스.
이름만 들어도 친숙한 이 물건들은 응용 프로그램의 대화상자에 들어가는 그야말로 필수 GUI 구성요소들이다.

여기에다 리스트 컨트롤, 트리 컨트롤 같은 더 고급스러운 공용 컨트롤까지 있으니 실무에서는 사실 99%에 가까운 일은 기존 컨트롤만으로 다 해치울 수 있다.
사소하게 마음에 안 들고 동작 방식을 좀 고쳐야 하는 건, (1) 이들이 제공하는 owner-draw 옵션(주로 외형 외주) 내지 일부 메시지에 대한 (2) 윈도우 프로시저의 서브클래싱으로 customize 가능하다.

그러나 아주 가끔은, 기존 컨트롤과는 동작 방식이 완전히 다른 새로운 윈도우를 내가 머리부터 발끝까지 직접 구현하여 대화상자에다 집어넣어야 하는 경우가 있다. 기존 컨트롤을 약간만 고치는 정도로는 성이 안 찬다.

본인이 개발한 <날개셋> 한글 입력기의 GUI를 보면 이런 custom 컨트롤들이 적지 않게 보인다. 당장 비트맵 글꼴을 사용하는 자체 에디트 컨트롤은 편집기의 클라이언트 영역뿐만 아니라 대화상자에서 입력란으로도 쓰인다. 그리고 한글 낱자를 뽑아 오는 독특한 스타일의 콤보 박스라든가 문자표 리스트, 글쇠배열 편집 윈도우도 다 자체 개발한 custom 컨트롤이다.

꼭 그렇게까지 특이한 용도의 윈도우가 아니더라도.. 이걸 생각해 보자.
자체적인 키보드 포커스를 받으며, 화살표 key나 마우스 휠로 2차원적인 스크롤이 가능한 형태로 그림 같은 owner-draw 컨텐츠를 출력하는 컨트롤.
쉽게 말해 MFC로 치면 CScrollView에 해당하는 컨트롤이다. 특이할 것 없는 아주 기본적인 기능임에도 불구하고 기존 컨트롤의 서브클래싱만으로는 구현 가능하지 않다.

키보드 포커스를 받지 않으며 스크롤 같은 것도 없이 고정적인 owner draw 그림만을 화면에 달랑 그리는 거라면 쉽다. 기성 컨트롤인 STATIC 윈도우에다 owner draw 스타일을 줘서 WM_DRAWITEM 메시지를 처리하거나, 아예 서브클래싱을 해서 WM_PAINT 메시지를 통째로 가로채면 된다.

그러나 스스로 키보드와 마우스 입력을 처리하는 윈도우라면 독립된 형태로 자체 구현이 불가피하다. 여러 메시지들에 대한 동작을 인위로 고쳐야 하기 때문이다.
<날개셋> 편집기에서 화면 인쇄를 시켰을 때 화면 인쇄 결과를 출력하는 윈도우가 바로 이런 용도로 만들어진 custom control이다.

custom control을 MFC를 써서 개발한다면 응당 CWnd에서 파생된 새로운 클래스를 떠올리게 될 것이다. 이 C++ 클래스는 자신만의 윈도우 클래스 이름을 갖고 있을 것이고 자신을 운영체제에다 등록하는(RegisterClass 호출) 함수도 static 형태로 갖추고 있어야 할 것이다. (응용 프로그램이 실행 초기에 호출함)
그리고 대화상자 리소스에는 그 클래스 이름을 지정해 놓은 custom 컨트롤을 마음껏 생성해 놓는다.

그런데 대화상자의 컨트롤들은 내가 CWnd::Create를 호출하여 만드는 게 아니라 운영체제의 대화상자 관련 함수들이 CreateWindowEx에다가 윈도우 클래스 이름만 달랑 줘서 만들어진다. 이렇게 C++ 언어 체계의 통제를 받지 않고 밖에서 만들어진 HWND에다가 MFC 기반의 C++ 개체는 어떤 메커니즘을 통해 상호 연결시켜야 할까?

단순히 CWnd::FromHandle 함수 같은 걸로 임시 CWnd만 달랑 생성해서 연결하는 게 아니다. 이 custom 컨트롤은 구현체 클래스가 존재하니, 그냥 CWnd가 아니라 내가 만든 전용 CWnd 파생 클래스가 정확히 연결돼야 한다. 그렇게 해야 응용 프로그램 해당 윈도우끼리는 type-safe하지 않고 불편한 메시지를 쓸 필요 없이 C++ 멤버 함수/변수에 직통으로 가능해지니 좋다.

연결하는 방법은 크게 두 가지가 있다. 먼저, C++ 클래스의 생명 주기를 윈도우 자체의 생명 주기와 일치시키는 것이다. 만드는 윈도우 클래스에다가 윈도우 프로시저를 아래와 같이.. MFC의 AfxWndProc와 거의 똑같은 형태로 작성해 준다.

LRESULT CALLBACK CHeapCtrl::_MyWndProc(HWND hWnd, UINT msg, WPARAM w, LPARAM l)
{
    CWnd *pWnd = CWnd::FromHandlePermanent(hWnd);
    if (pWnd==NULL) { pWnd=new CHeapCtrl; pWnd->Attach(hWnd); }
    return AfxCallWndProc(pWnd, hWnd, msg, w, l);
}

이 개체는 언제나 new 연산자를 통해 heap에만 생성된다. 그러므로 PostNcDestroy 함수를 다음과 같이 구현하여 윈도우와 함께 C++ 개체도 같이 소멸되게 해 줘야 한다.

void CHeapCtrl::PostNcDestroy()
{
    delete this;
}

또한 대화상자 내부에서는 CHeapCtrl을 언제나 포인터를 통해 접근해야 한다.

CHeapCtrl *p = DYNAMIC_DOWNCAST(CHeapCtrl, GetDlgItem(IDC_MYCONTROL));

둘째 방법은.. 대화상자이니까 가능한 더 간단한 방법이다. 대화상자 클래스에다가 해당 컨트롤 클래스의 개체를 선언한다. 윈도우 클래스를 등록할 때 WNDCLASS 구조체에다가 윈도우 프로시저는 그냥 쿨하게 DefWindowProc이라고 주면 된다.

CStackCtrl m_wndCustomCtrl;

그리고 윈도우와 C++ 개체를 그냥 이렇게 컨트롤 변수로 연결해 버린다.

void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_MYCONTROL, m_wndCustomCtrl);
}

이 경우, CStackCtrl은 스택, 아니 최소한 대화상자 클래스와 동일한 메모리에 생성된다. 그래서 개체를 포인터를 거치지 않고 더 간편하게 접근할 수 있을 뿐만 아니라, 대화상자 같은 윈도우 개체가 사라진 뒤에도 C++ 객체가 갖고 있던 내부 정보에 접근을 할 수 있다. PostNcDestroy 처리가 필요하지 않음은 두 말할 나위도 없고. 여러 모로 더 속 편하다.

윈도우 클래스상으로 이 윈도우는 프로시저가 아무 특수한 일도 하지 않는 DefWindowProc로 지정되어 있지만, DDX_Control 함수는 윈도우 프로시저를 서브클래싱하고 저 윈도우의 핸들을 우리가 준 CStackCtrl에다가 연결해 준다. 그래서 각종 메시지가 발생했을 때 CStackCtrl의 메시지 맵에 등록된 핸들러 함수가 호출되는 것이다.

윈도우 클래스와 MFC 클래스를 연결한 건 시작일 뿐이고 본격적인 코딩은 지금부터이다. 그야말로 산 넘어 산이다.
WM_PAINT와 필요하다면 WM_SIZE를 처리해야 할 것이고, 키보드 포커스를 받는 물건으로 계획을 했으니 WM_GETDLGCODE를 잡아서 스크롤을 위해 최소한 DLGC_WANTARROWS 정도는 되돌려야 할 것이다. 다른 단축키 같은 걸 추가로 인식하려면 DLGC_WANTCHARS도 필요할 테고.

스크롤이 되는 윈도우라면 요즘은 마우스 휠 인식은 필수다. WM_MOUSEWHEEL을 처리해야 한다. SystemParametersInfo(SPI_GETWHEELSCROLLLINES, ...) 을 호출하여 마우스 휠의 움직임 단위를 감지하여 동작할 필요가 있다. 특히 n줄이냐, 아예 페이지 단위냐(WHEEL_PAGESCROLL)를 잘 판단해야 한다.

만드는 컨트롤에 확대/축소 배율이 존재한다면 Ctrl+휠로 배율 조절을 시키는 게 요즘 트렌드다.
또한, 전통적인 세로 스크롤용 마우스 휠뿐만이 아니라 가로 마우스 휠 WM_MOUSEHWHEEL (wheel 앞에 H 추가)이라는 게 있다는 것도 알아 두면 좋다. 마우스 현물보다는 손가락 제스처를 이용한 스크롤 기능이 있는 노트북 터치패드로 생성되는 듯하다.

어디 그 뿐이랴? 표준 인터페이스에는 아예 마우스 휠을 눌러서 구동하는 '자동 스크롤' 모드도 있다. WM_MBUTTONDOWN(마우스 가운데 버튼) 되시겠다. 이건 아까와는 반대로 마우스 실물이 아닌 노트북 터치패드로는 구경하기 힘든 모드이다.

.마우스로 화면을 끌어서 스크롤이 되게 하려면 WM_LBUTTONDOWN, WM_MOUSEMOVE 같은 메시지들을 처리하면 될 것이고.
아, 이런 것보다 더 중요하면서도 스크롤 윈도우에서 상당히 번거로운 작업이 하나 있는데 그건 바로 WM_HSCROLL 및 WM_VSCROLL 메시지이다. 우리의 편견과는 달리,처음에 SetScrollInfo 함수 하나로 전체 스크롤 크기와 영역만 지정해 준다고 해서 그 다음부터 모든 스크롤 처리가 자동으로 되는 게 아니기 때문이다.

스크롤 메시지는 사용자가 스크롤 바의 화살표(한 칸씩)를 눌렀을 때, 스크롤 바를 드래그하고 있을 때, 스크롤 바 옆을 눌렀을 때(한 페이지 씩) 등등의 상황별로 서로 다른 정보가 담긴 채로 전달된다. 그리고 이때 실제로 화면을 얼마만치 스크롤시키고 어떤 처리를 할지는 전적으로 해당 응용 프로그램에 달려 있다. 운영체제가 자동으로 해 주는 일은 없다. 이걸 처리하지 않으면 사용자가 스크롤 바를 눌러도 다른 반응이 발생하지 않는다.

바로 이런 특성 때문에 사용자가 스크롤 바를 끌고 있는 동안 화면이 바로 갱신될지, 혹은 곧장은 아니고 스크롤 바의 드래그가 끝난 뒤에야 화면을 갱신할지 같은 것도 응용 프로그램마다 달리 동작할 수 있다. 물론 반응성이 좋은 프로그램이라면 어지간하면 즉각 화면이 갱신되는 게 좋겠지만 말이다.

그리고 요즘은 화면 캡처 유틸리티들이 스크롤 캡처를 지원하는데, 이 역시 생각보다 꼼수를 써서 구현돼 있다. 화면에다 별도의 표식을 그려 넣은 뒤, 캡처 대상 윈도우에다 스크롤 메시지를 보내고 그 표시가 얼마나 이동했는지를 수동으로 점검한다. 위와 같은 높은 자유도로 인해, 저렇게 하지 않으면 그 스크롤 분량을 정량적으로 알아낼 수 없기 때문이다. (스크롤 바가 이동한 양과 그에 따라 지금 화면이 실제로 이동한 픽셀수 사이의 인과관계)

화면이 스크롤되면 ScrollWindowEx 함수를 호출해서 이미 그려진 화면은 운영체제가 제공하는 스크롤 기능으로 넘기고 새로 칠해져야 하는 최소한의 부분만 새로 칠하는 '평범한 프로그램'이라면.. 저 꼼수가 통한다.
그러나 스크롤 될 때마다 화면을 몽땅 지우고 새로 그리는 프로그램이라면, 저 표식도 지워지기 때문에 스크롤 캡처를 할 수 없게 된다.

이상이다. 윈도우의 스크롤 기능까지 얘기하다 보니 말이 또 길어졌다. 여기에도 뭔가 정량적인 동작 패턴이 분명 있는 듯한데, 그것만 추려내기는 쉽지 않아 보인다.
공통된 기능을 운영체제가 API 함수로든, 공용 컨트롤 윈도우로든 뭘로든 좀 제공을 하지 않는다면 역시나 프로그래머들이 비슷한 기능을 여전히 자체적으로 중복 구현할 수밖에 없을 것이다.

Posted by 사무엘

2014/07/22 08:36 2014/07/22 08:36
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/987

내가 컴퓨터 프로그래밍을 시작하기 전에, 심지어 철도를 빨기 전에.. 정말 까마득한 먼 옛날엔
자동차를 머리부터 발끝까지 얼마나 심취해서 진심으로 쪽쪽 빨고 지냈는지...;;

1991년, 지금으로부터 거의 23년 전에 혼자 다른 책을 베끼고 온갖 사견을 덧붙여서 만들었던 자동차 화보-_-;;가 고향집에서 뒤늦게 발견되었다. 나의 초딩 3학년 시절의 작품이다.
물론 사진 찍는 건 어머니께서 도와 주셨다. 디카가 없던 시절이니 당연히 필카로 찍고 현상해서 찾아 와서 붙였다.

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

어린 눈에는 자동차별로 타코미터의 존재 여부, 파워윈도우의 존재 여부, 그리고 뒷좌석 중앙에 팔걸이의 존재 여부가 특별하게 다가왔던가 보다.

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

르망, 각그랜저, 그리고 콩코드, 로얄 시리즈 등.. 정말 추억의 올드카들이다. 지금은 저 차 번호들은 존재할 가능성이 0에 한없이 수렴하므로 번호판을 굳이 가리지는 않았다.

사용자 삽입 이미지사용자 삽입 이미지
그 당시 우리집 자가용이었던 엑셀의 카탈로그 내지 취급 설명서를 베껴서 그린 거지 싶다. ㅎㅎ

사용자 삽입 이미지사용자 삽입 이미지
그 당시 액정 디지털 계기판, 그리고 헤드라이트에까지 와이퍼가 달려 있던 임페리얼을 무척 신기하게 여기고 인상깊게 관찰했었다.

사용자 삽입 이미지사용자 삽입 이미지
대략 이런 내용.
걍 이 취미를 그대로 유지해서 현대 자동차에라도 입사했으면 돈은 더 많이 벌었겠다는 생각이 폭풍처럼 든다. ㅠ.ㅠ

Posted by 사무엘

2014/07/19 08:22 2014/07/19 08:22
Response
No Trackback , 5 Comments
RSS :
http://moogi.new21.org/tc/rss/response/986

1. 안톤 드보르작

음악가 드보르작. 알면 알수록 대단하며 우리 같은 후대의 철덕들의 귀감이 되는 존경스러운 철덕이다. 우리 모두 드보르작을 본받자. 불끈!

진 회숙의 <클래식 오딧세이> 중에서

드보르작은 사실 상당히 괴팍한 성격의 소유자였다고 한다. 그는 한 가지 것에 거의 편집증에 가까운 집착을 가지고 있었는데 그것은 기관차와 역, 철도에 관한 것이었다. 프라하에 살고 있을 때, 그는 매일같이 프란츠 요제프 역으로 가 입장권을 사서 구내로 들어간 다음 역 구석구석을 자세히 살펴보고, 개찰구의 역원이나 짐꾼, 감시원, 기관사들과 농담을 하기도 하고 기차에 관한 궁금한 사항을 물어보며 시간을 보내곤 했다.

기차 시간표를 줄줄이 암기하고 있었던 그는 열차가 가끔 늦기라도 하면 마치 큰일이나 난 것처럼 지나가는 역원이나 승객에게 그 이유를 물으며 야단법석을 피웠다고 한다.

그렇다고 음악원 선생 노릇을 전폐하고 역에 머물 수는 없는 노릇. 하지만 음악원에서 학생을 가르치고 있을 때에도 그는 틈틈이 역장이 가지고 있는 것과 똑같은 고풍스러운 시계를 신경질적으로 꺼내보며 열차의 도착 시간을 점검하곤 했다. 그러다가 정 궁금하면 학생을 역으로 보내 11시 20분 도착 예정인 브륀-프라하 행 급행열차 158호가 정시에 도착했는지, 기관사인 야로슬라브 보트루바가 무슨 재미있는 경험을 하지나 않았는지 알아오게 했다.

이 때문에 노바크, 수크, 피비히, 레하르와 같은 미래의 대음악가들이 종종 수업을 중단하고 스승의 취미에 봉사하기 위해 요제프 역으로 달려가야만 했다. 그러다가 언젠가 꾀가 난 제자가 역에 다녀오지도 않고 다녀온 것처럼 꾸며서 애기한 적이 있었다. 하지만 거짓말이 곧 들통이 나 그 제자는 드보르작으로부터 무척 호되게 야단을 맞았는데 그 제자의 표현을 빌면 당시 드보르작의 모습이 마치 ‘기차 화통을 삶아먹은 것’ 같았다고 한다.

어느 날 드보르작의 딸과 약혼한 제자 요제프 수크가 고향에서 돌아왔다. “그래, 여행은 어땠는가?”하고 드보르작이 물었다. “모든 것이 즐거웠습니다. 우리는 2시 34분 정각에 크로세비치를 출발해 3시 13분에 벤샤우에 도착, 거기서 물을 공급 받고, 3시 28분에 발차하여 5시 46분에 프라하에 도착했습니다. 아, 그리고 저희가 탄 열차의 번호는 10726번이었습니다.”

이렇게 얘기하고 나서 수크는 ‘이 정도면 스승이 만족했겠지’ 하고 생각했다. 그런데 웬걸? 그의 대답을 들은 스승의 표정이 그다지 밝지 않은 것이었다. 씁쓸한 표정을 지으며 드보르작이 하는 말,

“자네 정말 한심하군. 10726번은 열차번호가 아니라 기관차의 제작번호란 말일세. 이 벤샤우 열차의 번호는 187이야.”
이렇게 제자를 향해 쏘아붙인 드보르작은 다시 딸에게로 고개를 돌려 이렇게 물었다. “그래 너는 이런 남자와 결혼하겠다는 거냐?”

철도 차량의 번호와 운행 번호는 정말로 혼동하기 쉬운 개념이긴 하다만.. ㅋㅋㅋ
이것 말고도 드보르작의 놀라운 언행을 살펴보자. 이 사람이 오늘날 지하철이나 전기 기관차의 VVVF 구동음이라도 들었으면 정말 뿅 갔지 싶다..

“이것은 많은 부품으로 되어 있어. 너무 너무 다양한 부품들이지. 모두 각자가 모두 중요성을 가지고 있고, 각자 그 역할이 있어. 심지어 가장 작은 스크류 부속조차 제 위치에 있으며 무언가를 연결하고 있어. 모든 부품이 그 목적이 있고, 그 역할이 있어. 그 결과는 말이야 놀라워!!”

“오오 그런 기관차가 트랙에 있다니!! 그들이 석탄과 물을 넣으면 말이지, 단 한 사람이 작은 레버를 누르면, 큰 레버가 작동되기 시작해, 비록 기차는 수천 톤의 금속덩어리 인데도, 기관차는 토끼처럼 움직인다고! 내가 만약 기관차를 발명한 사람이 될 수 있다면, 나는 내가 작곡한 모든 교향곡이라도 포기할 수 있어!!


2. 유 병언

그러나 참으로 안타깝고 애석한 것은... 우리나라엔 정말 뜻밖의 인물도 완전 뼛속까지 철덕이라는 점이다.
정말 욕 나오고 분노가 치민다. 내가 다 민망하고 얼굴이 화끈거린다.

유 병언 전 세모그룹 회장이 취미생활로 알려진 각종 폐열차 구입에 약 20억 원에 이르는 거액을 쓴 것으로 밝혀졌다.
기독교 복음 침례회(구원파)가 소유한 전국 폐교, 연수원 등 4곳에 있는 각종 폐열차는 120여 량. 전남 곡성군 삼기면의 한 폐교에는 ㈜아해 소유의 폐열차 4량, 화차 58량이 있다. 벌크라고 불리는 화차는 유류, 시멘트 원료 등 각종 화물을 운송하는 데 쓰인다.


게다가 저 아저씨는 내가 재벌 갑부가 됐으면 하고 싶었던 취미생활을 정확하게 똑같이 하고 있었다.. ㅠㅠㅠㅠㅠ
금수원 사진에 웬 서울 지하철 열차가 있는 걸 보고는 깜짝 놀랐었는데, 실상은 이거 뭐 상상 이상이었다.

자고로 철덕이라면 철도를 이해하는 데 도움이 되는 문과 무와 예체능 일체의 학문을 분야 불문하고 두루 겸비한 인재로서
나라사랑 국토사랑 정신으로 국가와 사회에 기여하고 한국 철도의 향기를 좋은 간증으로 남겨 방방곡곡에 전해야 하거늘!
만나면 철덕의 명예를 걸고 한 대 패 주고 싶다.
구원파라고 해서 일반적인 기독교회까지 함께 싸잡아 팀킬시킨 게 다가 아니었구나.

서울메트로 관계자는 "유 전 회장이 폐전동차를 구입한 것이 밝혀지면서 회사 이미지에 부정적 영향을 끼칠 수 있어 앞으로는 객실을 해체해 고철로만 파는 방안을 검토 중"이라고 말했다.

"이것은 기록된바, 철도의 이름이 너희로 말미암아 일반인들 가운데서 모독을 받는도다, 함과 같으니라." 꼴이 됐다.

Posted by 사무엘

2014/07/13 19:37 2014/07/13 19:37
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/984

<날개셋> 한글 입력기는 도대체 왜 만들어도 만들어도 또 만들 게 끝도 없는 걸까? 미치겠다. ㅠ.ㅠ 이거 좀 진지한 고민거리이다. 누가 이 마약 같은 코딩의 노예계약으로부터 나를 좀 해방시켜 줄꼬.

난 기술을 매우 긍정적으로 보지만, 한편으로 IT 쪽은.. 이제 어지간히 만들어질 거, 나올 건 다 나오고 한계에 도달하지 않았나 하는 회의감도 어느 정도 갖고 있다. Windows도 그렇고 Office도 그렇고.. 소프트웨어 업그레이드의 여파가 이제 예전만 하지 않다.

그러나 <날개셋> 한글 입력기에 관한 한은 상황이 다르다. 여전히 만들어 질 거, 나올 것들이 다 완성된 상태가 아니다. 이건 긍정적인 상태라고 해석해도 될 것 같다.
이 글에서는 <날개셋> 한글 입력기 7.4에 대해서 미처 제대로 공지가 안 되었던 변화 사항과 다음 버전 개발 근황 등을 전하도록 하겠다.

※ 7.4 버전의 잠수함 패치 내역

1.  고급 입력기의 사용자 정의 조합은 이제 언제나 '일반 문자' 타입의 날개셋문자만을 인식한다. 한글 타입(두벌식, 세벌식 등)의 날개셋문자를 0x11??대의 글쇠로 자동으로 인식하는 기능은 없어졌다.
이것은 동작 방식의 간결화를 위해 취해진 조치이다. 한글 자모나 글자를 이용하여 사용자 정의 조합을 만드는 것은 7.4의 고급 입력기에서 추가된 '한글 출력 치환' 기능으로 구현해도 된다. 더 전문적인 대체 기능이 생겼다.

2. 기본 입력기의 글쇠배열 수식에서 이제는 A와 C 변수가 제공되지 않는다. 이것은 사실 디자인상의 실수에 가까운 잉여일 뿐이었다.
글쇠가 눌러질 때 Alt 키가 눌러져 있으면 A에, Ctrl 키가 눌러져 있으면 C에 nonzero 값이 들어왔다. 그러나 7.4부터는 기본 입력 스키마의 기본 94개 글쇠는 언제나 Alt, Ctrl이 눌러져 있지 않을 때만 동작하게 동작이 바뀌었으며 해당 변수는 제공하지 않는다. Alt/Ctrl까지 동원해야 하는 복잡한 글쇠 조합은 고급 입력 스키마로 구현하면 되고, 또 기본 입력 스키마에도 그런 사용자 정의 글쇠 배당 기능이 6.5 버전에서부터 따로 추가되었으므로 이를 활용하면 된다.

지난 7.4 버전은 긴 시간 동안 한글 입력 관련 기존 코드들을 싹 정리하면서 각 개체와 계층들의 역할을 재정리하고 프로토콜도 다시 설계했다. 즉, 리팩터링의 비중이 컸다. 그러면서 이런 미세한 기능들은 좀 예고 없이 변경해도 여파가 별로 없겠다 싶은 것들을 과감하게 뜯어고쳤다. 그랬는데 본인은 <날개셋> 한글 입력기 헤비 유저들의 창의성을 너무 얕잡아 봤던 듯하다.

7.4의 공개 직후에, 잠수함 패치 때문에 예전에 되던 기능이 갑자기 안 되어서 불편을 겪으신 분께 사과드리며, 앞으로는 이런 변화는 충분히 예고를 드리도록 노력하겠다.
특히 고급 입력 스키마의 새 기능을 적극 사용하면서 여러 질문과 버그 신고를 해 주신 김 기윤 님께 감사드린다.

※ 다음 버전 개발 근황

7.4는 큰 버그 없이 잘 만들어진 듯하다. 딱 이 정도 만들어졌을 때 커트를 하여 새 버전을 내놓은 것도 매우 적절했다.
새로 추가된 고급 입력 스키마에서 이것저것 미흡한 점과 개선할 점들이 보이지만 그건 시간과 여유의 부족으로 인해 애초에 고려를 못 했던 부분들이다. 새 기능으로 인해 기존 기능에서 예기치 못한 오동작이 발생한다거나 프로그램의 안정성과 관련된 치명적인 버그가 생긴 것은 없다.

7.4의 다음 버전은 7.5로 계획하고 있다. 7.4를 마무리 지으면서 나머지 잔여 기능들은 하반기에 나올 다음 버전을 기약하기로 그때부터 이미 결정을 해 놨다.
다음 버전의 개발 방향은 (1) 7.4에서 미처 못 끝낸 입력 엔진 리팩터링과 개선, (2) 고급 입력 스키마의 기능 마저 구현, (3) 기타..로 나뉜다. 다만, 이것저것 넣고 싶은 기능들을 다 구현한다면 변화량이 7.5 수준을 초과할지도 모른다.

(1) 고급 입력기의 기능을 활용하고 나면, 두 글자 이상 길이의 조합을 만드는 게 가능해진다. 그러나 조합 중에 C0|0xD (앞쪽으로 조합 중단) 같은 특수글쇠를 집어넣어 보면, 현재는 정확하게 조합의 앞에 cursor가 놓이는 게 아니라 조합의 뒤에서 한 글자 앞에 cursor가 놓이게 된다. 기본 입력기의 기능만 활용해서 한글 한 글자만 조합 중일 때에야 이런 동작 방식이 문제가 없지만, 범용성 면에서 이런 동작 방식은 문제가 있다.

이렇게밖에 할 수 없는 것은 내부적으로 여러 한계가 있기 때문인데, 이 한계를 극복하는 작업을 7.4에서 완전히 마무리 짓지 못했다. 그래서 다음 버전에서는 이를 지체없이 이어서 진행할 예정이다.

또한, 한글로부터 입력 순서를 찾아내는 알고리즘, 인접한 두 한글의 연속 입력 가능 여부를 판별하는 알고리즘을 처음부터 깔끔하게 다시 작성할 예정이다. 지금 작성된 코드는 긴 세월이 흐르면서 나중에 추가된 특수 도깨비불 규칙, 종성 지향 두벌식, 오토마타의 O 변수 같은 복잡한 기능들을 정확하게 반영하여 처리하지 못하며 구조적으로 확장하기도 어려운 형태이다.

주어진 입력 설정으로부터 최적의 한글 입력 sequence를 찾는 알고리즘은 한글 입력기가 제공할 수 있는 가장 유용하고 멋진 자동화 기능이므로 올여름에 심혈을 기울여 재개발을 할 것이다.
뭐, 이것 말고도 지금 모든 내역을 밝힐 수 없는 다른 리팩터링 작업들도 남아 있음.

(2) 고급 입력 스키마에 아직 숙제로 남은 여러 미흡한 기능들을 개선하고, 본격적으로 한글 동시치기와 관련된 추가 옵션들을 구현할 예정이다. 세벌식 자판도 직전 한두 타를 아주 빠르게 누른다거나 하면 조합 중이던 자모가 다음 글자로 넘어가는 '도깨비불' 현상이 발생할 수 있게 된다.

(3) 이것도 모든 내역을 당장 밝힐 수는 없는 여러 이슈들이 현재 존재한다. 아, 입력 패드와 관련된 내용을 잠시 후에 언급하도록 하겠다.

한편, 타자연습은 다른 특이점은 없고 새 연습글들을 허겁지겁 추가하다 보니 오타가 생각보다 많이 발견되어 이걸 고쳤다. 버전 번호를 바꾸지는 않을 것이고, 입력기 새 버전이 나오는 날에 타자연습을 동일 버전으로 다시 배포할 생각이다. 그렇기 때문에 기존 3.4 사용자라면 지금 쓰는 타자연습을 제거한 후, 새 3.4를 받아서 다시 설치해서 사용하시면 될 듯하다. 연습글의 오타 신고는 지금까지 박 철현 님께서 가장 열성적으로 해 주셨다.

※ 입력 패드의 버그 수정

<날개셋> 한글 입력기의 구현체들 중 입력 패드는 7.11에서 7.4로 넘어가는 그 격변기에도 큰 변화가 없었으며, 얘는 앞으로 거의 건드릴 일이 없을 거라 여겨졌다.
그러나 다음 7.5 버전에서는 이 프로그램과 내부 hook DLL이 정말 오랜만에 좀 고쳐질 예정이다.

예전에 외부 모듈은 Excel이나 Paint.NET 같은 프로그램에서 한글을 처음 입력할 때 첫 타 조합이 끊어지거나 덧나는 등 자잘한 문제가 있었다. 엄밀히 말하면 내 프로그램의 로직에 문제가 있긴 하지만, 그 프로그램들이 또 좀 특이하게 동작을 해서... 서로 조심을 안 해서 발생하는 문제였다.

그래서 외부 모듈은 한동안 특정 프로그램에서만 인위적으로 다르게 동작하는 예외 로직을 넣어서 문제를 피해 갔었으나, 지난 7.4에서는 오랜 연구 끝에 그 문제를 드디어 완벽하게 해결했다.
그러나 그 방법이 외부 모듈 말고 입력 패드에는 적용되지 않아 있었다. 여전히 Excel에만 예외 로직이 적용되어 있었으며, Paint.NET 같은 다른 프로그램에서는 글자가 덧나는 문제가 남아 있었다. 단지 입력 패드는 편집기나 외부 모듈보다 훨씬 덜 쓰이는 잉여 프로그램이기 때문에 문제의 심각성이 덜 부각되었을 뿐이다.

그러다가 이번에 입력 패드에까지 새로운 해결책을 적용하여 그 문제를 해결했다.
원래 입력 패드는 hooking을 이용하여 변칙적인 꼼수를 부리며 동작하는 위험한 프로그램이기 때문에 이 문제는 외부 모듈만치 깔끔하게 해결하기가 어려웠다. 이 문제를 해결하느라 다른 부작용(side effect)이 생기지는 않았는지를 아주 꼼꼼하게 테스트해야 했으며 이 과정이 대단히 힘들었다.

또한, '한손 입력기'처럼 내부적으로 독자적인 문자 생성기를 가진 도구를 사용했다가 닫은 뒤에 '화면 키보드' 같은 다른 도구로 문자 입력을 시도했을 때 프로그램이 죽는 문제를 해결했다. 늘 나타나는 현상이 아니어서 그저 그러려니 싶었는데.. 확실하게 코딩 실수가 있는 걸 발견했다. 이 두 가지 버그가 현재 해결되었다.

system hook 프로그래밍을 해 본 분들은 아시겠지만, hook을 사용하는 프로그램이 hook을 해제하고 종료한 뒤에도 어찌 된 일인지 그 hook DLL은 오랫동안 메모리에서 완전히 제거되지 않고 남아 있는 경우가 많다. 그래서 그 hook DLL의 소스를 고쳐서 다시 빌드를 하려 해도 덮어쓰기가 안 되고 진행이 안 되는 경우가 많다.

자잘하게 코드 한두 군데만 고친 뒤 결과를 확인하려고 하는데 매번 운영체제 로그인을 다시 해서 상태를 초기화해야 하니, hook 개발은 IME 개발보다도 더 불편한 애로사항이 있었다. IME는 그래도 프로그램만 확실히 종료하고 나면 업데이트가 안 되는 불편은 없기 때문에 말이다. 예전에 XP/Vista 시절에는 명령 프롬프트 디버깅을 한 뒤에는 conime.exe를 매번 죽여 줘야 해서 불편했지만, 그건 7부터는 개선됐다.

아무튼 본인으로서는 문제를 최대한 해결하여, 지금 동작이 예전의 문제를 해결하면 해결해서 더 낫게 만들면 만들었지, 최소한 예전보다 상태를 더 '나쁘게' 만든 것은 없음을 확인했다. 말은 이렇게 했는데 또 버그가 발견되면 그러면 할 말이 없긴 하지만...

여담인데, Internet Explorer의 웹페이지 내부에 있는 폼에다가 입력 패드로 문자를 입력해 보면,
IE 10까지는 조합이 일반적인 IME로 한글을 입력할 때와 마찬가지로 본문에다 네모 사각형 모양으로 제대로 생긴다. 그러나 유독 IE 11부터는 조합이 그렇게 처리가 안 되고 마치 IME-aware하지 않은 프로그램처럼 프로그램 밖의 조합 창에 따로 생기는 형태로.. 시각적인 피드백이 좀 불편해졌다. 어째 이런 것에도 미세한 변화가 생겼다.

※ 기타 공지

1. 다음 버전에서는 문자 생성기를 가리키는 명칭에 날개셋이라는 단어가 빠지고, 입력 스키마의 명칭과 마찬가지로 그냥 빈 / 기본 / 고급이라는 3단계 수식어만 붙을 예정이다. '빈 입력기, 기본 입력기, 고급 입력기'.
날개셋이라는 이름이 왜 지금까지 있었느냐 하면, 오토마타라든가 각종 특수글쇠처럼 <날개셋> 한글 입력기의 가장 중요한 핵심 기능들이 구현된 계층이 문자 생성기이기 때문이다. 쉽게 말해 상징적인 의미 때문이다. 하지만 그건 군더더기라 여겨져서 다음 버전부터는 빼게 되었다.

2. <날개셋> 한글 입력기가 버전을 매기는 방식은 통상적인 소수점과 완전히 동일하다. 가령, 버전 7.4와 7.40은 동일한 표기이며 7.4는 7.11보다 더 높은 버전이다. 다만, 공식적으로는 끝의 0은 생략하여 7.40 대신 7.4라고 표기하는 것을 권장· 선호한다.

3. 그리고 이것도 한 번쯤 언급할 필요가 있어서 입장을 확실히 밝히고자 한다. <날개셋> 한글 입력기는 브랜드 이름을 지금까지 less than과 greater than 부호로 감싸는 이상한(?) 관행이 존재해 왔다. 이것은 세벌식 최종 글자판이 ()와 <>를 아랫글쇠로 입력할 수 있다는 것에 착안하여 별 생각 없이 붙이게 됐는데..
반드시 강요는 안 한다. 파일 이름이나 HTML 태그 같은 상황에서 <>를 붙이기가 대략 난감할 때는 얼마든지 생략해도 된다. 영문 표기에서도 당연히 생략.
하지만 한글로 full name을 공식 표기할 때는 <>를 넣는 것을 원칙으로 삼고자 한다. ㅎㅎ 여기에도 이런 내력이 있는 셈이다.

4. 진짜 마지막으로... 간단한 내용이지만 최근에 문의를 한 분이 있어서 또 공지하도록 하겠다.
입력기와 타자연습을 모두 사용하시는 분이라면, 두 프로그램을 모두 최신 버전으로 업데이트할 것을 강력하게 권한다.

타자연습도 실행에 필요한 최소한의 파일들은 자체적으로 모두 갖추고 있으며 입력기와 독립적으로 동작하는 게 가능은 하다. 그러나 입력기와 타자연습이 서로 API 호환이 되지 않으면 타자연습은 입력기의 모든 기능을 100% 활용할 수가 없게 된다. 특히 플러그 인을 사용할 수 없게 되기 때문에 고급 입력 스키마나 고급 입력기 같은 기능을 사용한 입력 설정이 무용지물이 된다. 반드시 업데이트를 해야 한다.
이번에 타자연습은 3.31 이후 거의 1년 반 가까이 버전업이 없다가 3.4로 업데이트됐기 때문에 문의가 들어올 만도 했던 것 같다.

Posted by 사무엘

2014/07/10 19:32 2014/07/10 19:32
Response
No Trackback , 5 Comments
RSS :
http://moogi.new21.org/tc/rss/response/983

노트북 PC에서 가장 흔하게 발생하는 잔고장의 양대 산맥은 (1) 액정 화면 접촉불량과 (2) 키캡 빠짐이라 해도 과언이 아닐 것이다.

본인이 개인용 노트북 PC를 사용한 지가 15년이 넘었고 지금 쓰는 맥북은 제 5대 컴퓨터인데,
예전에 쓰던 노트북들은 쓴 지 1년 남짓 되면 저런 잔고장이 어김없이 발생하곤 했다.
물론, 언제나 새 노트북만 쓴 게 아니라 중고나 준중고를 쓴 것도 있기 때문에, 품질이 원래부터 안 좋아서 그랬던 것일 수도 있다.

(1)은 화면을 편 각도에 따라서 붉은 세로줄이 나타났다가 사라진다거나, 화면이 아예 꺼진다거나 하는 등 굉장히 성가신 증상이다. 이것 때문에 서비스센터 들러서 수리 받느라 신경 쓰이고 시간· 돈이 낭비되는 것도 과거엔 상당한 수준이었다.

(2)도 노트북 키보드가 데스크톱 PC 키보드보다 약해서 발생하는 고질적인 문제인 듯.
자주 누르는 편인 화살표, 엔터, space, shift 같은 게 잘 빠졌으며 가끔은 문자 키가 빠지기도 했다. 키캡이 없어도 해당 키를 누르는 것 자체는 가능하지만, 빠른 타자와 원활한 컴퓨터 사용에는 애로사항이 꽃핀다.
빠진 키캡 한두 곳만 수리가 되지는 않는 경우가 많다. 그래서 키캡이 대여섯 개쯤 빠질 때까지 컴을 더 쓰다가, 나중에 한꺼번에 키보드 기판을 교체하곤 했던 것 같다. 돈 몇만 원 정도는 깨진다.

그런데.. 지금 쓰는 맥북은.. 쓴 지 2년이 넘었지만. 위의 잔고장이 지금까지 전혀 발생한 적이 없다. 엔터 키가 약~간 달랑달랑거리긴 하지만 그래도 키캡이 완전히 빠진 건 없다. 잡느님의 손길이 담긴 품질 덕분인 걸까? 놀랍다.
맥북은 한번 병원 치료를 받으면 일반 놋붉에 비해 수리비가 작살나게 깨진다는 게 겁나긴 했었지만, 아직까지 A/S를 받을 일 자체가 전혀 없었다.
(참고로 난.. 흔들리는 교통수단 안에서도 쓰고 몇 번 떨어뜨린 적도 있고, 노트북 PC를 시도 때도 없이 험악하게 혹시시키며 쓰는 편이다.)

따라서 애플케어를 구입 안 한 게 현재로서는 결과적으로 이익이었다.
난 비록 맥북으로도 95% 이상의 시간은 맥OS가 아닌 Windows만 쓰며 지내지만 맥북의 이런 품질은 만족스러우며 인정할 만하다.

다만, 세월 때문인지 배터리 용량은 예전보다 확실히 줄어들었다. 2시간 남짓이면 간당간당하다. 배터리는 아직 구경도 못 해 봤다.
그리고 얼마 전엔 맥북을 쓴 지 2년 3개월 만에 처음으로 기능 고장을 경험했다. 본체나 LCD 쪽은 아니고, 전원 어댑터가 문제가 발생했다.

여기저기서 전선의 피복이 슬슬 벗겨지면서 속의 금속선들이 드러나 보이기 시작했다. 벗겨진 부분에다가는 테이프를 감았으며, 노출 부위 때문에 감전이나 화재 사고가 날까 두려워서 잘 때나 부재 중일 때는 전원 플러그를 빼 두기 시작했다.
그러더니 나중엔 컴퓨터 본체와 연결하는 목덜미 부분이 너무 너덜너덜해진 나머지 거의 두 동강 나다시피하면서 결국 단선됐다. 전원을 연결해도 본체에 전원 공급이 되지 않기 시작했다. 컴퓨터 본체는 이제 2시간짜리 시한부 인생으로 전락했다.

어댑터 전선에 피복이 벗겨지면서 고장이 이런 식으로 발생하는 노트북 컴은 맥북이 처음이다. 그런데 다른 맥북/아이폰 사용자에게 물어 보니, 애플 제품은 그런 식으로 전원 어댑터 내지 충전기가 망가지는 건 생각보다 흔한 일이라고 한다.

어댑터 자체는 이상이 없고 전선만 망가진 건데 어째 물건을 재활용할 수는 없나 궁금하다. 물론, 콘센트 쪽 전선이 아니라 컴퓨터에다 꽂는 쪽의 전선이다 보니 어댑터와 분리가 가능하지도 않고 가능하지는 않을 것 같다.

지금은 어댑터를 새로 구입해서 상황을 마무리 지었지만, 약 3~4일 동안 내 컴을 못 쓰면서 좀 불편하게 시간을 보냈다. 다음부터는 좀 불편하더라도 컴퓨터 본체와 어댑터 선이 언제나 같은 높이와 평행한 각도가 유지되게 해 놓고 써야겠다. 목덜미 부근엔 수축 튜브를 감아 주고, 전선을 둘둘 감아서 가방에 넣는 것도 굉장히 조심해서 해야 할 것 같다.

* 다음은 여담.

1. 맥 OS가 의외로 굉장히 유용한 경우가 있는 걸 본인이 얘기한 적이 있나 모르겠다. 바로 학교 안에서이다.
Windows의 경우 컴퓨터의 속도를 한 반쯤 깎아내리는 엄청난 백신, 보안 솔루션 등을 강제로 설치해야만 교내 무선 인터넷 이용이 가능한 반면, 맥 OS는 그런 것 전혀 없이도 바로 인터넷 이용이 가능하기 때문이다. 아주 편리하고 좋다.

2. Windows 진영에서는 Metro라는 이름을 안 쓰는 게 마음에 안 들던데, 애플 진영에서는 매킨토시로도 모자라서 Mac이라는 이름까지 왜 빼 버렸나 궁금하다.. 자기 정체성을 가장 잘 분명하게 보여 주는 명칭을 빼 버리고 그냥 OS X...;;;

3. 그러고 보니, 플래시가 깔려 있지 않은 맥 OS의 사파리 브라우저에서 유튜브 동영상이 나오고 있어서 깜짝 놀라서 살펴봤더니.. 말로만 듣던 HTML5 기반 동영상이다. 우와~ 물론 비스타+IE9 구닥다리에서 실행해 보니 여전히 플래시다. 브라우저에 따라 기술을 알아서 판별하는 듯하다.

솔직히 플래시든 뭐든 인터넷으로부터 패킷을 받아서 하드웨어 가속으로 동영상을 틀어 준다는 기본 원리는 똑같다. 단지, 동영상을 해독하고 재생하는 기계어 코드가 예전에는 플래시 ActiveX라는 일종의 private한 영역에 있었던 반면, 이제는 그게 통일된 규격으로 웹브라우저에 있다는 차이만이 존재할 뿐이다. 웹 표준은 기술 자체가 아니라 기술을 담는 그릇의 규격에 대한 논쟁인 것이다.

Posted by 사무엘

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

근황 + 컴퓨터 음악 이야기

올해 상반기는 박사 첫 학기 진학과 <날개셋> 한글 입력기 7.4 완성이라는 본인의 개인사와는 대조적으로, 분위기가 은근히 우울했다.
월드컵 축구 경기는 기대를 저버리는 졸전 끝에 별 재미를 못 봤고, 신촌 동성애 퍼레이드에다 어째 1993년에 벌어진 것과 비슷한 패턴의 사건· 사고가 두 건이나 벌어졌다. 세월호(1993년의 서해 페리호), 그리고 총기 난사+무장 탈영(1993년의 임 채성 무장 탈영 인질극) 말이다. 정치판에서 돌아가는 큼직한 사건들은 좌파와 우파 성향 모두에게 최악의 실망만을 안겼다.

뭐 어쨌거나.. 이번 학기에 본인은 아직 프로그램 개발에 더 전념하려고 수업은 2개만 들었다. 언어학 문법 수업은 배경 지식이 부족하다 보니 확실히 어려웠다. 그래도 다음 학기에 프로그래밍 언어와 관련된 수업을 들으면서 경험을 서로 대조해 보면, 자연어와 인공 프로그래밍 언어가 개념적으로 어떤 관계가 있는지를 조명할 수 있을 것 같다.

다음으로 학기 초부터 기대했던 컴음악은 어려운 한편으로 재미있었다.
다른 학생들이 텀 프로젝트를 발표한 걸 보니 모바일 또는 웹으로 간단한 미디 음악 시퀀서를 만든 경우도 있고, 미디 데이터를 일정 규칙대로 변조하거나 climax를 찾는 알고리즘을 연구하기도 했다.
그 담당 교수님의 연구실에 들어가 있는 학생들은 여러 이미지와 여러 음악들을 분위기에 맞는 것끼리 서로 짝지어 주는 솔루션을 주로 내놓았다.

나도 처음에는 멜로디로부터 chord를 자동으로 매긴다거나 다른 감정 같은 의미를 읽어 내는 프로그램을 생각하고 있었으나.. 곧 단념했다. 그런 것도 없는 곡을 새로 만드는 것만큼이나 엄청 어렵고 창의적인 일이라는 걸 곧 인지했기 때문이다.

결국, 컴음악 시간에는 이 기회를 이용해 죽이 되건 밥이 되건 자동 작곡을 하는 프로그램을 만드는 걸로 방향을 선회했다. 복잡한 요소들 싹 다 제끼고 오로지 초등학교 음악책에 나오는 동요 급의 간단하고 짤막한 단음 멜로디를 생성하는 것.

음악이라는 게 어느 정도는 무질서하고 무작위한 요소가 있지만, 그 뒤부터는 정말 인간의 언어만큼이나 극도로 예전 문맥에 의존적이고 체계와 질서가 있어야 한다. 그게 없이 그저 rand()의 결과대로 멜로디와 박자를 뿌리면 그건 음악이 되지 않고 아무 호소력이나 메시지, 시너지 효과가 안 나오는 횡설수설 노이즈밖에 만들어지지 않는다.

연구하면 할수록 음악도 마치 문장을 구문 분석하듯이 계층이 존재한다는 걸 알 수 있었다. 각 마디 안의 음표들은 일정 chord 범위에 드는 한도에서 생성되는데, 그 chord가 바뀌는 규칙은 또 다른 상위 계층에 따라 정해지고, 그 계층의 상위 계층은 또??

맨 처음엔 박자를 재귀적으로 무작위 생성하는 것부터 해 봤다. 음색이 들어간 음악이 말 그대로 색, 컬러 그림이라면, 박자는.. 그냥 흑백 그림에 가깝다고 하겠다. 박자도 생각보다 가짓수가 많았으며, 취사선택을 잘 해야 했다.

2 1 1 2 1 1
8
3 1 4
4 2 2
3 1 4
8
2 1 1 2 2
6 2
4 2 2
3 1 2 2
2 2 3 1
8
2 2 2 2
3 1 2 1 1
6 2
3 1 4
8
4 2 1 1
4 2 2
6 2
1 1 1 1 2 2
1 1 1 1 4

아주 공교롭게도, 마지막 두 박자는.. 바로 “노래 시작했다 노래 끝났다 / 그런 노래 없다 다시 불러라”의 박자와 동일하다.. ㅋㅋㅋㅋ 컴퓨터가 그런 박자도 만들어 냈다. 하지만 박자에다가 음색을 입히는 건 훨씬 더 어려운 일이었다.

처음엔 1도 화음에서 시작하고 끝은 언제나 '도'로 끝나고, 주어진 chord와 어긋나는 음은 약박에만 들어가게 하고,
같은 음 반복, 1도씩 증가, 1도씩 감소 같은 인위적인 규칙을 일정 확률로 준 결과, 노이즈보다는 듣기 좋은 멜로디가 종종 생성되었다. 아 물론, Looking for you나 Let it go 같은 퀄리티를 기대해서는 안 되지만..ㅎㅎ

텀 프로젝트를 발표한 후 교수님의 반응은 “(1) 마디별 코드 전환이 부드럽고 꽤 그럴싸하게 작곡이 잘 됐다. (2) 단, 당초 계획만치 참고문헌 내용이나 관련 기존 연구 성과가 반영되지 못한 것은 아쉬움”이었다.

내가 목표했던 퀄리티는 그냥 별 생각 없이 콧노래를 흥얼거리는 수준의 작곡이었다. 그런데 사람은 무작위로 흥얼거린다 해도 결국 예전에 자기가 들어서 기억하고 있는 음악을 변형하는 형태인 반면, 컴퓨터는 그런 경험 데이터가 없이 난수 생성만으로 음악을 만든다. 결국 컴퓨터도 사람에게 듣기 좋은 음악을 만들려면 모방이 필요하며 기존 음악 패턴에 대한 데이터가 아주 없어서는 안 될 것 같다.

이래저래 음악은 탁월한 수리 능력에다가 창의성까지 갖춘 괴수 천재들을 매혹시키기 충분한 분야이다. 리서치 과정에서 Musimathics라는 책을 참고했는데, 저자는 이건 뭐 수학, 전산학에 소리를 물리· 전자공학적으로 분석하는 것까지 완전 다 통달한 천재다. 전자공학의 푸리에 변환도 나오고, 작곡 방법론에서 난수 생성 얘기를 하는 데서는 ACM 논문까지 소개한다.

나 또한 딴 건 몰라도 음악의 위력에 대해서는 Looking for you와 관련하여 할 말이 무진장 많다. 이런 음악 한 곡도 지적 설계자의 치밀한 설계 없이는 만들어질 수 없는데 하물며 이 세상 만물이겠는가 하는 생각도 응당 들었다.

사실, 과거에 마소에서는 미래엔 이렇게 실시간으로 작· 편곡을 하여 분위기에 맞는 음악을 만들어 내는 게임이 등장할 걸로 예상하고 DirectX에다가 미디 기반의 DirectMusic이라는 컴포넌트도 만들었다. 1990년대 말이면 아직 소프트웨어 기반 미디 신시사이저도 흔치 않던 시절이어서.. 하지만 게임 음악 기술은 음표 신호 방식이 아닌 waveform 방식으로 대세가 완전히 바뀌었으며, DirectMusic도 개발이 중단된 흑역사로 전락했다. 아쉽다면 아쉬운 점이다.

다음은 여담이다.

1.
어떤 학생이 자기 결과물을 발표하고 시연하는 중이었는데, 파일을 기록했다는 영문 메시지가 writed라고 뜨고 있었다. 본인은 그걸 보면서 속으로 뿜었다. 우와, 정말 생각도 못 했던 단어다.
그런데 집에 돌아와서 내가 발표했던 PPT 자료를 다시 보니, 나도 ‘결론’을 Conclusition이라고 써 놔 있었다. ㅋㅋㅋㅋㅋ

다들 시간에 쫓기는 상태로, 혹은 밤샘 하고 나서 머리 가동률이 70% 이하로 떨어진 상태로 비몽사몽 발로 영작을 하다 보니 저런 오타들이 나왔는가 보다.

2.
본인은 작곡한 멜로디를 출력할 때 미디 API를 쓴 게 아니라, 과거 BASIC에 존재하던 PLAY문과 비슷한 기능을 하는 함수를 직접 만들어서 썼다. 지정된 음의 주파수에 해당하는 sine wave를 생성해서 오디오로 출력하는 것이다. 난생 처음으로 waveOut*** 어쩌구 하는 함수들을 직접 공부해서 써 봤다.

난 간단한 콘솔 프로그램을 만드는 게 목적이기 때문에 파일 재생 관련 통지를 그냥 callback 함수 호출로 받게 했는데... 뭐가 이상하게 꼬이면서 잘 되질 않았다.
한참을 디버깅 하다가 시간도 부족하고 설마 하는 심정으로 message-only 윈도우를 만들고 통지를 메시지로 받게 했더니.. 모든 문제가 싹 해결되었다. 메시지가 진리. 두 메커니즘의 차이가 뭔지는 잘 모르겠다.

그래픽 애니메이션 출력 때 더블 버퍼링을 하는 것만큼이나, 실시간으로 오디오 데이터를 보내는 것도 더블 버퍼링 기법이 쓰인다는 게 흥미롭다. 관련 코딩을 해 보신 분이라면 이미 잘 아실 것이다.
버퍼 A의 내용이 사운드 카드로 가서 재생되는 동안 미리 버퍼 B의 내용을 보내 놓고 기다리고, 다음으로 버퍼 B가 처리되었으면 다시 버퍼 A에다가 다음 내용을 보내는 것이다.

Posted by 사무엘

2014/07/05 08:36 2014/07/05 08:36
, ,
Response
No Trackback , 4 Comments
RSS :
http://moogi.new21.org/tc/rss/response/981

« Previous : 1 : ... 131 : 132 : 133 : 134 : 135 : 136 : 137 : 138 : 139 : ... 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:
3064932
Today:
243
Yesterday:
3190