« Previous : 1 : ... 7 : 8 : 9 : 10 : 11 : 12 : 13 : Next »

도움말의 역사

오늘날 PC의 GUI 환경에서 돌아가는 거의 모든 프로그램들은 F1을 누르면 도움말이 나온다.

윈도우는 운영체제 차원에서 표준 도움말 규격이 있는 것으로 예로부터 유명했다. 아예 운영체제의 API에 WinHelp 같은 함수가 정식으로 등재되어 있다. -_-
맥 OS는 모르겠고, 리눅스는 그런 시스템이 없다고 들었다(쉘부터가 GNOME이 뭔지 KDE가 뭔지 사실 아직도 알쏭달쏭... ㄲㄲ).

그 원조는 바로 WinHelp와 그 기반의 HLP 도움말 파일이다. 20년 전의 윈도우 3.0때 처음으로 도입된 이 기능은 나름 굉장히 유용했다. 다양한 서식을 적용한 텍스트 + 이미지 + 하이퍼링크 + 팝업창은 일종의 인터넷 WWW와도 비슷한 수준의 인터페이스였다. WinHelp는 의외로 기능이 다양해서 도움말에다 색인도 넣고, 도움말 창의 버튼도 customize 가능했다.

당시 WinHelp를 설계한 엔지니어가 누군지는 모르겠지만, 도움말이라는 간단한 주제 하나만으로 굉장한 대작을 만들어 냈다. 윈도우 3.1 때 도움말 시스템이 소폭 업그레이드되긴 했으나, 아직까지는 대동소이하고 하위 호환성 정도는 유지되었던 걸로 본인은 기억한다.

도움말은 기본적으로 오늘날 워드패드가 사용하는 RTF(서식 있는 텍스트) 기반이었다. 문서 파일에다가 각종 도움말 메타정보를 WinHelp 스펙대로 넣어 준 후, 이들 파일과 그림들을 Help Compiler로 컴파일하고 압축하면 HLP 파일이 생성되었다. 하지만 이건 대단히 번거롭고 까다로운 일이었기 때문에, 그 절차를 간소화해 주는 위지윅 도움말 저작 도구도 응당 개발되어 나오곤 했다.
16비트 윈도우용 SDK를 보면 도움말 컴파일러가 HC30 (윈 3.0 공용), HC31 (윈 3.1 전용)이 따로 있었다.

이 WinHelp는 윈도우 95에서는 4.0으로 버전이 올라가고 기능이 훨씬 더 강화되었다. 계층 구조의 목차가 따로 추가되어서(*.CNT) 도움말의 첫 화면에다 번거롭게 목차를 본문 형태로 넣을 필요가 없어졌으며, What's this?라는 풍선 도움말이 추가되었다. 창도 더욱 아담해지고 응용 프로그램과 통신만 잘 주고받으면 거의 CBT 수준의 인터렉티브한 도움말을 만들 수도 있게 됐다.

윈도우 3.x 시절에는 매 대화상자마다 한쪽 끝에 ‘도움말’ 버튼이 있는 게 유행이었는데 그게 95부터는 다 사라졌다. 그 대신 X 버튼 왼쪽에 [?] 버튼이 생겼다.

그리고 또 여기서 주목할 점은, 도움말 시스템이 16비트(winhelp.exe)와 32비트(winhlp32.exe)로 완전히 분리되었다는 것이다. 왜 그럴까?
윈도우 운영체제의 도움말은 단순히 하이퍼링크가 달린 RTF 문서 뷰어 수준을 훨씬 더 능가하는 방대한 시스템이었기 때문이다.

HLP 파일은 윈도우 API를 호출하는 건 물론이고 WinHelp 규격대로 만들어진 플러그 인 DLL들을 붙여서 도움말 화면을 사실상 마음대로 제어할 수 있었다. 나만의 버튼을 추가하고, 확장 기능을 넣고... DLL이 들어간 이상 16비트와 32비트의 분리는 불가피해진 것이다. 지금 같으면 32비트와 64비트의 분리가 필요하겠지.

얼마나 customize가 가능하냐 하면, HLP 파일에다가 마치 오늘날의 HTML 도움말(CHM)처럼 목차 탭을 도움말 내부에다 보조 윈도우로 집어넣을 수 있었다. 도움말이 WinHelp에다가 아예 없던 기능을 추가할 수 있을 정도였던 것이다.
과거 본인이 즐겨 이용하던 Paint Shop Pro 7은 Robo HelpOffice라는 저작 도구로 만들어진 HLP 도움말을 제공했는데, 정말 기능이 상상을 초월하게 화려했다.

이게 웹으로 치면 ActiveX이다. 도움말 세계의 ActiveX인 셈인 것이다. -_-;;

그랬는데, 윈도우 98 + 인터넷 익스플로러 4가 되면서 새로운 도움말 시스템이 또 등장했다. 서식 있는 텍스트+하이퍼텍스트의 진수는 바로 웹이 아니던가. RTF가 아니라 아예 IE의 엔진을 쓰는 도움말이 생긴 것이다. 이것이 오늘날까지 전해져 오는 HTML 도움말이며, 파일의 확장자는 CHM이다. Compiled HTML.

HTML 도움말은 내부적으로 IE를 쓰는 관계로 과거의 WinHelp보다 훨씬~ 더 덩치 크고 무거웠다.
IE 4를 얹지 않은 옛날 윈도우 95 시절의 탐색기 vs 오늘날 탐색기의 덩치 및 구동 시간은
과거 WinHelp 도움말 vs 오늘날 HTML 도움말의 덩치 및 구동 시간

이건 비슷한 구도이다. -_-;;;
하지만 웹에서 쓰이는 각종 자바스크립트+다이나믹 비주얼 효과를 도움말에서도 그대로 재활용 가능하다는 점을 감안하면, 웹 기술을 도움말에다 활용하겠다는 발상 자체는 훌륭하다고 볼 수 있다. WinHelp 기술은 윈도우 밖에서는 아무 쓸모도 없는 테크닉이지 않은가.

개발자의 입장에서야 RTF보다야 HTML이 훨씬 더 친근하니 예전보다 도움말 만들기가 쉬워진 것도 아주 좋다. 본인도 HLP 도움말은 만들 엄두를 못 냈었는데 CHM 도움말은 나모나 프런트페이지만으로도 비교적 손쉽게 만들 수 있었다.
홈페이지 만드는 데 쓰이는 파일을 그대로 모아서 컴파일만 하면 끝. 그러니 CHM 파일은 웹 문서 아카이브를 만드는 데도 아주 유용했다.

일반 웹에는 존재하지 않지만 도움말에는 필요한 기능이 있다. 가령, 팝업 메뉴를 띄운다거나 외부 프로그램을 실행하는 기능은 소스를 보면 MS가 자체적으로 ActiveX처럼 비표준 확장 태그를 써서 구현해 놓은 걸 볼 수 있다.

CHM 도움말은 장기적으로 기존 HLP 도움말 시스템을 대체할 목적으로 만들어졌기 때문에, HLP로 할 수 있는 일은 CHM으로도 다 할 수 있게 돼 있다. 가령, CHM으로도 풍선 도움말을 구현 자체는 할 수 있다. 하지만 그 쬐그만 풍선 도움말이 웹 페이지 내용이라는 건 영 안 어울린다. 실제로, 비스타부터 풍선 도움말은 윈도우 운영체제 내부에서는 완전히 사라졌다.

윈도우 98부터 XP까지 운영체제의 도움말은 WinHelp와 HTML 도움말이라는 양분된 구도를 유지하고 있었다. 그러다 윈도우 비스타는 과감하게 WinHelp를 없애 버렸다. HLP 도움말을 열면 ‘이 도움말은 옛날 버전으로 만들어져서 이제는 더 지원되지 않습니다’만 뜬다. (단, 16비트용 WinHelp는 남아있음)
원래 마소는 과거 호환성을 극도로 존중해 주는 집단이다. 그런데 왜 이런 조치를 취한 것일까?

오늘날 과거 호환성보다 더 중요한 건 보안이기 때문이다.

HLP와 CHM 모두 단순히 read-only 하이퍼텍스트 문서만 취급하는 게 아니다. 사용자의 컴퓨터에 있는 응용 프로그램을 실행할 수 있고, DLL의 코드를 불러와서 실행할 수 있다. 따라서 잠재적 보안 위험성도 충분하다.

마소는 21세기부터 자사 소프트웨어에 있는 이스터 에그를 모두 없앴으며, 이미 짜 놓은 수많은 코드에 대해서도 대대적인 보안 강화 리팩터링을 시작했다. 비주얼 C++ 2005부터는 잘 알다시피 비표준 오명을 감수하고라도 C 라이브러리까지 뜯어고쳐서 *_s 함수를 도입할 정도였다.

그랬는데 그렇잖아도 구닥다리 WinHelp의 코드를 보니까, 이건 기능도 카오스 그 자체이지, 앞으로 지원도 안 할 건데 리팩터링을 할 필요를 못 느낀 것이다. 그러니 철도 당국이 수익 안 나는 간이역을 폐역하듯이 지원 중단 결정을 내렸다. WinHelp 함수 지못미.

이런 보안 강화 정책으로 인해, 윈도우 비스타부터는 탐색기에 16비트 윈도우 실행 파일들이 아이콘이 그려져 나오지 않는다. 웹페이지의 파비콘을 추출하고 그리는 코드의 허점을 이용해서도 악성 코드를 주입하고 실행할 수 있을 정도이니 말 다 했다. -_-;; 비슷한 이유로, 워드패드에서 과거 wri 파일 포맷을 읽는 기능도 삭제되었다. 구닥다리 코드는 이제 와서 보안을 강화하는 작업을 하기 귀찮으니까 그냥 무시하기. ㄲㄲ

사실은, CHM 파일마저도 이제 MS가 더 적극적으로 개발을 안 하기는 마찬가지이다. 요즘 MS가 만드는 프로그램들은 CHM 안 쓰고 또 자기만의 다른 도움말 시스템을 쓴다. 비록 내용 렌더링이 HTML 기반인 건 동일하지만, CHM은 아니라는 뜻. 그 때문인지는 모르겠지만 HTML 도움말을 보면, 도구상자의 아이콘은 10년 전이나 지금이나 아직까지도 16컬러 그대로이다. ㄲㄲㄲ

