이제는 딱히 새삼스러울 것도 없지만, Windows용 응용 프로그램들의 현대화 수준을 나타내는 지표로는 다음과 같은 것들이 있다.
1. 유니코드: 완전 기본 필수. 시대가 어느 시댄데 시스템 로케일(로캘?)이 한국어로 지정되어 있지 않은 운영체제에서 한글 UI가 ?로 죄다 깨진다거나 한글로 된 파일을 인식하지 못하는 프로그램은 처지가 참으로 안습하다. 한글 로케일에서도 상용 한자 4888자 이외의 한자를 인식할 수 없는 프로그램이라면 역시 무효임.
2. 64비트: 프로그램이 혼자서만 동작하는 EXE라면 32비트만 있어도 큰 상관이 없겠지만, 여타 프로세스 내부에서 동작하는 DLL(셸 확장, 훅, IME, 드라이버 등등)이라면 64비트 바이너리가 반드시 있어야 한다.
3. 멀티코어: 빡세게 많은 작업을 하는 프로그램이라면 요즈음의 컴퓨터에서 CPU를 최대 겨우 10~20%대밖에 안 쓰는 비효율적인 형태로 동작해서는 안 된다. 여러 코어가 작업을 어떻게 분담할지를 염두에 두고 프로그램이 개발되어야 한다.
4. 사용자 계정 컨트롤: Program Files 디렉터리 밑에다 개념 없이 사용자 데이터를 써 넣지 말며, XP 이하 OS에서는 신경 쓸 필요가 없던 권한 부족 에러가 제대로 처리되어야 한다. 레지스트리나 디렉터리가 redirection되는 일 없이 동작해야 한다.
5. 고해상도: 이제는 고해상도 모니터가 많이 보급되면서 종래의 100dpi가 아닌 120dpi 정도를 쓰는 빈도가 증가하고 있다. 이런 환경에서도 UI 화면은 적당하게 확대되어 나오거나 차라리 시종일관 동일한 픽셀 크기로 나오지, 글자가 깨지거나 GUI 요소가 들쭉날쭉 뒤죽박죽으로 배치되는 일은 없어야 한다.
이런 이슈들 중, 본인은 현재 5번을 주목하고 있다.
사실, 화면의 논리적 해상도를 바꾸는 건 엄청 옛날에 Windows 9x 시절부터도 있었던 기능이다. 하지만 그 당시는 화면 해상도가 겨우 800*600이나 1024*768이 고작이었기 때문에, 안 그래도 화면이 작아 죽겠는데 배율을 더 키우는 기능은 사실상 전혀 필요하지 않았다.
그러니 이건 정말 누가 쓰나 싶은 잉여로 전락했고, 수많은 프로그램들은 운영체제에 그냥 표준 해상도인 96dpi밖에 존재하지 않는 걸로 가정한 채 각종 좌표들을 하드코딩한 채로 개발되었다.
그랬는데 요즘 컴퓨터의 모니터들은 가로 해상도가 1500을 넘어가고 세로 해상도가 1000을 넘어가니, 이제는 화면을 좀 더 큼직하게 써도 되는 시대가 도래했다. 컴퓨터의 성능과 직접적인 관계가 있는 메모리와 CPU뿐만 아니라, 이런 디스플레이 기술의 발전도 컴퓨터의 발전에 큰 기여를 했음이 분명하다.
이제는 아이패드 같은 모바일 태블릿 기기조차 화면 해상도가 2000*1500을 넘어서 있다. 그러나 기술 발전을 아주 점진적으로 경험하여 legacy의 역사가 긴 PC 환경에서는, 고해상도를 고려하지 않고 설계된 프로그램들에게 재앙이 시작되었다. 논리 해상도에 따라 자동으로 크기가 조절되는 요소(시스템 글꼴 크기, 그리고 대화상자 크기)와 그렇지 않은 요소가 뒤섞이면 GUI 외형이 개판이 될 수밖에 없다.
현재 화면의 논리적 해상도는 데스크톱 화면의 DC를 얻어 온 뒤 GetDeviceCaps(hDC, LOGPIXELSX)를 하면 구할 수 있다. X뿐만 아니라 Y도 존재하는데, X축 값과 Y축 값이 서로 달라지는 경우는 (사실상) 없다고 생각하면 된다. 일반 배율인 100%일 때의 리턴값은 96이고, 125%일 때는 120이 돌아온다..
Windows에서 화면 DPI의 변경은 완전히 on-the-fly로 자유롭게 되는 작업은 아닌지라, 운영체제 재시작이나 최소한 로그오프가 필요한 이벤트이다. 그래서 그런지 Windows Vista는 전무후무하게 화면 DPI 변경을 '관리자 권한이 필요한 작업'으로 규정했었으나, 그 규제가 7 이후부터는 풀렸다. 또한, XP 이하의 버전은 100% (96dpi)보다 작은 값으로 변경하는 것도 가능했지만, Vista 이래로 더 작은 값으로는 지정 가능하지 않게 바뀌었다.
본인이 개발하는 <날개셋> 한글 입력기의 경우, 보조 입력 도구들은 옛날에 급조하느라 각종 버튼들의 좌표가 하드코딩되어 있었다. 다음 7.0 버전부터는 고해상도일 때는 전반적인 외형도 그에 비례해서 더 큼직하게 나오게 바뀔 예정이다.
하지만 편집기는 논리적 해상도에 관계없이 글자가 언제나 무조건 16*16 고정된 픽셀 크기로만 출력되며, 이것은 쉽게 개선되기 어려운 약점이다. 글꼴 자체는 16*16 비트맵만 쓰는 게 불가피하더라도, 고해상도에서는 그 상태 그대로 글자를 살짝 확대해서 찍어 주는 기능이 필요할 것 같다. 물론 anti-aliasing을 적용해서 부드럽게 확대해서 말이다.
고해상도 환경은 아이콘을 관리하는 것도 무척 까다롭게 만들었다. Windows 95/NT4 이전에는 아이콘은 오로지 32*32 크기밖에 없었는데 나중에 16*16 작은 크기가 추가되었다. 요즘은 그것도 모자라서 20*20이나 24*24 크기도 쓰이고 있다. 그래서 한 아이콘은 여러 크기의 아이콘 이미지들의 family 내지 컬렉션처럼 되었다고 본인이 예전 글에서 언급한 적이 있다.
예전엔 고해상도 모드에서 그냥 화면 왜곡을 감수하고라도 16*16 아이콘을 살짝 확대해서 보여주는 걸로 때웠지만, 이젠 안 그러고 20*20 크기용 아이콘도 직접 만들어 넣어 주는 셈이다.
사실 FM대로라면 운영체제가 사용하는 표준 아이콘 크기도 매번 GetSystemMetrics(SM_CXICON) 같은 식으로 쿼리를 해서 써야 고해상도 환경에서도 유연하게 대비를 할 수 있을 것이다. 하지만 맨날 봐 온 게 32나 16 같은 고정된 크기여서 하드코딩된 값을 쓰다가 나중에 그 코드를 고쳐야 하게 되면 대략 정신이 난감해질 수밖에 없다. 그리고 이것도 X값과 Y값이 서로 달라지는 일이 과연 존재할지 궁금하다.
그런데 문제는 Windows API는 아이콘이 여전히 단일 불변 크기만 있을 거라는 사상을 전제로 하고 설계되어 있다는 점이다.
HICON 은 여전히 그냥 단일 크기에 해당하는 아이콘 하나만을 나타내는 핸들이다. 즉, 한 아이콘 컬렉션 전체를 나타내는 자료형이 아니다. 그래서 LoadIcon이나 DrawIcon 같은 함수를 보면 아이콘의 크기를 받는 인자가 전혀 존재하지 않으며, 이 한계를 보완하는 LoadImage와 DrawIconEx 함수가 나중에 뒤늦게 추가되었음을 알 수 있다.
하지만 draw 기능은 몰라도 load 기능은 리소스 ID를 지정해 주면 그 ID가 가리키는 모든 크기의 아이콘을 다 로딩하게 하는 게 간편하지 않겠나 싶다. 그래서 draw 명령을 내리면, 원하는 크기와 가장 가까운 크기를 운영체제가 알아서 골라서 출력해 주는 것이다.
API의 기능이 그렇게 설계되었다면 윈도우 클래스를 등록할 때도 WNDCLASS에 이어서 굳이 작은 아이콘 핸들 hIconSm이 추가된 WNDCLASSEX 구조체가 번거롭게 또 만들어질 필요가 없었을 것이다. 그리고 응용 프로그램들이 고해상도용 아이콘을 지원하기도 훨씬 더 쉬워졌을 것이다. LoadIcon은 그냥 표준 크기 아이콘을 로딩하는 것만 지원하고, LoadImage는 아이콘을 로딩할 때 크기를 사용자가 일일이 지정해 줘야 하니 둘 다 불편한 구석이 좀 있다.
여담이지만, 응용 프로그램이나 운영체제별로 자신들이 설정하는 논리적 해상도는 제각기 좀 차이가 있다.
과거 도스용 아래아한글은 16*16 픽셀에 대응하는 글자가 10포인트였다. 그러나 Windows는 96dpi가 표준 해상도이며, 여기서는 12포인트가 16*16 크기이다.
한편, 맥 OS는 12포인트의 픽셀수가 Windows나 아래아한글보다 더 작다. 다시 맥 OS로 부팅해서 살펴보면 구체적인 비율을 알 수 있지만, 지금은 귀찮아서 생략.
이런 미묘한 문화 차이를 보면, FreeType API에서 FT_Set_Char_Size 함수에 굳이 상대 해상도 dpi값까지 인자로 받는 이유를 얼추 짐작할 수 있을 것이다. 번거롭지만 그런 것까지 다 수용할 수 있는 계층을 제공하기 위해서이다.
Posted by 사무엘