아울러, CHM 역시 보안 위협을 많이 받는 관계로, 웹에서 받아서 바로 실행한 녀석은 내용이 표시되어 나오지 않는다. 반드시 로컬 환경에다 저장해서 ‘속성 -> 제한 해제’를 해 줘야 내용을 볼 수 있다.

앞으로 윈도우 운영체제의 도움말 시스템이 어떻게 변모할지는 알 수 없는 노릇이다. 하지만 설마 CHM이 HLP처럼 그렇게 갑작스럽게 호락호락 없어지지는 않을 듯하다.

하긴, 예전엔 아래아한글도 언어(한국어든 영어든)와 플랫폼(3.1/95/NT)을 불문하고 동일하게 표시되는 GUI 엔진을 표방하고서, 도움말조차 자체 포맷을 만들었던 적이 있다. 97까지만 해도 윈도우 3.1 도움말 스타일의 자체 도움말을 썼었는데 워디안/2002 이후부터는 싹 잊혀지고 그냥 CHM을 쓰기 시작했다.
도스용 프로그램 개발할 때 도움말 기능을 구현하던 추억이 아직도 새록새록하다. ^^

※ 잡설: 응용 프로그램의 보안 문제

유명한 국산 압축 프로그램인 빵집의 구버전에서, 악의적으로 일부 내용이 조작된 zip 파일을 열자 엉뚱하게도 내가 지정해 준 프로그램이 실행된다. 프로그램의 보안 취약점을 시연하는 동영상을 보니 신기하기 그지없었다.

프로그램의 소스로는 제각각의 이름으로 구분되는 수많은 변수와 함수의 명칭들이, 빌드 후에는 그저 아무 의미 없는 오프셋 내지 메모리 주소로 바뀐다. 그러니 이런 정교한 숫자가 조금이라도 바뀌면 프로그램은 전혀 다른 동작을 하게 된다. 그런 조작은 입력 파일의 조건 검사를 허술하게 하는 프로그램의 허점을 이용해서 가능하다. 더구나 zip은 프로그램 실행과는 전혀 관계없는 데이터 파일일 뿐인데, 하물며 대놓고 프로그램 실행 기능이 있는 파일은 얼마나 위험하겠는가?

사용자의 입장에서는 각종 보안 업데이트가 귀찮기 그지없다. 하지만 개발자의 입장에서는 보안 업데이트를 안 하면 어떻게 되는지를 너무 자세하게 설명해 줄 수도 없다. 그러니 서로 답답한 노릇이다.

“모방 범죄 예방을 위하여 더욱 정확한 후레쉬 조작법... 이 아니고 더욱 정확한 악성 코드 삽입 방법은 알려드리지 못하는 점 양해 바랍니다.” ㅋㅋㅋㅋ

Posted by 사무엘

2011/05/03 08:14 2011/05/03 08:14
, , , ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/505

※ 비주얼 스튜디오 2003

지금은 바야흐로 2011년. 비주얼 C++ 2010이 나온 지 이미 1년이 지났고 C++0x 규격까지 등장한 마당에, 그 옛날 버전인 비주얼 C++ 닷넷 2003 관련 블로그 포스트를 아직도 적지 않게 찾을 수 있어서 본인은 놀랐고 한편으로 동질감을 느꼈다.
본인도 <날개셋> 타자연습을 비롯해 여러 legacy 프로젝트들을 여전히 VS 2003으로 관리하고 있다.

특히 2005와 그 후대 버전들은 MFC 라이브러리가 너무 심하게 bloat되어서 본인은 업그레이드할 의욕을 대략 상실했다.
static link를 할 엄두를 못 내겠는데, dynamic link 정책도 영 괴상한 방식으로 바뀌니..
MFC 라이브러리보다도 덩치 더 큰 포토샵, MS 오피스급의 초대형 상업용 프로그램을 개발할 때라면 모를까, 이건 소규모 프로그램 개인 개발자에겐 영 아니라는 생각이 든다.

그래도 듣자하니 2010은 msvcr100과 mfc100을 굳이 winsxs 매니페스트 방식을 안 쓰더라도 자기 local 디렉터리에서 로딩 가능하게 바뀌었다고 하던데, 그건 그나마 다행인 점이다. 전세계에서 터져 나온 개발자들의 불만을 비주얼 C++ 팀이 받아들인 모양이다. Class wizard도 부활하는 등, 2010이 꽤 참신한 변화를 많이 했다. 2005->2008은 연도 차이가 3임에도 불구하고, 2일 뿐인 2008->2010보다 변화량이 훨씬 더 적었다.

잡설이 길었는데..
운영체제인 윈도우 비스타는 시스템 계층에서 바뀐 게 많다 보니, 예전의 2000/XP와는 달리 비주얼 스튜디오, 혹은 비주얼 C++에게 그리 자비롭지 않았다. 비스타뿐만이 아니라 7도 마찬가지.

구닥다리 6.0은 그런 최신 OS에서 동작 자체는 한다만, 설치하는 과정에서 무슨 문제가 있을 수 있다고 하고(OLEView 같은 일부 컴포넌트),
2003은 비스타에서 대놓고 좀 잡다한 문제를 일으킨다. 하지만 MS는 VS 2003 지원은 2006년 중반의 SP1을 끝으로 이제 완전히 끊었다. 비스타 이후부터는 버려진 자식. -_-;;

그 잡다한 문제 중 유명한 게 뭐냐 하면, Find in files 기능.
윈도우 비스타/7에서 VS 2003으로 이 명령을 내리고 있으면 IDE가 응답 없이 그대로 멎어 버렸다. 파일 검색 기능을 쓸 수 없다는 소리. 그런데 이건 개발자가 밥먹듯이 써야 하는 기능인데, 이거 없으면 불편해서 프로그램 개발 어떻게 하라고? -_-;;;

이 문제를 해결하는 방법은 의외로 간단하다.
탐색기로 DEVENV.EXE를 찾아가서 Alt+Enter로 속성을 꺼낸 후, 호환성 탭에서 시각 테마를 꺼 버리면 된다. 이 팁을 올린 각종 블로그 포스트에는 한국어와 영어를 불문하고 "너무 좋은 정보군요.", "알려 주셔서 대단히 고맙습니다", "퍼 갑니다" 댓글들이 즐비하다. 아직도 VS 2003 쓰는 개발자가 많다는 뜻 되겠다. X86 아키텍처와 PE 방식 실행 파일이 존재하는 한, C++, Win32 API, 네이티브 코드 자체가 근본적으로 유행을 그렇게 타는 분야가 아니니 말이다.

비주얼 C++ 2003은 MS 오피스 XP와 동일한 GUI 기반이며, 어차피 comctl32 6.0 기반의 시각 테마를 쓰지도 않는 프로그램이다. 그러니 프로그램 외형이 딱히 달라지지도 않는다.
단, 그 비주얼 C++로 실행한(디버거를 붙인 F5든, 붙이지 않은 Ctrl+F5든) 나의 프로그램도 시각 테마가 무시된 채 실행되므로 그건 주의해야겠다. 물론, 탐색기 같은 걸로 따로 실행하면 문제 없음.

덧붙이자면 VS 2003은 도킹 윈도우 같은 걸 드래그하여 이동할 때 점선으로 윤곽이 나타나는데, 이 역시 알다시피 Aero 하에서는 동작이 굉장히 굼뜬다.
이것이 VS 2005부터는 개선되어 파란 도킹 다이아몬드도 생기고 비주얼이 산뜻해졌으나, 어차피 2005조차도 비스타에서 제대로 돌아가지 않긴 마찬가지이다.

SP1에다가 비스타 패치까지 다 복잡하게 설치해야 한다. 문제는 SP1과 비스타 패치 각각이 VS 2005를 처음 설치하는 것만치 시간이 욕 나오도록 오래 걸린다는 것. ㅆㅂ
윈도우 비스타보다 늦게 나온 2008부터가 드디어 비스타에서 별 트러블 없이 잘 돌아가며, 내장하고 있는 플랫폼 SDK도 윈도우 비스타 기준 최신이다.

※ 32비트 프로그램이 64비트 프로그램 디렉터리에 접근하기

잘 알다시피 64비트 윈도우에서도 시스템 디렉터리의 경로는 32비트와 마찬가지로 windows\system32이다. 64가 아니다.
그럼 64비트 윈도우 내부에서 32비트 시스템 파일들이 들어가는 경로는 windows\SysWOW64이다.

그런데 본인은 며칠 전 굉장히 놀랐다.
GetSystemDirectory를 호출하는 코드를 32비트로 빌드하나, 64비트로 빌드하나, 실행 결과는 windows\system32로 동일했기 때문이다. 왜 그럴까?

이는 일종의 가상화 내지 redirection 메카니즘 때문이다.
64비트 윈도우에서 동작하는 32비트 프로그램은 애초에 64비트 윈도우 시스템 디렉터리로 접근을 아예 할 수 없다. system32와 syswow64가 모두 보이긴 하지만, system32 디렉터리를 들여다보면 운영체제가 보내 주는 것은 어차피 syswow64의 정보뿐이다. 그 안에서만 놀아야 한다.

Program Files 디렉터리는 그렇지 않아서 32비트 프로그램이 32비트용 경로와 64비트 경로로 모두 따로 접근이 가능하다. 하지만 어차피 known path를 운영체제 차원에서 얻는 방법이 없다. 64비트 프로그램은 64비트용 경로와 32비트용 경로에 모두 접근 가능하지만 32비트 프로그램은 64비트용 경로를 얻을 수 없다.

이렇게 가상화를 너무 잘 해 주기 때문에, 심지어 64비트 OS에서도 32비트 프로그램은 GetSystemInfo 함수를 호출하더라도 멀쩡한 64비트 x64 컴퓨터를 32비트 x86으로만 인식한다. 이 OS가 진짜 64비트인지 32비트 프로그램도 알려면, GetNativeSystemInfo라는 새로운 함수를 써야 한다.

32비트 윈도우에서 <날개셋> 한글 입력기 64비트 에디션은 당연히 설치가 되지 않지만, 64비트 윈도우에서 32비트 에디션은 설치가 가능하다. 이 경우, 편집기나 변환기 같은 프로그램이야 별 차이 없이 쓰겠지만, 외부 모듈이나 입력 패드는 당연히 64비트 프로그램에서 제대로 쓸 수 없다.

그래서, 64비트 윈도우에서 <날개셋> 32비트 에디션이 설치되었을 때, "에디션을 잘못 고르신 것 같은데, 가능하면 64비트 쓰시져?" 하는 경고 메시지를 띄워 주고 싶다. 그런데, 32비트 프로그램이 자기 주변이 64비트인지 파악하기가 의외로 쉽지 않아서 고민이다. 운영체제가 64비트인 경우, 자신이 64비트 모듈과 병행 설치도 되어 있는지 체크를 해야 하는데 파일 시스템이 워낙 저렇게 샌드박스화해 있으니 말이다. =_=;;

※ TlsGetValue와 에러 코드

파일을 읽어서 주어진 일을 처리하는 함수를 만들었다. 이 함수는 파일을 찾지 못하면 false를 즉시 리턴하며, 그 후 이 함수가 호출한 CreateFile 함수가 남긴 GetLastError 값을 바탕으로, 응용 프로그램은 에러 메시지를 찍는다는 게 본인의 계획이었다.

그런데 이 함수가 선언한 각종 객체의 소멸자 함수가 뭔가 처리를 하면서, 또 GetLastError 값을 바꿔 버리기 때문에 정작 파일 조작이 실패한 이유를 밖에서 알 수가 없게 되는 경우가 있었다.
도대체 어디서 에러 코드가 바뀌지? MSDN을 뒤져보다 본인은 깜짝 놀랄 수밖에 없었다.

일반적으로 윈도우 API 함수들은 동작이 실패했을 때만 에러 코드를 설정한다. 그러나 TLS 값을 되돌리는 TlsGetValue 함수는 성공일 때도 에러 코드를 에러 없음을 의미하는 0으로 설정함으로써, 예전 함수의 에러 코드를 덮어써 버린다. 왜냐하면 리턴값 0만으로는 진짜 TLS 슬롯 값이 0인지, 아니면 실패를 의미하는 0인지 알 수 없기 때문이다.

TlsGetValue 함수는 C/C++에 언어적으로 존재하지 않는 새로운 scope를 만드는 것이나 마찬가지인 함수이기 때문에 밥먹듯이 자주 호출된다. 성능이 매우 중요함에도 불구하고 이 함수는 예외적으로 언제나 에러 코드를 건드리도록 설계되어 있다.

이게 에러 코드인지, 정상적인 리턴값인지 알 수 없는 예로 GetExitCodeThread/Process 함수가 있다.
STILL_ACTIVE라는 값이 리턴되었는데, 이게 해당 스레드나 프로세스가 종료하면서 진짜로 리턴한 값인지, 아니면 그게 아직 종료되지 않은 상태인지.. 알 게 뭐야..;;
개인적으로 함수를 왜 저렇게 설계했는지 모르겠다. 어지간하면 성공/실패 여부를 별도의 인자에다가 따로 되돌리게 하는 게 훨씬 안전할 텐데.

Posted by 사무엘

2011/04/08 17:29 2011/04/08 17:29
, ,
Response
No Trackback , 7 Comments
RSS :
http://moogi.new21.org/tc/rss/response/493

윈도우 프로그래머라면 이미 다 아시겠지만, 비스타에서부터 task dialog라는 아주 참신한 UI 기능이 추가되었다.
구닥다리 MessageBox를 쓰자니 뭐가 많이 부족하고,
그렇다고 해서 겨우 에러 메시지 하나 찍자고 별도의 대화상자를 또 만들자니 너무 번거로운데
task dialog는 가히 사막에 있는 오아시스 같은 존재가 아닐 수 없다.

사용자 삽입 이미지
위의 그림은 바로 task dialog의 뼈대. (출처: MSDN)

이제 당장 운영체제부터가 상당수의 UI를 task dialog으로 구현하고 있고,
메모장부터 워드패드까지 모든 기본 프로그램들의 “문서를 저장하시겠습니까?” 대화상자도 죄다 task dialog로 바뀌었다.
덕분에 Yes / No 일색이던 버튼이 Save / Don't save로 바뀐 걸 알 수 있다. task dialog는 각 버튼들에 들어가는 텍스트를 사용자가 자유롭게 지정 가능하기 때문이다.

Y/N이라고만 하면 이게 무슨 질문에 대한 “예/아니요”인지, 응답에 대한 결과를 사용자가 한 단계 더 추론을 해야 한다.
그러나 대놓고 “저장함/저장 안 함”이라고 표시를 해 주면, 이 선택으로 인해 야기되는 결과를 사용자가 더 직관적으로 알 수 있다. MS는 저런 UI 용어 하나하나까지 세심하게 검토를 해 온 것이다.

이것뿐만이 아니라 또 개인적으로 본인은 task dialog가 유용하다고 가장 먼저 느낀 면모가 뭐냐 하면,

“다음부터 이 확인 질문 안 하기” 부류의 체크 상자를 간단하게 추가할 수 있다는 점이었다. 과거의 MessageBox에서 진짜로 2% 부족한 면모였다.
그래픽 모드나 해상도를 바꾼 뒤에 타이머를 걸어서 “화면이 잘 나타나 보입니까? n초 이내에 응답이 없으면 원래 모드로 되돌립니다”를 구현하는 것도 이 task dialog로는 드디어 가능하다. 예전에는 그런 걸 구현하려면 전용 대화상자를 따로 만들어야 했다.

task dialog에는 인터넷 URL 링크를 넣을 수 있고, 라디오 버튼을 넣어서 사용자의 간단한 선택을 받을 수도 있다. 제목-본문 형태로 텍스트를 깔끔하게 배치할 수 있다는 것도 아주 좋은 점이다.
물론, 워낙 기능이 많기 때문에 사용하기가 다소 까다롭다는 건 어쩔 수 없다. 그래서 이를 간소화하기 위해, 비주얼 C++ 2008의 확장팩 내지 2010부터는 MFC에도 CTaskDialog라는 클래스가 추가되었다. 자료구조 관리는 이 클래스가 다 알아서 해 주기 때문에 사용자는 코드 한 줄로 간단하게 원하는 버튼, 원하는 컴포넌트들을 대화상자에다 추가할 수 있다.

그런데 task dialog로 할 수 있는 일은 단순히 메시지를 찍고 사용자로부터 간단한 피드백을 받는 일에 국한되지 않는다.
progress bar를 넣는 기능이 있고 bar의 상태를 일정 주기로 업데이트까지 가능하기 때문에, 이를 이용하면 진행 상황 표시 대화상자도 간단하게 구현 가능하다.

본인은 task dialog를 제어하는 코드와 스레드 작업 관련 코드를 한데 합쳐서 별도의 클래스를 만들어 이를 개인적으로 매우 즐겨 사용한다. task dialog를 사용하는 형태는 딱 정해져 있으니까 별로 customize를 하지 않고, 작업 상황 표시와 작업 스레드의 customization이 이 클래스의 존재 목표가 되는 셈이다.

task dialog 콜백과 스레드 콜백 함수는 내부의 private static 함수로 숨겨 놓는다. 스레드 콜백 함수는 this 포인터에 대해서 아래의 순수 가상 함수를 호출한다.

virtual UINT Work() = 0; //오버라이드 할 것
volatile int m_nCurPos, m_nPosMax; //현재/전체 진행 상황
volatile bool m_bCancel;

그리고 task dialog 콜백은 당연히.. 주기적으로 m_nCurPos 값을 체크하여 progress bar를 업데이트한다.
사용자가 도중에 취소 버튼을 눌러 버렸다면, m_bCancel 플래그가 설정된다. 작업 스레드는 이 값을 수시로 체크해서 사용자가 중단을 요청했다면 신속히 작업을 중단해야 할 것이다.

일이 언제 끝날지 모르는 작업에 대해서는 게이지가 marquee 형태로 뱅글뱅글 돌기만 하게 만들 수도 있다. 윈도우 부팅할 때처럼 말이다.

다만 한 가지 아쉬운 것은, task dialog는 진행 상황 표시만 전문으로 하는 녀석이 아니다 보니, progress bar를 두 개 표시해 주는 기능은 없다는 점이다.
설치 프로그램이라든가 압축/FTP 유틸리티처럼 파일을 다루는 프로그램들은 현재 처리하고 있는 파일의 진행률과 그리고 전체 작업의 진행률을 한데 표시하고 있으며, 이건 매우 흔한 관행이다. 이건 여전히 내가 직접 대화상자를 만들어야 할 것 같다.

.
.

그나저나 드디어 윈도우 7도 SP1이 정식 출시된 지 한 달쯤 됐다.
콘솔에서 세벌식으로 한글 입력할 때 한글+기호 입력이 제대로 안 되던 버그도 고쳐졌으려나? (난 7 안 써서 잘 모르겠다) 했는데
어느 지인의 얘기에 따르면 여전하다고 하네... -_- 어쩌라고.

Posted by 사무엘

2011/03/17 08:32 2011/03/17 08:32
, , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/481

큼직한 그래픽 화면에서 마우스로 조작하는 컴퓨터-사용자 인터페이스를 일명 GUI라고 부른다.
매킨토시가 원조라고 하는 이런 환경에서는 대화상자가 라벨, 입력란, 리스트박스, 버튼 같은 몇몇 기초 UI 요소들로 구성되며, 이 구성요소들을 윈도우 프로그래밍에서는 ‘컨트롤’이라고 부른다. GUI에서 일종의 부품과도 같다.

이런 GUI와는 달리, 그냥 전통적인 선택 막대만으로 각종 기능을 선택하고 옵션을 설정하는 단순한 인터페이스도 있는데, 과거의 도스용 아래아한글이 대표적인 예였다.
단순한 인터페이스는 말 그대로 너무 단조로워 보이기는 하지만, 다른 건 몰라도 화면 차지 면적이 작다는 장점 하나는 독보적이기 때문에 요즘은 스마트폰의 UI에서 제 위치를 찾은 것 같다.

이 글의 주제는 윈도우 GUI 컨트롤이므로 다시 GUI로 화제를 바꾸기로 한다.
아까 말했던 입력란(edit box), 라벨, 리스트박스, 버튼(체크, 라디오 등도 포함) 같은 건 기본 중의 기본 필수 요소이며, 까놓고 말해 윈도우 1.0 시절부터 존재했던 녀석이다. 해당 컨트롤의 기능은 운영체제와 완전히 일심동체가 되어 깊숙이 박혀 있다.
비단 운영체제의 GUI뿐만이 아니라 어느 GUI 툴킷을 보더라도 저런 컨트롤이 빠진 물건은 없다.

그런데 세월이 흐르다 보니 좀 더 새끈하고 산뜻한 컨트롤이 필요해졌다.
그래서 1990년대 후반, 윈도우 NT 3.51, 그리고 윈도우 95에서부터 운영체제 차원에서 새로운 컨트롤들이 여럿 도입되었다.
이름하여 공용 컨트롤(common control). 윈도우 1.0 때부터 있었던 innate한 선배들 system control과 구분하기 위해 붙은 이름이다.

무엇이 추가되었냐 하면,
트리 컨트롤: 계층 구조, 목차 따위를 표시할 수 있다.
리스트 컨트롤: 수많은 개체를 단순히 리스트 형태뿐만이 아니라 아이콘 모양으로도 표시할 수 있고, 개체의 특성을 여러 칼럼으로 분할해서 표현할 수 있어서 유용함.
도구모음줄(toolbar)과 상태표시줄(status bar)
탭 컨트롤
진행 상황 게이지 컨트롤(progress bar)

나름 쓸모 있는 것들이 많다. 특히 윈도우 95의 탐색기는 죄다 이 새로운 컨트롤을 잔뜩 우려먹어서 만든 것이다.
리스트 컨트롤과 기존 리스트박스는 하는 역할이 일면 비슷하다 할 수 있으나, 아이템을 추가하거나 정보를 얻어 오는 프로그래밍 인터페이스는 서로 완전히 다르다. 새로운 녀석이 기능이 워낙 많다 보니 훨씬 더 복잡하다. 게다가 둘은 사용법도 차이가 있다. 가령, 아이템을 복수 선택할 때 기존 리스트박스는 Shift+F8과 Space를 사용하지만, 리스트 컨트롤은 Ctrl+화살표와 Ctrl+Space를 사용한다.

이들 공용 컨트롤들은 어차피 MS가 오피스 같은 선구자적(?) 제품에서 자체 구현해 놓고 쓰던 컨트롤들을 운영체제 차원에서 정형화해 놓은 게 많았다.
예를 들어 도구모음줄과 상태표시줄은 어느 응용 프로그램들이나 자체적으로 구비해 놓던 GUI 요소였는데 그걸 다루기 쉬운 정식 컨트롤로 만들어 놨다. MFC도 16비트 시절에는 CToolBarCtrl이 도구 아이콘을 그리고 관리하는 자체 구현이었지만, 32비트부터는 공용 컨트롤에다 요청만 하는 형태로 바뀌었다.

윈도우 3.x의 매체 재생기는 자체 구현한 slider로 재생 위치를 표시했지만, 윈도우 95의 매체 재생기(지금 있는 Media Player의 전신)는 공용 컨트롤에 있는 slider를 썼다.
윈도우 3.x 시절의 설치 프로그램들은 자체 구현한 게이지로 설치 진행 상황을 표시했지만, 윈도우 95의 설치 프로그램은 공용 컨트롤에 있는 게이지를 쓴다. 컨트롤들의 재사용성이 향상된 셈.
비주얼 C++ 4.x의 예제 프로그램 중에는 이런 공용 컨트롤들을 다루는 모습만 시연해 놓은 놈도 있을 정도였다. 아래 그림을 참고하라.

사용자 삽입 이미지

공용 컨트롤들은 시기적으로 나중에 추가된 만큼, 기존 시스템 컨트롤만치 운영체제와 뗄레야 뗄 수 없는 일심동체 형태는 아니었다. 시스템 컨트롤들의 코드가 운영체제의 3대 요소 중 하나인 user(32)에 통합되어 있다면, 공용 컨트롤은 comctl32라는 고유한 라이브러리에 따로 들어있었다. 그리고 이들 컨트롤을 쓰려면 응용 프로그램이 comctl32.dll을 로딩하고 InitCommonControls 같은 함수도 호출해 줘야 했다.

실제로, ListBox, ComboBox, Edit 같은 시스템 컨트롤들은 언제라도 GetClassInfo 함수로 컨트롤의 정체성 정보를 확인할 수 있는 반면 SysListView32, msctls_statusbar32 같은 공용 컨트롤은 comctl32.dll을 별도로 읽어들이고 나야 정보를 얻을 수 있다. 운영체제와 완전한 일심동체가 아니라는 말이 이런 의미인 것이다.

다만, 굳이 InitCommonControls 초기화를 할 필요는 없이 그 DLL을 LoadLibrary만 해 줘도 되는 듯하다.
또한, 이들 컨트롤을 운영체제의 대화상자에서 쓴다면, 어차피 DialogBox 같은 함수가 comctl32.dll의 로딩과 공용 컨트롤의 초기화 정도는 알아서 해 주는 것 같다. 따라서 현실적으로는 응용 프로그램 개발자가 일일이 InitCommonControls를 호출은 안 해도 된다.

공용 컨트롤 라이브러리는 저렇게 새로운 컨트롤만 부품 차원에서 제공하는 게 아니라, 이들 컨트롤을 이용한 자체 UI 기능도 함수 형태로 제공한다. 탭 컨트롤을 이용한 Property Sheet와, ‘이전, 다음’ 형태인 Wizard가 대표적인 예이다. 이것도 윈도우 3.x 시절부터 자체 구현이 하도 유행으로 뜨다 보니까 운영체제 차원에서 자동화 기능을 넣어 준 셈이다.

윈도우 95 이후로 공용 컨트롤 라이브러리는 윈도우 XP에서 또 큰 변화를 겪었다. 이는 물론 테마라는 기능이 추가되었기 때문이다.
컨트롤을 그리는 방식이 예전과는 근본적으로 완전히 다르게 바뀌었기 때문에, 예전 라이브러리를 고칠 수는 없어서 그건 호환성 차원에서 그대로 두고 새 라이브러리를 덧씌우는 방식이 채택되었다. 바로 윈도우 XP에서 추가된 DLL side-by-side assembly 매니페스트 방식으로 말이다.

윈도우 시스템 디렉터리에 있는 comctl32.dll은 이제 구형이다. 윈도우 비스타나 7에서도 이놈의 제품 버전은 6.x이지만 파일 버전은 5.8x에서 멈춰 있음을 알 수 있다. 그 반면, 새로운 comctl32.dll은 Windows\winsxs 같은 완전히 다른 곳에 숨어 있다.
새로운 comctl32는 원래 user32에 있던 기존 컨트롤들을 테마가 적용된 자기 걸로 다 대체해 버린다. 그래서 Spy++ 같은 프로그램으로 확인해 보면, Edit· Button 같은 시스템 컨트롤들도 클래스 스타일에 CS_GLOBALCLASS 같은 플래그가 있다.

또한, URL 링크 같은 새로운 공용 컨트롤이 XP에서 추가되었는데, 이런 것들은 응용 프로그램이 6.0 버전 이상의 새로운 공용 컨트롤 라이브러리를 사용하겠다는 표식을 명시적으로 해야만 사용 가능하다. 나중에 새롭게 추가된 기능은 호환성을 지키기 위해 옛날 프로그램들에게는 바로 노출되지 않으며, 접근 내지 사용하가 이런 식으로 더욱 까다로워진다는 걸 알 수 있다.

이거 지정을 위해 예전에는 개발자가 매니페스트 xml 문서를 직접 써 줘야 했지만 비주얼 C++ 2005부터는 #pragma comment(linker, ...) 한 줄로 손쉽게 할 수 있다. 사실, 2005부터는 MFC와 C 라이브러리 DLL 지정도 이런 방식으로 바뀌었고, 2008부터는 윈도우 비스타에서 추가된 응용 프로그램 권한 등급 지정도 이렇게 할 수가 있다는 것도 잘 알려진 사실이다.

윈도우 비스타에서부터 추가된 UI 기능인 Task dialog 역시 comctl32.dll에 기능이 구현되어 있으며, 공용 컨트롤 6.0 이상이 지정된 응용 프로그램에서만 사용 가능하다. 쉘(shell32)이나 공용 대화상자(comdlg32) 계층에 구현되어 있지 않나 생각했는데 그렇지는 않다.

닷넷 프레임워크에서는 저런 운영체제의 지저분한 버전 별 디테일을 전혀 신경 쓸 필요가 없다는 게 좋은 점 중 하나이겠다.

Posted by 사무엘

2011/02/26 08:12 2011/02/26 08:12
, , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/471

아래아한글이 윈도우 비스타부터 키매크로를 지원 안(못) 하는 이유는?
(관련 글: 아래아한글의 키매크로 )
이것과 관련하여 갑자기 떠오른 생각이 있어서 글을 남긴다. 본인은 한컴에 입사한 개발자도 아니고 아래아한글의 소스 코드를 본 적도 없지만, 본인이 보기에 이것 때문이 거의 확실하다.

윈도우 훅 중 WH_JOURNALRECORD와 WH_JOURNALPLAYBACK 훅이 비스타에서부터는 보안 강화를 이유로 차단되었기 때문이다. MSDN을 보면 알 수 있지만 저건 완전 키매크로를 구현하라고 만든 훅이다.
(관련 글: 훅킹 프로그래밍 )
실패 사유를 나타내는 에러 코드는 5(access denied)가 들어온다.
심지어는 프로그램을 관리자 권한으로 실행해도 차단은 풀리지 않는다. 이건 좀 너무 심하지 않았나?

물론, 키매크로를 구현하는 방법이 저 훅만 있는 건 아니기 때문에 다른 키보드/마우스 훅을 사용하여 동일 기능을 우회 구현할 수도 있다. 하지만 이래저래 개발자에게는 귀찮고 짜증나는 일이 하나 더 생긴 게 틀림없다.

참고로 이렇게 차단을 하는 주체는 사용자 계정 컨트롤(UAC)이다. 그렇기 때문에 이걸 끄면 비스타도 XP와 완전히 동일하게 동작은 한다. 하지만 보안상으로는 위험하기 때문에 개발자가 사용자에게 UAC를 끌 것을 강요해서는 안 된다.
UAC는 안전을 위해 프로세스 간 의사소통을 하는 메커니즘에도 상당한 제약을 부과했다. 단적인 예로, 권한이 낮은 프로그램이 권한이 높은 프로그램에게 임의의 메시지를 보낼 수 없다.

이미 아시는 분도 있겠지만 <날개셋> 한글 입력기는 5.3부터 입력 패드라는 프로그램을 제공하고 있다. 윈도우 IME 훅킹을 통해, 정식 외부 모듈이 아니면서도 외부 모듈의 동작을 흉내 내어 주는 프로그램인데, 이 프로그램을 제대로 사용하려면 관리자 모드로 실행해 줘야 한다. 그렇지 않으면 입력 패드보다 권한이 높은 프로그램(관리자 권한으로 실행된)에다가는 글자 입력을 할 수 없게 된다.

그런데, UAC 하에서도 예외적으로 실행 중인 모든 프로세스의 윈도우에다가 메시지를 보낼 수도 있고 심지어 봉인된 WH_JOURNAL* 훅까지 구사할 수 있는 만능 권한 등급이 없는 건 아니다. MS에서는 대표적인 예 중 하나로 장애인의 UI 접근성 개선을 위해 쓰이는 프로그램에게나 그런 만능 권한을 주고 있다.
예를 들어 화면 키보드 같은 프로그램이야 권한을 초월하여 아무 프로그램에게나 문자 입력 메시지를 전달할 수 있어야 하고 심지어 운영체제 로그인 UI에도 존재해야 하기 때문이다. (ID/패스워드 입력할 때)

단지 그 권한을 얻기가 더럽게 까다로워서 문제이다. 만능 권한을 얻을 수 있는 프로그램은 사용자의 컴퓨터에 반드시 관리자 권한으로 정식으로 설치되어 EXE 파일이 Program Files 같은 특정 경로에만 존재해야 한다. 잘 알다시피 UAC 하에서는 평소에는 Program Files 디렉터리 밑에다가 파일을 만들지도 못한다.

또한, 결정적으로 EXE 내부에 디지털 서명이 되어 있어야 한다. 과거에 마치 ActiveX를 배포할 때 안전한 코드 인증을 받는 것처럼 말이다. 이거 서명을 받으려면 $이 필요하고, 무엇보다도 사업자 등록 번호가 있어야 한다. 즉, 듣보잡 개인 개발자는 서명을 받지도 못한다는 뜻.
따지고 보면 <날개셋> 입력 패드도 일종의 화면 키보드처럼 UI 접근성 개선 프로그램의 성격이 강하기 때문에 저런 권한이 있어야 할 텐데... 그러지는 못하고 있고 그저 사용자가 알아서 충분히 높은 권한을 줘서 프로그램을 실행해 주길 바랄 뿐이다.

이래저래 보안이 안전을 빌미로 세상을 많이 복잡하게 만들고 있다.
(관련 글: 프로그램의 권한 )

Posted by 사무엘

2010/09/13 18:34 2010/09/13 18:34
, , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/372

윈도우 운영체제에는 MDI (Multiple Document Interface)라는 규격이 존재하여, 한 응용 프로그램이 메모리가 허용하는 한 여러 파일 내지 문서를 한꺼번에 다루는 걸 수월하게 해 줬다. MDI 프로그램에는 '창'이라는 메뉴가 존재한다.
과거에 도스용 아래아한글이 기껏해야 겨우 두 개의 문서만 동시에 열 수 있었던 것에 비하면 이건 아주 획기적인 개념이 아닐 수 없었다. MDI는 무려 윈도우 3.x는 말할 것도 없고 원래 2.x 때부터 존재한 개념이라고 한다.

그래서 나만의 작업 문서라는 개념이 있고(스프레드 시트, 그래픽, 워드 프로세서 등등), 좀 규모가 있다 싶은 업무용 프로그램이라면 예외 없이 MDI 방식으로 만들어졌다. 그리고 본인이 개발한 <날개셋> 편집기 프로그램도 1.0 시절부터 MDI였다. ^^
프로그램 자체를 중복 실행하지 않고 한 프로그램 안에서 여러 문서를 동시에 열 수 있는 것은 작업 생산성 면에서 매우 바람직하고 시스템 자원 사용 효율면에서도 좋기 때문이다. (한 번에 소스 코드를 하나만 열 수 있는 에디터로 대규모 프로그래밍 작업을 해 보면 어떨까? -_-)

물론, 윈도우 운영체제가 제공하는 액세서리 프로그램들은 그 정도의 근성은 없는 그냥 말 그대로 액세서리에 불과하기 때문에 MDI 프로그램을 찾아볼 수 없다. 마치 워드패드나 그림판처럼 말이다.
하지만 과거 윈도우 3.x 시절에는 운영체제(?)의 쉘이요 간판 프로그램이라 할 수 있는 '프로그램 관리자'가 딱 MDI 프로그램이었다.

이 MDI 방식에 대해서는 비판도 많았다. 그 자체가 사실 등장한 지 20년 가까이 된 너무 구닥다리 인터페이스이도 하고.. 특히 Aero가 적용된 윈도우 비스타에서도 MDI 창들은 여전히 전혀 세련되지 못한 밋밋한 모양이다.
그래서 요즘은 프로그램 안에 또 여러 창이 타일처럼 더덕더덕 겹쳐 있는 모습 자체를 안 보이려고 하는 게 대세이다. 그 대안으로 각광받고 있는 건 탭 인터페이스이다.

이런 추세는 MS의 주력 상품인 오피스에서도 바로 나타났다. 그것도 꽤 오래 전부터 말이다.
워드의 경우, 아예 10년 전 오피스 2000부터 MDI 방식을 버렸다. 그냥 모든 문서마다 응용 프로그램 프레임이 따로따로 붙어서 '창' 메뉴만 있을 뿐 SDI 프로그램을 여러 개 실행한 것처럼 동작한다.
마치 윈도우용 아래아한글처럼 말이다. 특이하게도 오피스 제품들 중, 워드만 유일하게 그렇게 따로 놀고 있다.

사용자 삽입 이미지

엑셀은 그래도 좀 전통적인 스타일을 유지하고 있다. MDI스러운 메뉴를 볼 수 있으며, 여러 문서 창들을 응용 프로그램 창 내부에다가 덕지덕지 배열할 수 있다. 엑셀은 표 형태로 된 각종 수치와 데이터를 처리하는 프로그램이지 않던가? 당연히 그런 식으로 한 화면에서 여러 파일을 대조할 수 있어야 한다.

사용자 삽입 이미지

하지만 파워포인트는 성격이 좀 다르다. 큼직한 화면 전체에다가 슬라이드 그림을 놓고, 그 곁엔 다른 슬라이드들 썸네일과 슬라이드 노트를 작성하는 공간이 들어가기 때문에 근본적으로 화면이 많이 필요하다.
즉, 파워포인트 슬라이드의 작업 화면은 엑셀 워크시트와 같은 MDI 식 덕지덕지 타일 배열 자체가 무의미하다. 그래서 파워포인트는 워드가 아닌 MDI 형태임에도 불구하고 MDI 메뉴를 갖추고 있지 않으며, 문서 창은 언제나 최대화되어 있다고 가정하고 동작한다. 굳이 최대화 상태를 해제려면 계단식 배열 같은 별도의 명령을 직접 내려 줘야 한다.

사용자 삽입 이미지

끝으로 데이터베이스 프로그램인 엑세스는 한 프로그램이 한 데이터베이스만 열 수 있고, 그 데이터베이스 안에 있는 각종 테이블, 쿼리, 모듈 등을 MDI 형태로 여럿 열어볼 수 있는 형태이다. 이런 점에서는 엑셀처럼 매우 MDI스러운 UI를 유지하고 있는 셈인데, UI 기반이 엑셀과는 다르다 보니 각 창에 대한 시스템 메뉴도 갖추고 있고, MDI 배경색이 엑셀이나 파워포인트의 배경색보다는 짙다. 또한 View 탭이 따로 없으며, 창과 관련된 메뉴가 Home 탭에 같이 들어있다.

사용자 삽입 이미지

이렇듯, MS 오피스의 주축을 이루고 있으며 2007부터 리본 UI가 첫 적용된 워드, 엑셀, 파워포인트, 액세스의 UI 형태는 다 조금씩 차이가 있다는 사실이 흥미롭다. 참고로, 엑셀이나 파워포인트는 워드처럼 매 문서창이 완전히 제각각 따로이지 않음에도 불구하고, 매 문서마다 운영체제의 작업 표시줄(Taskbar)에 제목이 마치 별개의 프로그램처럼 추가된다. 이 역시 2000부터 그렇게 되었는데, 무척 특이한 점이 아닐 수 없다.

MDI에 대해 끝으로 생각해 볼 점은, 웹브라우저나 파일 관리 유틸리티가 MDI 형태로 개발되고 있지 않다는 것.
이들은 분명 한 프로그램이 여러 창을 취급할 수는 있어야 하지만, 문서라는 개념을 다루는 프로그램이 아니라는 것이 독특하다.

Posted by 사무엘

2010/09/07 14:43 2010/09/07 14:43
, ,
Response
No Trackback , 5 Comments
RSS :
http://moogi.new21.org/tc/rss/response/367

※ CreateFont

받는 인자가 무려 14개나 되어, Win32 API 전체를 통틀어 손꼽힐 정도로 받아들이는 인자가 많다. MSDN 레퍼런스 없이는 함부로 꺼내 쓰지도 못한다.
그렇다고 해서 딱히 포인터를 전달한다거나, 결과값을 받는다거나 하는 것도 아니고 인자들은 다 단순한 int 아니면 문자열들이다. 이 값들을 LOGFONT라는 구조체에다 담아서 한꺼번에 전달하는 CreateFontIndirect라는 함수가 별도로 있기도 하다.

하지만 실제로 쓰이는 인자는 글꼴 이름과 크기(가중치 100), 그리고 아주 가끔 빌드/이탤릭 여부(가중치 20) 정도가 진짜 전부이다.
전문적인 워드/그래픽 프로그램이 아니고서야 장평값이 다르다거나 기울여진 상태로 글자를 찍을 일이 있기나 할까? 운영체제가 기본으로 지정한 퀄리티(안티앨리어싱 여부) 말고 다른 걸 지정할 일도 거의 없기는 마찬가지. 좀더 간단한 형태의 함수가 있었으면 좋겠다. MFC의 CFont::CreatePointFont()처럼 말이다.

※ CreateProcess

인자 개수 10개. 프로그램을 실행하는, 좀더 정확히 말하면 프로세스를 생성해 주는 가장 저수준 함수이다.
실생활에서는 파일 이름과 매개변수(가중치 100)만 있으면 거의 다 통용되고, 거기에다 초기 시작 디렉터리와 윈도우 초기 배치 방식을 나타내는 SW_* 값 정도만 있으면 될 것이다(가중치 20).

하지만 이 함수 역시 사용하기는 무진장 까다롭다. 파일 경로를 나타내는 버퍼는 read only여서는 안 되고 write 가능한 영역에 있어야 한다. 운영체제가 이 문자열을 그대로 strtok 스타일로 tokenize를 했다가 다시 원래 형태로 되돌려 주기 때문이다. null 문자를 잠시 삽입하므로 이는 버퍼를 수정하는 행위임.
디버거 붙일지 여부, 각종 보안 설정, 환경 변수 값, 심지어 멀티모니터 환경에서 프로그램을 초기에 띄울 모니터 위치 등등.. 별별 정보를 다 지정 가능하기 때문이다.

게다가 리턴값으로는 새로 생긴 프로세스 및 스레드의 식별자와 핸들 같은 것도 돌아오는데, 그 핸들은 이 함수를 호출한 프로세스가 알아서 Close 해 줘야 된다. 여간 손이 많이 가는 게 아니다.
MS는 프로그램을 실행할 때 16비트 시절의 잔재인 WinExec 함수를 사용하지 말고 이 함수를 사용할 것을 권하나, WinExec의 간편함(달랑 명령줄과 윈도우 배치 방식만 넘겨주면 됨!)의 유혹을 뿌리치기는 쉽지 않을 것이다. 사실 WinExec도 이제는 내부적으로 CreateProcess를 호출하는 방식으로 실행된다.

※ CreateFile

인자 개수 7개. C 표준 함수에 있는 fopen처럼 파일 이름과 용도(많지도 않다. 읽기 아니면 신규 생성)만 있었으면 좋겠지만, 역시 운영체제 API이다 보니 보안 관련, 파일 공유 여부 같은 잡다한 정보들이 엄청 많이 들어간다. 파일을 그저 문서의 열기/저장 기능 구현 용도로나 쓴다면 대부분의 세부 옵션들은 필요하지 없으며, 그냥 디폴트만 넘겨 주면 된다.
사실 이 함수는 디스크 상의 파일뿐만 아니라 파일의 형태로 표현 가능한 각종 운영체제 오브젝트들을 생성할 수도 있는 상당히 다재다능한 녀석이다. 피타고라스는 세상만물이 수라고 말했다면, 유닉스에서는 모든 게 파일이라고 한다. 윈도우 운영체제도 그런 철학이 아주 없지는 않다.

※ GetOpenFileName

우리에게 친근한 파일 열기 대화상자를 꺼내 주는 함수. 이제 얘는 인자로 일일이 입력 정보를 받는 방식을 애초부터 포기하고, 대신 크고 아름다운 구조체만을 받는 형태이다. C++로는 응당 클래스를 만들어 쓴다. MFC의 CFileDialog처럼.

하지만 실제로 자주 쓰이는 정보는 열기/저장 여부, 시작 디렉터리, 파일 포맷 필터 말고 있나? (가중치 100)
거기에다가 아주 가끔씩 파일 복수 선택 여부라든가 '읽기 전용으로 열기' 같은 자잘한 옵션만.. (가중치 30)
이렇게 굳이 구조체 만들 필요 없이 간단하게 실행이 끝나는 함수도 좀 있었으면 좋겠다는 생각을 꽤 자주 하곤 했다.

※ TaskDialogIndirect

너무나 클래식한 API인 MessageBox 함수를 대체하는 새로운 UI 대화상자 함수로, 윈도우 비스타에서 처음으로 추가된 걸로 잘 알려져 있다.
다른 건 '메시지 박스' 그대로 쓰면 되는데 "다음부터 이 메시지 표시하지 않음" 체크 같은 딱.. 2% 아쉬운 면모만 보충하고 싶을 때... 이 함수가 가히 구세주이다. 참고로 이 함수를 쓰려면 공용 컨트롤 6.0 매니페스트가 필수라는 걸 잊지 말자.

물론 얘는 TaskDialog와 TaskDialogIndirect로 아예 두 버전으로 나뉘어 있고, 쓸데없이 괜히 함수 프로토타입만 복잡한 게 아니라 진짜로 사용자가 실제로 쓸 수 있는 기능이 엄청 많은 게 맞다. 최근에 만들어진 만큼 API를 비교적 잘 설계했다는 생각이 든다. 하지만 정확하게 기억은 안 나는데 TaskDialog에는 정작 내가 꼭 써야 하는 customize 기능이 빠져 있어서 어쩔 수 없이 훨씬 더 복잡한 TaskDialogIndirect 함수만 써야 했던 것 같다. 그건 아쉬운 점.

대화상자의 제목, 큰 제목, 본문, 각 버튼의 모양, 링크, 라디오 상자 등등등...
이건 구조체가 아니라 아예 대화상자 생성 스크립트(XML 기반)를 받게 해도 이상할 게 없어 보인다.
최신 MFC에는 이 task dialog를 감싸는 클래스가 "당연히" 추가되어 있으며, 각종 상업용 GUI 패키지들에는 XP 이하 운영체제에다가도 task dialog를 자체 구현한 솔루션이 있기도 하다.

Posted by 사무엘

2010/06/29 08:53 2010/06/29 08:53
,
Response
No Trackback , 3 Comments
RSS :
http://moogi.new21.org/tc/rss/response/306

프로그램의 권한

1.
병특 회사에서 근무하던 시절의 일이다.
그때 본인은 본업을 넘어-_-, ActiveX 컨트롤을 만들어 관리하던 적이 있었다.
(사용자들이 아무리 ActiveX 욕하고 우리나라가 무슨 MS 공화국이네 뭐네 하면서 까도, 일선 개발자들은 위에서 까라면 깔 수밖에 없다. 더구나 본인은 국방부 시계가 돌아가던 중! ^^;;; )
ActiveX는 내부에 플래시 UI를 하나 만들어서 플래시는 웹 상에서 사용자와 소통을 하고, ActiveX는 플래시와 소통을 하면서 플래시만으로 하기 힘든 네이티브 코드를 수행했다. 내가 왕년에 저런 일까지 했다니..

그런데 문제가 있었다. 정확하게는 기억이 안 나지만, ActiveX든 플래시든.. 뭔가 로컬에 있는 파일을 참조하는 건 아무 문제가 없었는데 웹에 있는 놈을 가져오는 건 아무 이유 없이 도무지 되지 않고 작동을 거부하는 것이었다.
먼 옛날 일이 됐으니 망정이지, 이것 때문에 당시 회사에 환멸을 느낄 정도로 좌절하고 삽질했었다. -_-;;

문제의 원인은 보안이었다. 그 당시 갓 출시된 플래시 7이던가 8이던가.. 하필 그때부터 보안 정책이 딱 바뀌어 플래시의 액션스크립트는 아무 웹에서나 정보를 덥석 가져오지 못하게 되었다.
그 반면, 내 로컬 컴퓨터의 ....\flash player\#security\flashplayertrust 이런 디렉터리에다가 configuration file을 만들어서 접근을 허용하는 웹 주소를 먼저 적어 줘야 하고, 플래시는 허용된 웹으로만 접근할 수 있다.
자세한 정보: http://kb2.adobe.com/cps/116/1165eb90.html

어쨌든 이것 때문에.. 가장 권한이 많고 강력한 ActiveX가 DllRegisterServer를 통해 등록될 때 저 flashplayertrust에다가 우리 플래시에 대한 정보를 덩달아 등록해 주고, 등록 해제될 때 그 정보를 삭제하도록 함으로써 문제는 일단락되었던 걸로 기억한다. ActiveX는 네이티브 코드인 관계로 파일, 레지스트리, 웹 등에 다 접근이 되고, 심지어 Win32 API를 직접 호출해서 뭐든 다 할 수 있으니.. 사기 유닛이다.

물론 오늘날은 다른 웹 표준과 RIA 기술도 풍부한데 저런 무식한 방법을 쓰는 건 곤란하다.
참고로 플래시에 전설의 flv 동영상이 추가된 게 그 무렵부터일 것이다. 유튜브가 그때 막 태동했으니 말이다. 플래시가 벡터 드로잉 애니메이션뿐만 아니라 일반 비디오 플레이어 분야도 섭렵하기 시작했으며, 덕분에 이제 인터넷으로 동영상 볼 때 ActiveX 설치를 요구하는 사이트는 개념 없다는 소리를 듣기 시작하게 됐다.

2.
안드로이드 어플 만들면서도 비슷한 경험을 했다. 아놔 다른 프로그램에서는 잘 되는 환경설정 변경이 왜 도대체 안 되고, 기껏 되더라도 왜 내가 바꾼 환경설정이 다른 곳에 도무지 적용이 안 되는지.. 함수 호출 결과는 성공인데.. 그 뒤 결과는 그냥 씹히고 있던 것이다.
하루를 삽질하고 났더니 원인은 역시 매니페스트 파일에다가 android.permission.WRITE_SETTINGS , android.permission.CHANGE_CONFIGURATION 요 따위 퍼미션 요청을 안 해 놨기 때문이었다.

3.
그동안 유닉스 계열 OS에 비해 권한이나 보안 같은 관념이 너무 약하던 윈도우도, 비스타부터는 그쪽으로 좀더 엄격해졌다.
잘 알다시피 사용자 계정 컨트롤(UAC)라는 게 추가됐으며, 프로그램을 관리자 권한으로 실행할 때와 그렇지 않을 때에 허용되는 권한의 차이가 매우 커졌다. 가령, 관리자 권한이 아니면 '내 문서' 말고 다른 디렉터리에다가는 파일을 제대로 만들지도 못한다.

그리고 이 프로그램이 요구하는 권한을 명시하는 게 가능해졌다.
아무 권한에서나 실행 가능한지, 무조건 관리자 모드에서 실행돼야 하는지 하는 걸 말이다.
지정은 EXE 내부의 매니페스트 XML에다가 하면 된다. 그 개념은 이미 윈도우 XP에서 시스템 DLL의 로딩 방식을 제어하기 위해 도입된 바 있으므로 새삼스러울 게 없다.
비주얼 C++ 2008부터는 링커 옵션에 이걸 바로 지정해 주는 게 추가됐다. 그 이전 버전에서는 사용자가 직접 xml 파일을 손으로 써서 링크해 주면 된다.

스크린 키보드처럼 장애인 Accessbility용 프로그램은 의외로 높은 보안 수준이 필요하다.
내가 받은 입력에 대한 결과를 시스템 모든 프로그램에다가 끼쳐야(키보드 입력 흉내) 하기 때문에
이런 프로그램은 별도의 인증을 거쳐야 운영체제가 그 정도의 권한을 허락하게 되어 있다.
그런 인증을 거치지 않은 "<날개셋> 입력 패드"는, 사용자가 직접 관리자 권한으로 실행해 주지 않으면,
자기보다 권한 등급이 높은 프로그램에다가는 글자 입력을 전달해 줄 수 없다.

글을 맺는 소감:
삽질해야 하는 게 싫다. -_-;;
지금 유닉스 명령어 익히느라 땀 뻘뻘 흘리는 걸 보면, 옛날에 지금보다 영어도 훨씬 더 못 하던 시절에 도스 명령은 어째 알아서 외웠는지 궁금하다.
지금 이놈의 안드로이드 때문에 삽질하는 걸 보면, 옛날에 윈도우 API는 어째 공부했는지 내가 생각해도 나 자신을 이해할 수 없다.
그때는 삽질을 삽질이라고 여기지 않고 전적으로 재미로 했기 때문에 프로그래밍에 재미를 붙일 수 있었던 것 같다.

Posted by 사무엘

2010/06/22 08:55 2010/06/22 08:55
, , ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/300

파일 대화상자

1. 파일 대화상자라는 개념

윈도우 운영체제.. 사실 이뿐만이 아니라 플랫폼을 불문하고 현대적인 GUI 프레임워크들은
불러오기/저장하기(파일 선택) 기능을 공통 기능으로 제공한다.

어떤 형태로든 사용자가 작업하는 문서(데이터)를 파일로 읽고 쓰는 소프트웨어치고 이 기능을 안 쓰는 녀석은 없으므로, 이건 가히 필수 공통 기능이라 하기에 손색이 없다. 도스 시절에는 불러오기/저장하기 UI도 프로그래머가 제각각으로 직접 구현해야 했으니 얼마나 번거로웠는지 모른다. 이거 하나만 운영체제가 고수준 API를 제공해 줌으로써 응용 프로그램이 직접 FindFirstFile, FindNextFile 같은 파일 탐색 함수를 호출해야 할 일은 상당수 없어졌다.

물론 이것 말고도 색깔을 찍는 대화상자, 인쇄 대화상자 같은 것도 공통 대화상자에 속하며 운영체제가 제공해 주는 게 있다. 그리고 필요한 경우, 대화상자의 일부 요소나 동작 방식을 프로그래머가 자기 입맛에 맞게 customize하는 테크닉도 응당 제공된다.

2. 윈도우 운영체제의 파일 대화상자의 역사

윈도우 3.x의 파일 대화상자는 파일 목록과 디렉터리 목록이 리스트 박스의 형태로 좌우로 나란히 나오고, 그 아래에는 저장하거나 열려는 파일의 format 그리고 드라이브 목록이 콤보 박스의 형태로 나란히 나와 있었다. 드라이브-디렉터리-파일이라는 클래식한 형태에 충실한 디자인이라 하겠다. 가정에서는 네트웍이 아직 많이 생소하던 시절이었기 때문에, 네트웍 드라이브에 접근하기 위해서는 별도의 버튼을 눌러야 했다.

사용자 삽입 이미지

그러던 것이 윈도우 95/NT4에 와서는 크게 바뀌었다. 사실 윈도우 95부터는 쉘의 디자인의 근간이 싹 바뀌어 오늘날까지 이어져 오고 있다. 드라이브를 제공하는 장치간의 구분이 완화되었고, 가장 최상위 계층인 바탕 화면 아래로 내 컴퓨터, 휴지통 등등이 따르는 컨셉이 이때 도입된 것이다. 파일 리스트는 구닥다리 리스트 박스 대신, 소위 공용 컨트롤이라고 불리는 리스트뷰 컨트롤 기반으로 바뀌고 디렉터리와 드라이브는 폴더라는 개념으로 바뀌었다. 그리고 탐색기가 제공하는 쉘 기능(파일 복사, 붙여넣기, 삭제, 개명, 각종 우클릭 메뉴)은 파일 대화상자 내부에서도 그대로 쓸 수 있게 된 것 역시 큰 변화이다.

사용자 삽입 이미지

윈도우 98부터는 파일 대화상자의 크기 조절이 가능해졌다. 상당히 바람직한 변화이다.

윈도우 2000/ME부터는 파일 리스트 왼쪽에 바탕 화면, 내 문서 등 주요 폴더로 곧바로 이동하는 아이콘이 추가되었다(일명 favorite bar). 그리고 아마 이 무렵부터, 파일이나 디렉터리 이름의 처음 몇 자를 입력하면 자동 완성 후보가 뜨는 아주 편리한 기능이 생겼다.

이 구조가 윈도우 XP까지 이어지다가 비스타/7부터는 또 파일 대화상자가 싹 바뀌었다. 변화의 양상에 대해 한 마디로 요약하자면, 탐색기와의 경계가 더욱 모호해지고 좀더 "웹처럼"(webby) 바뀌었다. 웹 페이지 탐색하는 기분으로 내 컴퓨터의 폴더를 탐색하게 되었는데, 이는 IE4부터 MS에서 부르짖은 캐치프레이즈이기도 하다. 물론 탐색기와 IE의 완전 통합은 보안상의 이유로 인해 IE7부터는 좀 지양되었지만 말이다.

얼마나 바뀌었냐 하면, 파일 대화상자에도 웹브라우저처럼 "뒤로, 앞으로" 버튼이 생겼고, 검색란이 생겼다. 자주 쓰는 폴더 목록은 마치 인터넷 즐겨찾기처럼 뜨기 시작한 것이다. 그런 디자인이야 디자이너의 취향 나름이라 하지만, 기본 크기가 좀더 큼직해지고 마우스로 두세 단계의 폴더를 바로 건너뛰어 상위 단계로 갈 수 있어서 디렉터리 변경이 좀더 편해진 게 매우 좋다.

3. 과거 호환성

이렇게 운영체제가 버전업되면서 파일 대화상자의 디자인은 몇 차례 변화를 겪었다.
응용 프로그램이 아무 조작을 안 가하고 기계적으로 MSDN에 명시된 input과 output만 FM대로 잘 활용한다면, 파일 대화상자의 디테일은 응용 프로그램의 본질적인 동작에 전혀 영향을 끼치지 않는다. (당연한 말이지만)

그렇기 때문에 윈도우 비스타 이전에 개발된 프로그램이라 할지라도, 파일 대화상자 API만 곱게 쓴다면 비스타에서 실행했을 때 최신 디자인의 파일 대화상자가 뜬다. 이게 무슨 공용 컨트롤 매니페스트도 아니고, 최신 대화상자를 쓰기 위해서 응용 프로그램이 뭔가 조치를 취해야 할 필요는 없다.

그럼에도 불구하고 운영체제들은 옛날 버전 파일 대화상자들의 디자인도 갖고는 있다.
응용 프로그램이 파일 대화상자에다가 자신만의 컨트롤을 추가하고, 동작 방식을 제어하고 특정 컨트롤을 서브클래싱까지 하는 경우, 그 파일 대화상자의 디자인이 최신 운영체제에서 바뀌어 버린다면 동작 방식에 심각한 문제가 생길 수 있기 때문이다.

이미지 프로그램의 경우 열기 대화상자에다가는 그림 preview를 추가하기도 하고, 저장 대화상자에다가는 JPG로 저장할 경우 화질을 지정하는 추가 옵션을 대화상자에다 덧붙이곤 했다.
압축 유틸리티나 파일 변환 프로그램은 아예 파일 열기 대화상자에다가 자기네 동작 옵션을 한 보따리 가득 집어넣어 그걸로 프로그램 메인 화면을 만들기도 했다는 걸 알 필요가 있다.

최신 디자인을 적용할 수 없는 경우, 운영체제는 여전히 윈도우 2000이나 심지어 98(favorite bar까지 없어진) 스타일로 파일 대화상자를 출력해 준다.
특히 MFC를 써서 프로그램을 개발하는 경우 이 점을 매우 신경써야 한다. MFC는 프로그래머가 원하는 타이밍에 손쉽게 이벤트를 날려 주기 위해서.. 쉽게 말해 개발자의 편의를 위해서 윈도우에다가 온갖 보이지 않는 훅킹과 서브클래싱을 남발하는데, 이런 이유로 인해서 구형 버전의 비주얼 C++로 CFileDialog 클래스를 쓰면, 아무리 내가 customize를 하는 게 없어도 최신 운영체제에서 파일 대화상자가 최신 디자인으로 나오지 않는다!

까놓고 말해 본인이 개발한 <날개셋> 편집기의 열기 대화상자와, <날개셋> 타자연습의 연습글 추가 대화상자를 윈도우 비스타/7에서 살펴보기 바란다. 차이가 느껴질 것이다.
이런 이유로 인해, 최신 운영체제의 GUI 혜택을 입으려면 새로운 기능을 쓰는 게 없어도 개발툴도 최신으로 써야 하는 경우가 있다. 싫으면 MFC 클래스 쓰지 말고, 불편하더라도 GetOpenFileName처럼 윈도우 API를 직접 호출하든가 말이다. ^^

4. 파일 대화상자의 중복 개발

그런데 MS 오피스 제품들은 전통적으로 운영체제의 표준 API를 쓰지 않고, 무려 자기네가 따로 자체 개발한 파일 대화상자를 사용해 왔다. 가령, 운영체제의 표준 파일 대화상자는 윈도우 2000/ME대에 가서야 favorite bar가 추가된 반면, MS 오피스의 대화상자는 꽤 일찍부터.. 최소한 오피스 97 시절부터 그런 걸 갖추고 있었다.

이런 식으로 MS 내부에서 운영체제 GUI가 오피스 GUI를 뒤쫓아가는 양상은 일상적인 모습 같다. 하다못해 윈도우 3.1 시절에도 오피스가 자체 구현했던 도구모음줄(toolbar), 상황선(status bar), 은빛 3D 효과 대화상자, 프로퍼티 시트와 위저드 같은 게 95로 넘어가면서 운영체제 표준 GUI로 나중에야 편입되었다. 그러던 관행이 세월이 흘러 윈도우 7에서는 리본 인터페이스가 워드패드와 그림판에까지 적용되어 있다.

오피스 제품 중에서도 무려 1980년대부터 개발되어 온 워드와 엑셀은, 겉모습은 별 차이 안 나지만 사실 일반 대화상자들마저도 윈도우 운영체제의 표준 대화상자가 아니며 마치 아래아한글처럼 자체 구현 대화상자이다! 걔네들이 처음부터 아주 크로스 플랫폼으로 개발되어서 그런 건 아니고, 애초에 개발 컨셉이, 빈약한 운영체제의 기본 컴포넌트에 의존하지 않고 자기네 컴포넌트로 UI를 자체 구상하겠다는 방향이었던 것 같다. 그 부자 기업이 하고 싶은 걸 뭘 못 하겠는가?

90년대 이후부터 개발된 파워포인트나 액세스는 그런 수준까지는 아니지만 열기/저장 대화상자라든가 About 대화상자만은 여전히 MS 오피스 공용 라이브러리의 것을 사용해 왔다.
개발툴인 비주얼 스튜디오도 닷넷급부터는 MS 오피스의 GUI 엔진을 이어받고 있는 중이다. 순수 MFC만으로 MS 오피스 짝퉁 GUI을 구현했던 비주얼 C++ 5와 6의 계보는 흑역사가 된 지 오래.

그런데, 그러던 정책이 이제는 바뀌었다.
윈도우 비스타와 동일한 timeline에 개발된 제품인 비주얼 스튜디오 2008과 MS 오피스 2007부터는
놀랍게도 운영체제의 표준 파일 대화상자를 사용하며, 앞으로도 계속 그런 구도가 유지될 것이다!
비주얼 스튜디오 2005와 MS 오피스 2003은 그렇지 않다는 소리.

다만, 이건 비스타 이상에서 실행됐을 때에 한해서이다. 윈도우 XP에서 돌아가는 비주얼 스튜디오 2008이나 MS 오피스 2007은 여전히 자체 대화상자를 사용한다. -_-;; 이것도 무지 신기한 점임.

비스타부터는 이제 운영체제의 파일 대화상자도 기능이 매우 향상되었고 customize하는 수단도 충분히 깔끔해졌기 때문에 굳이 운영체제 따로, 오피스 따로 노선을 갈 필요를 느끼지 않게 되어 그렇게 바뀐 것 같다.
비스타에서는 비주얼 스튜디오 2005의 옛날식 파일 대화상자가 오히려 더 촌스럽게 느껴진다. ^^;;

Posted by 사무엘

2010/05/13 07:34 2010/05/13 07:34
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/267

사용자 삽입 이미지
위의 그림은 동일한 32비트 윈도우용 프로그램을 세 개 연달아 실행하여
1. 자신의 인스턴스 핸들
2. 어떤 지역 변수의 주소
3. 어떤 전역 변수의 주소
4. 그리고 동일한 공유 메모리(memory-mapped file)를 가리키는 주소
를 차례로 찍은 것이다.

그림을 보면 알겠지만 동일한 실험을
a. 윈도우 3.1+Win32s
b. 윈도우 9x
c. NT급 윈도우

에서 모두 해 봤다. (요즘 버전의 비주얼 C++로 그 구닥다리 Win32s에서도 동작하는 프로그램을 만들려면, 컴파일/링크 옵션을 상당히 특이하게 바꿔야 한다. ㄲㄲ)

Win32s의 한계를 절실히 느낄 수 있을 것이다.
CPU의 가상 메모리 기능을 적극 활용하여 각 프로세스마다 자신만의 주소 공간이 절대 보장되는 윈도우 NT에서는,
같은 프로그램은 아무리 동시에 여럿 실행하더라도 자기 주소가 0x400000으로 고정 불변임을 알 수 있다. 심지어 윈도우 9x조차도 그건 보장된다.

그러나 Win32s는 프로그램을 실행할 때마다 프로그램의 인스턴스 핸들이 제각각이며, 지역 변수와 전역 변수의 주소조차도 완전히 달라진다. 시스템의 모든 프로그램들이 단일 주소 공간을 공유한다는 게 바로 저런 의미인 것이다.

Win32s는 모든 메모리 주소가 0x80000000 위의 상위로 잡혀 있는 것도 매우 신기하다.
9x나 NT급 윈도우에서는 그런 주소는 사실상 커널에서나 볼 수 있기 때문이다.
16비트 운영체제에다 아주 특수한 임시방편으로 32비트를 구현한 Win32s의 동작 방식을 짐작케 한다.

또 하나 재미있는 차이를 발견할 수 있는 것은 인스턴스 핸들과 포인터와의 관계이다.
9x/NT에서는 인스턴스 내지 모듈 핸들이 곧 포인터이기 때문에, 0x400000 같은 값에 해당하는 메모리 주소를 들여다보면 EXE 파일이 통째로 로드된 흔적을 고스란히 찾을 수 있다. 즉 MZ 같은 EXE 헤더가 바로 나타난다는 뜻이다. 그리고 전역 변수의 주소는 역시 근처의 0x40????대로 잡힌 것을 볼 수 있다.

그러나 Win32s의 인스턴스 핸들은 포인터와 아무 관계가 없는 임의의 16비트 정수일 뿐이다. 이는 원래부터 포인터가 서로 아무 관계가 없던 16비트 윈도우의 인스턴스 핸들과 개념을 일치시키기 위한 조치로 보인다. 제아무리 32비트 프로그램이라 하더라도 16비트 운영체제 내부에서는 16비트 규모로 식별이 가능해야 하기 때문이다.

끝으로, 공유 메모리의 주소도 흥미로운 결과가 나와 있다. 오로지 윈도우 9x만이 세 프로그램이 가리키는 주소가 모두 일치해 있다.
이는 윈도우 9x만의 메모리 사용 방식 때문이다. 0x80000000~0xC0...에 해당하는 영역에다 모든 프로그램들이 공유하는 운영체제 시스템 DLL과 공유 메모리를 올려 놓는다. 즉, 이 영역은 윈도우 9x에서는 아무 프로그램이나 바로 접근할 수 있는 단일 주소 공간이나 마찬가지이기 때문에 어느 프로그램에서나 의미가 동일한 셈이다.

NT는 그렇지 않다. 비록 실질적으로 가리키는 물리 메모리는 동일한 위치인지 모르나 이를 가리키는 응용 프로그램의 주소는 완전히 제각각이다. 이렇게 하는 게 훨씬 더 안전하고 보안 관점에서도 유리하기 때문이다.

Win32s는 공유건 응용 프로그램의 코드건 데이터건 가리지 않고 무조건 0x80... 상위 메모리 주소가 뒤죽박죽으로 쓰이는데, 공유 메모리마저 9x와는 달리 제각각인 주소가 배당되는 건 좀 의외이다. 9x는 공유 메모리만 상위 메모리 주소가 쓰였고 NT는 보다시피 상위 메모리 주소가 전혀 등장하지 않는다. 사용자 계층과 커널 계층이 엄격하게 잘 분리되어 있음을 뜻한다.

※ 덧붙이는 말

1. 유니코드

일단 Win32s와 9x는 운영체제의 내부적으로는 유니코드 기반이 전혀 아니다. 그래도 9x는 GDI 계층 차원에서 유니코드 문자를 폰트로부터 인식하고 찍는 건 지원하며 98부터는 유니코드 IME 프로토콜까지도 지원한다. 그 반면 Win32s는 운영체제의 한계 때문에 그런 게 전혀 없다. 운영체제 차원에서 임의의 유니코드 문자를 출력할 방법이 없다는 뜻이다.
오늘날까지 살아남은 NT는 무려 1993년에 나온 3.1 버전부터 애초에 100% 유니코드 지원을 염두에 두고 16비트 wide string을 기본으로 설계했으니 과연 대인배. 물론 이렇게 하려면 메모리가 더 많이 필요하다.

9x는 TextOutW, ExtTextOutW, GetTextExtentPoint32W 같은 GDI 함수는 NT와 기능이 동일하다(비록 surrogate는 지원 안 하지만). 그리고 MessageBoxW도 지원한다. 에러 메시지 뱉고 죽는 최소한의 동작만은 유니코드 함수로도 가능하게 배려했다는 뜻이다.
이외에 리소스를 찾는 FindResourceExW, 명령 인자 옵션을 얻어오는 GetCommandLineW 같은 함수가 유니코드 버전도 간단히 구현돼 있다. 비록 문자열을 ansi 문자열로 변환해서 A 함수를 그냥 호출해 주는 수준이지만.

Win32s는 그런 거 없다. MessageBoxW도 지원하지 않으며, 오로지 WideCharToMultiByte(와 그 역함수) 처럼 문자열 변환 함수만 지원되고 나머지 W 함수는 전혀 지원되지 않는다.

2. GDI/User 계층의 32비트

NT는 순수한 32비트 운영체제인 반면 9x 계열은 아직 상당수의 코드가 16비트로 존재했다. 이런 이유로 인해 9x는 대표적으로 GDI의 좌표계가 16비트 크기로 제한되어 있었으며, NT는 GDI 함수의 실행이 실패했을 때 GetLastError() 에러값이 온 반면, 9x 계열은 그렇지 않은 경우가 많았다. 그 에러값은 32비트 코드 계층에서 설정되는 값이기 때문이다.

과거 16비트 윈도우(Win32s도 당연히 포함)에서는 어떤 GDI 오브젝트 자체와 그 오브젝트가 따로 동적으로 할당하는 메모리의 양이 모두 GDI 힙 64KB 내부에 매여 있었다면,
9x는 일단 할당 가능한 오브젝트의 개수는 64KB의 제약을 받으나 각 오브젝트가 추가로 할당하는 메모리는 ‘별도의 제약이 없는 32비트 범위’인 식으로 제한 조건이 완화된 경우가 많았다. 가령, 복잡한 path나 region 같은 경우 추가 메모리 사용량이 만만찮으리라 예상 가능하다.

제약이 완화되기는 했으나 그래도 9x는 공포의 ‘리소스 제한’이 여전했던 것이다. 리소스 퍼센티지를 아직 기억하시는 분 계시려나?
NT는 역시 애초부터 그런 개념이 없었다. 모든 게 자유로운 32비트 공간이고 지금은 64비트로 자연스럽게 확장되어 있기까지 하다. ^^;;

Posted by 사무엘

2010/05/07 07:45 2010/05/07 07:45
,
Response
No Trackback , 6 Comments
RSS :
http://moogi.new21.org/tc/rss/response/261

« Previous : 1 : ... 7 : 8 : 9 : 10 : 11 : 12 : 13 : Next »

블로그 이미지

철도를 명절 때에나 떠오르는 4대 교통수단 중 하나로만 아는 것은, 예수님을 사대성인· 성인군자 중 하나로만 아는 것과 같다.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2021/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:
1698355
Today:
13
Yesterday:
499