« Previous : 1 : ... 108 : 109 : 110 : 111 : 112 : 113 : 114 : 115 : 116 : ... 221 : Next »

서울대는 관악산 기슭에 있고 국민대는 북악산 기슭에 있는데, 난 정작 내가 적을 둔 학교 근처에 있는 산을 올라 본 적이 없었다. 그래서 하루 날을 잡아서 곧장 달려갔다.
3호선 독립문 역은 서대문 형무소를 관람하기 위해 예전에 방문한 적이 있었는데 이번엔 등산을 위해 한 번 더 방문했다.

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

독립문 역 주변의 공원 풍경은 대략 이렇다.

사용자 삽입 이미지

이것은 서대문 형무소의 뒤에서 인왕산 쪽을 바라보며 찍은 사진이다. 안산을 오르기 위해서는 이쪽으로 가야 한다. 형무소 뒤에는 "이 진아 기념 도서관"이 있다.

사용자 삽입 이미지

이 건물은 미국에 어학연수를 갔는데 거기서 교통사고로 죽은 딸을 기리기 위해, 유족이 재정을 후원하여 설립한 구립 도서관이다.
이 도서관을 지나면 등산로 계단이 나오는데 그 옆에는... 군부대가 있다.
이른 아침 7시 무렵에 여기를 지나니 군인들이 연병장에서 아침 점호를 하는 게 내려다 보였다. 우와..;;

사용자 삽입 이미지

안산은 능선만 도는 둘레길, 그리고 정상으로 향하는 암벽 등산로 등이 잘 닦여 있었다. 예전에 올랐던 인왕산이 저 멀리 저렇게 보인다. 아래에는 아파트와 한성 과학 고등학교가 있다.

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

높이 올라갈수록 아래에 내려다 보이는 것은 더욱 많아진다. 위의 사진에서는 나오지 않았지만 여기서도 저 멀리 내부순환로를 볼 수 있다.

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

안산의 정상에는 봉수대가 있다. 물론 조선 시대의 오리지널은 아니고, 나중에 레플리카를 만든 것이다.
봉수대란 통신 수단으로서 불 내지 연기를 피우던 곳이다. 물과는 아무 관계 없으니 '수'라는 음에 낚이지 말 것. 水 가 아니라 燧라는 아주 생소한 한자이다.

사용자 삽입 이미지

나는 왔던 길로 되돌아가지 않기 때문에 하산은 서쪽의 연세 대학교 방면으로 했다.
하산하는 길엔 '무악정'이라는 정자와 마주쳤다. 북악산에 팔각정이 있는 것처럼 이 산도 중턱에 이런 정자가 있더라.
이 외에도 안산에는 약수터가 많이 있었다. 하지만 이들의 수질은 대부분 음용 부적합 판정이 떨어져 있었다. 대장균이 검출됐다고 말이다.

안산은 정상까지 오르는 일부 암반 구간을 제외하면 대부분 길이 잘 닦여 있었다. 단, 일부 등산로는 군사 작전 지대라고 민간 등산객의 출입이 금지되기도 했다.
연세 대학교 쪽으로 계속 내려가다 보니 연대 신촌 캠퍼스의 최북단에 있는 강의동인 대우관(상경대학 건물) 주차장에 잘 착륙했다. 하산이 결과적으로 등교가 됐다. 본인은 학교에 들른 김에 오랜만에 연구실에서 볼일을 좀 보고 귀가했다.

북악산과 안산은 다음이나 네이버 같은 인터넷 지도에 등산로가 바로 표시되어 있지 않아서 지금까지 선뜻 갈 생각을 못 하고 있었다. 하지만 정작 근처의 지하철역에만 가면 등산로 안내는 곳곳에 아주 잘 돼 있다. 더구나 안산보다 더 낮은 산에도 등산/산책로가 표시되어 있기도 하다.
북악산이야 청와대와 너무 가까워 표시를 숨긴 것이겠지만 안산은.. 그 군부대 때문에 생략한 건가 싶은 생각이 든다. 아무튼, 안산 탐방도 재미있었다.

Posted by 사무엘

2016/06/08 08:37 2016/06/08 08:37
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1235

등산 답사기: 북악산 -- 下

북악산은 북한산보다 남쪽에 있는 산이긴 한데, 북악산 자체도 사실 내부에 분지가 있어서 북부와 남부라는 두 파트로 나뉘어 있다고 생각하면 편하다.
성곽이 둘러져 있고 가장 높은 정상이 있고 청와대를 배경으로 보이는 그 산은 남부이다. 그리고 남부의 서쪽에는 창의문 안내소가 있고, 동쪽에는 말바위 안내소가 있어서 등산객들을 통제한다. 남부에 입산하려면 신분증을 제시하고 번호표 목걸이를 받아야 한다.

그 반면, 숙정문으로 나가서 움푹 파인 분지를 향해 내려가면 삼청각이 보이고, 숙정문 안내소에서 또 목걸이를 받거나 반납할 수 있다. 팔각정을 비롯해 북악산의 주요 관광지는 사실 북악산의 북부에 있다. 북부는 어차피 청와대가 보이지도 않으며, 목걸이 통제 구역이 아니다. 난 이 사실을 뒤늦게 깨달았다. 항공/위성 지도로도 지면의 고도는 거의 짐작할 수 없으므로.
지난번에 북악산을 수평 횡단했을 때는 북악산의 이런 지형적 특성을 모두 이해하지 못하고 남부를 반쪽짜리만 구경했던 관계로, 이번에는 북악산을 수직 종단하면서 나머지 구간을 마저 구경했다.

사용자 삽입 이미지

먼저, 북악산 남부에 진입도 예전에 다녀갔던 창의문 내지 와룡 공원이 아니라, 삼청 공원에서 했다. 위의 사진은 삼청동 골목길의 모습이다. 이로써 청와대의 왼쪽과 오른쪽 주변을 골고루 답사해 보게 됐다. 여기는 서울 도심과 가깝고 데이트 코스로 좋지만, 딱 봐도 차 세울 만한 곳은 없게 생겼다. 자차를 갖고 방문하기는 곤란하다.

내가 내린 버스 정류장은 '삼청공원 입구'와 '교육과정 평가원'이라는 명칭이 뒤섞여 쓰이고 있었다. 한국 교육과정 평가원이 한때 여기 근처에 있었지만, 지난 2010년에 이전했기 때문이다.

사용자 삽입 이미지

북악산을 오르는 자동차 도로는 늘 그렇듯이 청와대 쪽은 철망이 몇 겹으로 둘러져 있다.
창의문에서 정상으로 오를 때는 주변에 차도가 없이 가파른 경사를 계단으로 오르느라 정신 없었다. 그러니 이런 광경을 딱히 볼 일이 없었다.

사용자 삽입 이미지

이제부터 시멘트 오르막길이 끝나고 등산로가 나왔다. 성곽 둘레길보다는 인위적인 느낌이 덜한 비탈길을 오른 뒤, 지난번에 들렀던 성곽 둘레길과 합류를 했다.

사용자 삽입 이미지

드디어 숙정문을 나서서 북악산의 남부에서 북부로 건너가기 시작했다.
길이 어떻게 되느냐 하면, 그냥 앞만 보고 쭈욱 올라서 팔각정으로 갈 수도 있고, 중간에 성북천 발원지라는 지점에서 오른쪽으로 꺾어서 더 길고 험한 등산로를 타고 동쪽으로 갈 수도 있다.
후자는 제2 산책로인데, 요게 일명 '김 신조 루트'이다. 그 시절에 남파된 북한 무장공비들이 청와대로 침투할 때 이용한 경로라고 해서..

사용자 삽입 이미지

김 신조 루트는.. 뭐 그렇게까지 특별한 게 있지는 않았다. 이런 식으로 길이 쭉 이어졌다.

사용자 삽입 이미지

북악산의 북부를 오르면서 이전에 지나 온 남부를 바라본 모습이다. 서울 성곽이 쭉 둘러져 있는 게 보인다.

사용자 삽입 이미지

이것은 '호경암'이라는 바위이다. 성곽 둘레길에는 1· 21 사태 교전 때 총알이 박힌 소나무가 있더니만, 여기는 총알이 박힌 바위가 있었다.
그 시절에 단순히 시가전뿐만 아니라, 도주한 무장공비를 소탕하기 위해 산 속에서 치열한 교전이 벌어졌음을 알 수 있다.

사용자 삽입 이미지

하늘마루 전망대에 도착했다. 내부순환로, 국민 대학교, 평창동 등이 모두 보이고 경치가 아주 좋았다. 산꼭대기에까지 무슨 건물을 어떻게 지었는지, 근처에는 사람이 거주 가능한 것으로 보이는 군사 시설도 있었다.

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

하산 예정 지점인 국민 대학교 인근과, 다른 방향인 평창동의 모습이다.

사용자 삽입 이미지

전망대에서 더 진행한 끝에, 드디어 '하늘교'라고 불리는 하얀 다리에 도달했다. 북악산과 북한산을 연결하는 통로이다.

사용자 삽입 이미지

아래로는 자동차 도로가 있다. 이 등산로 위에서 도로 쪽으로 오르내리는 통로는 일단은 주변에 보이지 않았다.
여기서도 차도를 따라 팔각정으로 가는 길이 있었다. 하지만 본인은 그쪽으로 가지 않고 북한산, 국민대 방면으로 진행하여 북악산을 하산했다.
개인적으로 북한산 팔각정은 교회 친구들과 함께 차를 끌고 가 본 적이 있다. 하지만 밤이어서 전망이 제대로 보이지 않으며, 사람들로 바글바글하고 정신없기까지 한 때 간 것이어서 딱히 등산 기분은 못 냈다.

가는 길목에는 뭔가 호국 불교 냄새가 물씬 풍기는 '여래사'라는 절이 있었다. 그리고 한참을 더 내려간 끝에..

사용자 삽입 이미지

지난번엔 와룡공원 쪽으로 하산하면서 성균관 대학교를 봤는데, 이번에는 더 외곽에 있는 국민 대학교를 처음으로 구경했다. 오오!
국민 대학교 건물은 가끔 내부순환로를 차로 달릴 일이 있을 때 가끔 보긴 했다. 내부순환로는 '정릉 터널'을 통해 북악산을 횡단하는데, 그 옆엔 '북악 터널'이라는 도로와 터널이 더 있었다.

그리고 여기는 북악산과 북한산이 만나는 곳이다 보니 북한산 등산로도 근처에 있었다. 노래에 메들리가 있는 것처럼 시간과 체력이 허락하는 사람이라면 이런 식으로 하루 종일 산을 몇 콤보로 오를 수도 있겠다. 하지만 본인은 거기까지는 차마 하지 않고 돌아왔다.

앞으로 등산 이야기가 좀 더 올라올 듯하다. 이러다 내 블로그가 프로그래밍 블로그에서 여행· 등산 블로그로 성향이 바뀌는 건 아닌가 모르겠네..;;
북악산과 북한산 사이에 저런 길이 있는데, 사실은 서울 완전 북쪽 끝에 북한산과 도봉산의 경계엔 '우이령'이라는 고갯길이 있다. 거기도 안보상의 이유 때문에 거의 40년 동안 민간인 출입이 금지돼 있다가 2010년 무렵에 금지가 풀렸고, 지금도 신분증 지참에 "예약 + 하루 통행 인원수 제한"까지.. 북악산보다도 더 까다로운 제약이 남아 있다. 조만간 거기도 가 볼 생각이다.

Posted by 사무엘

2016/06/05 08:31 2016/06/05 08:31
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1234

1. C++의 new/delete 연산자

C++의 new와 delete 연산자에 대해서는 먼 옛날에 한번 글을 쓴 적이 있고,  연산자 오버로딩에 대해서 글을 쓸 때도 다룬 적이 있다.
new/delete 연산자는 메모리를 할당하고 해제하는 부분만 따로 떼어내서 operator new / opertor delete라는 함수를 내부적으로 호출하는 형태이며, 이건 클래스별로 오버로딩도 가능하다. 그리고 객체 하나에 대해서만 소멸자를 호출하는 일명 스칼라 new/delete와, 메모리 내부에 객체가 몇 개 있는지를 따로 관리하는 벡터 new[]/delete[]가 구분되어 있다는 점이 흥미롭다.

new는 메모리 할당이 실패할 경우 한 1990년대까지는 NULL을 되돌렸지만 요즘은 예외를 되돌리는 게 malloc과는 다른 점이라고 한다. 하긴, 요즘 세상에 메모리 할당 결과를 무슨 파일 열기처럼 일일이 NULL 체크하는 건 굉장히 남사스럽긴 하다.

1980년대의 완전 초창기, 한 터보 C++ 1.0 시절에는 벡터 delete의 경우, 원소 개수를 수동으로 써 주기까지 해야 했다고 한다. pt = new X[3] 다음에는 delete[3] pt처럼. 안 그래도 가비지 컬렉터도 없는데, 이건 너무 불편한 정도를 넘어 객체지향 언어의 기본적인 본분(?)조차 안 갖춰진 막장 행태로 여겨진지라 곧 시정됐다. 객체의 개수 정도는 언어 차원에서 메모리 내부에다 자동으로 관리하도록 말이다.

그런데 스칼라이건 벡터이건 메모리를 n바이트 할당하거나 해제하는 동작 자체는 서로 아무 차이가 없는데 operator new/delete와 operator new[]/delete[]가 따로 존재하는 이유는 난 여전히 잘 모르겠다.

new char[100]을 하면 operator new(100)이 호출되고, 생성자와 소멸자가 있는 new TwentyFour_byte_object[4]를 호출하면 x86 기준으로 24*4+4인 operator new[](100)이 호출된다.
operator new[]라고 해서 딱히 내가 할당해 준 메모리에 저장되는 객체의 개수나 크기를 알 수 있는 것도 아니다. 단지, new[]의 경우 내가 되돌려 준 메모리 바로 그 지점에 객체가 바로 저장되지는 않는다는 차이가 존재할 뿐이다. 맨 앞에는 오브젝트의 개수 4가 저장되기 때문.

즉 다시 말해 벡터 new[]는 operator new[]가 되돌린 포인터 값과, new operator[]를 호출한 호스트 쪽에서 받는 포인터 값에 미묘하게 차이가 생기며 서로 일치하지 않게 된다. 마치 다중 상속으로 인해서 this 포인터가 보정되는 것처럼 말이다.
그래도 스칼라/벡터 처리는 operator new/delete가 전혀 신경 쓸 필요가 없는 영역이며, 여전히 new/delete operator가 자동으로 하는 일일 뿐인데 그것 때문에 메모리 할당 계층 자체가 둘로 구분되어야 할 필요가 있는지는 여전히 개인적으로 의문이다.

그리고 하나 더.
operator new/delete는 오버로딩이 가능하다고 아까 얘기했었다.
global scope에서 오버로딩을 해서 오브젝트 전체의 메모리 할당 방식을 바꿀 수 있으며, new의 경우 추가적인 인자를 집어넣어서 placement new 같은 걸 만들 수도 있다. "메모리 할당에 대한 답은 정해져 있으니 너는 저 자리에다가 생성자만 호출해 주면 된다"처럼.. (근데 new와는 달리 delete는 왜 그게 가능하지 않은지 모르겠다만..)

global scope의 경우, Visual C++에서는 operator new/delete 하나만 오버로딩을 해도 new[], delete[] 같은 배열 선언까지도 메모리 할당과 해제는 저 new/delete 함수로 자동으로 넘어간다. 물론 new[]/delete[]까지 오버로딩을 하면 스칼라와 벡터의 메모리 요청 방식이 제각기 따로 놀게 된다.

그러나 클래스는 operator new/delete 하나만 오버로딩을 하면 그 개체의 배열에 대한 할당과 해제는 그 함수로 가지 않고 global 차원의 operator new[]/delete[]로 넘어간다.
이것도 표준에 규정된 동작 방식인지는 잘 모르겠다. 결정적으로 xcode에서는 global도 클래스일 때와 동일하게 동작하여 스칼라와 벡터 사이의 유도리가 동작하지 않았다.
메모리 할당이라는 기본적인 주제를 갖고도 C++은 내부 사연이 무척 복잡하다는 걸 알 수 있다.

2. trigraph

아래와 같은 코드는 보기와는 달리 컴파일되는 올바른 C/C++ 코드이다. 그리고 Foo()를 호출하면 화면에는 What| 이라는 문자열이 찍힌다.

void Foo()
??<
    printf( "What??!\n" );
??>

그 이유는 C/C++엔 trigraph라는 문자열 치환 규칙이 '일단' 표준으로 정의돼 있기 때문이다.
아스키 코드에서 Z 뒤에 나오는 4개의 글자 [ \ ] ^ 와, z 뒤에 나오는 4개의 글자 { | } ~, 그리고 #까지 총 9개의 글자는 ?? 로 시작하는 탈출문자를 통해 등가로 입력 가능하다.
이런 치환은 전처리기 차원에서 수행되는데, #define 매크로 치환과는 달리 일반 영역과 문자열 리터럴 안을 가리지 않고 무조건 수행된다. 그래서 문자열 리터럴 안에서 연속된 ?? 자체를 표현하려면 일부 ?를 \? 로 구분해 줘야 한다.

이런 게 들어간 이유엔 물론 까마득히 먼 역사적인 배경이 있다. 천공 카드던가 뭐던가, 저 문자를 한 글자 형태로 입력할 수 없는 프로그래밍 환경에서도 C언어를 지원하게 하기 위해서이다. 1950~70년대 컴퓨팅 환경을 겪은 적이 없는 본인 같은 사람으로서는 전혀 이해할 수 없는 환경이지만 말이다.
C(와 이거 호환성을 계승한 C++도)는 그만치 오래 된 옛날 레거시 언어인 것이다. 그리고 C는 그렇게도 암호 같은 기호 연산자들을 많이 제공하는 언어이지만 $ @처럼 전혀 사용하지 않는 문자도 여전히 있다.

오늘날 PC 기반 프로그래밍 환경에서 저런 trigraph는 전혀 필요 없어진 지 오래다. 그래서 Visual C++도 2008까지는 저걸 기본 지원했지만 2010부터는 '기본 지원하지는 않게' 바뀌었다. 이제 저 코드는 기본 옵션으로는 컴파일되지 않는다. /Zc:trigraphs 옵션을 추가로 지정해 줘야 한다.

C/C++ 코드를 가볍게 구문 분석해서 함수 블록 영역이나 변수 같은 걸 표시하는 IDE 엔진들은 대부분이 trigraph까지 고려해서 만들어지지는 않았다. 그러니 trigraph는 IDE가 사용하는 가벼운 컴파일러들을 교란시키고 혼동시킨다. 한편으로 이 테크닉은 소스 코드를 의도적으로 괴상하게 바꾸는 게 목표인 IOCCC 같은 데서는 오늘날까지 유용하게 쓰인다. 함수 선언을 void foo(a) int a; { } 이렇게 하는 게 옛날 원래의 K&R 스타일이었다고 하는데 그것만큼이나 trigraph도 옛날 유물이다.

차기 C/C++ 표준에서는 trigraph를 제거하자는 의견이 표준 위원회에서 제안되었다. 그런데 여기에 IBM이 적극적인 반대표를 던진 일화는 유명하다. 도대체 얼마나 케케묵은 옛날 코드들에 파묻혀 있으면 '지금은 곤란하다' 상태인지 궁금할 따름이다. 하지만 IBM 혼자서 대세를 거스르는 게 가능할지 역시 의문이다.

3. Visual C++ 2015의 CRT 리팩터링

도스 내지 16비트 시절에는 C/C++ 라이브러리를 DLL로 공유한다는 개념이 딱히 없었던 것 같다. 다음과 같은 이유에서다.

  • 도스의 경우, 근본적으로 DLL이나 덧실행 같은 걸 쉽게 운용할 수 있는 운영체제가 아니며,
  • 메모리 모델이 small부터 large, huge까지 다양하게 존재해서 코드를 한 기준으로 맞추기가 힘들고,
  • 옛날에는 C/C++ 라이브러리가 딱히 공유해야 할 정도로 덩치가 크지 않았음.
  • 예전 글에서 살펴 보았듯이, 16비트 Windows 시절엔 DLL이 각 프로세스마다 자신만의 고유한 기억장소를 갖고 있지도 않았음. 그러니 범시스템적인 DLL을 만드는 게 더욱 까다롭고 열악했다.

모든 프로세스들이 단일 주소 공간에서 돌아가긴 했겠지만, small/tiny 같은 64K 나부랭이 메모리 모델이 아닌 이상, sprintf 하나 호출을 위해서 코드/세그먼트 레지스터 값을 DLL 문맥으로 재설정을 해야 했을 것이고 그게 일종의 썽킹 오버헤드와 별 차이가 없었지 싶다. 마치 콜백 함수를 호출할 때처럼 말이다. 이러느니 그냥 해당 코드를 static link 하고 만다.

그 반면 32비트 운영체제인 Windows NT는 처음부터 CRT DLL을 갖춘 상태로 설계되었고, 그 개념이 Visual C++을 거쳐 Windows 9x에도 전래되었다. 1세대는 crtdll, msvcrt10/20/40이 난립하던 시절이고 2세대는 Visual C++ 4.2부터 6까지 사용되던 msvcrt, 그리고 3세대는 닷넷 이후로 msvcr71부터 msvcr120 (VC++ 2013)이다. 2005와 2008 (msvcr80과 90)은 잠시 매니페스트를 사용하기도 했으나 2010부터는 그 정책이 철회됐다.

그런데 매니페스트를 안 쓰다 보니 Visual C++의 버전이 올라갈 때마다 운영체제의 시스템 디렉터리는 온갖 msvcr??? DLL로 범람하는 폐단이 생겼고, 이에 대한 조치를 취해야 했다. C/C++ 라이브러리라는 게 생각보다 자주 바뀌면서 내부 바이너리 차원에서의 호환성이 종종 깨지곤 했다. 이런 변화는 함수 이름만 달랑 내놓으면 되는 C보다는 C++ 라이브러리 쪽이 더 심했다.

그 결과 Visual C++ 2015와 Windows 10에서는 앞으로 변할 일이 없는 인터페이스 부분과, 내부 바이너리 계층을 따로 분리하여 CRT DLL을 전면 리팩터링을 했다. 본인은 아직 이들 운영체제와 개발툴을 써 보지 않아서 자세한 건 모르겠는데 더 구체적인 내역을 살펴봐야겠다.

사실 C++ 라이브러리는 대부분의 인터페이스가 템플릿 형태이기 때문에 코드들이 전부 해당 바이너리에 static 링크된다. 하지만 그래도 모든 코드가 static인 건 아니다. 메모리 할당 내지 특정 타입에 대한 템플릿 specialization은 여전히 DLL 링크가 가능하다.
C++ 라이브러리가 어떤 식으로 DLL 링크되는지는 마치 함수 타입 decoration 방식만큼이나 그야말로 표준이 없고 구현체마다 제각각인 춘추전국시대의 영역이지 싶다.

4. Windows의 고해상도 DPI 관련 API

요즘이야 컴퓨터 화면의 해상도가 PC와 모바일을 가리지 않고 워낙 높아져서 프로그램의 UI 요소나 각종 아이콘, 그래픽도 크기 조절에 유연하게 대처 가능하게 만드는 게 필수 조건이 됐다. 폰트의 경우 저해상도에 최적화된 힌팅이 필요 없어질 거라는 전망까지 나온 지 오래다.
그러나 태초에 컴퓨터, 특히 IBM 호환 PC라는 건 텍스트 모드만 있다가 그래픽 모드라는 게 나중에 추가됐다. 그것도 그래픽 모드는 320*200이라는 막장급의 낮은 해상도에 4색짜리인 CGA에서 첫 시작을 했다.

시작은 심히 미약했다. 이런 저해상도 저성능 컴퓨터에서는 쑤제 도트 노가다로 최적화된 그래픽이나 비트맵 글꼴이 속도와 메모리 면에서 모두 우월했기 때문에 그게 세상을 평정했다.
그러나 컴퓨터 화면이 커지고 해상도가 크게 올라가면서 단순히 픽셀보다 더 고차원적인 단위를 도입할 필요가 생겼다. 물론 예나 지금이나 메뉴와 아이콘, 프로그램 제목 표시줄의 글자 크기는 제어판에서 간단히 고칠 수 있었지만 영향을 받는 건 오로지 그것뿐. 대화상자 같은 다른 요소들의 크기는 변하지 않았다.

그 고차원적인 단위를 일명 시스템 DPI라고 부른다.
평소에야 이 단위는 언제나 관례적으로 100%로 맞춰져 있었으며, 이게 125나 150% 같은 큰 값으로 맞춰져 있으면 응용 프로그램은 창이나 글자의 크기도 원칙적으로는 이에 비례해서 키워서 출력해야 한다.

대화상자는 픽셀이 아니라 내부적으로 DLU라는 추상적인 단위를 사용해서 컨트롤들을 배치하며 이 단위는 시스템 DPI를 이미 반영하여 산정된다. 하지만 CreateWindowEx를 써서 픽셀 단위로 컨트롤을 수동으로 생성하는 코드들이 이런 시스템 DPI를 고려하지 않고 동작한다면 프로그램의 외형이 많이 이상하게 찍히게 된다.

여기까지가 Windows 95부터 8까지 오랫동안 지속된 프로그래밍 트렌드이다. 시스템 DPI는 단순히 메뉴와 아이콘의 글자 크기와는 달리 운영체제 전체에 끼치는 여파가 매우 크다. 이건 값을 변경하려면 운영체제를 재시작하거나 최소한 모든 프로그램을 종료하고 현 사용자가 로그인을 다시 해야 했다.

시스템 DPI라는 개념 자체에 대한 대비가 안 된 프로그램도 널렸는데, 응용 프로그램들이 시스템 DPI의 실시간 변화에까지 대비하고 있기를 바라는 건 좀 무리였기 때문이다. 시스템 메트릭이 싹 바뀌기 때문에 이미 만들어져 있는 윈도우들이 다 재배치돼야 할 것이고 후유증이 너무 크다.

그런데 지난 Windows 8.1은 이 시스템 DPI에 대해서 또 어마어마한 손질을 가했다.
간단히 결론부터 말하자면 사용자가 재부팅 없이도 DPI를 막 변경할 수 있게 했다. 실행 중에 DPI가 변경되면 WM_DPICHANGED라는 새로운 메시지가 온다. 그리고 응용 프로그램은 자신이 실시간 DPI 변경에 대응 가능한지 여부를 운영체제에 별도의 API 내지 매니페스트 정보를 통해 지정 가능하게 했다.

DPI 변경에 대응 가능하지 않은 레거시 프로그램들은 시스템 DPI가 바뀌었는지 알지도 못하고 virtualize된 샌드박스 속에서 지낸다. DPI가 150%로 바뀌면서 사용자의 화면에 보이는 창 크기가 100에서 150으로 늘었지만, 응용 프로그램은 여전히 자신의 최대 크기가 100인줄로 안다. 그래서 100*100 크기로 그림을 찍으면 그건 운영체제에 의해 1.5배 비트맵 차원에서 크게 확대되어 출력된다.

그 프로그램은 처음부터 시스템이 150% DPI인 것을 알았으면 그에 맞춰 실행되었을 수도 있다. 그러나 실행 중의 DPI 변경까지 예상하지는 못하며, 그런 API가 도입되기 전에 개발되었기 때문에 운영체제가 그래픽 카드의 성능을 활용하여 그런 보정을 해 주는 것이다.
물론 이렇게 확대된 결과는 계단 현상만 뿌옇게 보정된 채 출력되기 때문에 화질이 좋지 못하다. 응용 프로그램이 고해상도 DPI 변화를 인식하여 직접 150*150으로 최적화된 그림을 다시 그리는 게 바람직하다.

그리고 시스템 DPI는 제어판 설정의 변경을 통해서만 바뀌는 게 아니다.
Windows 8.1부터는 모니터별로 시스템 DPI를 다르게 지정할 수 있다. 그래서 100%(96dpi)짜리 모니터에서 돌아가고 있던 프로그램 창을 125%(120dpi)짜리 커다란 모니터로 옮기면 거기서는 동일 프로그램이 그 DPI에 맞춰서 동작해야 한다. 물론 DPI가 바뀌었다는 메시지는 운영체제가 보내 준다.

이렇듯, 응용 프로그램은 처음에는 (1) 고해상도 DPI를 인식할 것만이 요구되었다가 나중에는 (2) 실행 중에 DPI가 변경되는 것에도 대비가 되어야 하는 것으로 요구 조건이 추가되었다.
옛날에는 시스템 전체의 화면 해상도나 색상수를 재부팅 없이 실시간으로 바꾸는 것도 보통일이 아니었는데 이제는 DPI의 변경도 그 범주에 속하게 되었다.

재부팅이 필요하다는 이유 때문에 그런지 Windows Vista는 전무후무하게 DPI의 변경에 마치 시스템의 시각 변경처럼 '관리자 권한' 딱지가 붙어 있기도 했는데 이것도 참 격세지감이다.

Posted by 사무엘

2016/06/02 08:32 2016/06/02 08:32
, , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1233

등산 답사기: 북악산 -- 上

한동안 너무 바빴던 나머지, 남한산성 이후 다음 등산 때까지 블로그에 다른 글을 올릴 시간이 거의 없었다.
그래도 이번에도 아주 흥미진진한 산행을 다녀왔다. 이번에 간 곳은 청와대 뒷산인 북악산이었다.

북악산은 자명한 이유로 인해, 서울에 있는 산들 중 아마 유일하게 신분증 까고 번호표 목걸이를 해야 입산 가능한 산이지 싶다. 인왕산은 사진 찍는 걸 감시하는 초소만 있던데 북악산은 그에 덧붙여서 저런 절차도 필요하다.

인왕산과 북악산은 빨간 날의(일요일 + 공휴일) 다음 날은 입산 금지이다. 감시 초소 직원들도 한 주에 하루 정도는 출근 안 하고 쉬어야 할 테니까. 북악산은 거기에다 아침 9시부터 오후 3시까지 입산 가능 시각도 정해져 있다. 현재 북악산에 있는 사람들의 신원이 모두 파악돼 있어야 하며, 해가 떨어진 뒤에는 산 속에 아무도 없게 마치 민통선에 준하는 수준의 관리를 하는 듯하다.

인왕산은 감시 초소는 있지만 저 정도까지 등산객들을 일일이 파악하고 통제하지는 않는다. 그도 그럴 것이, 해가 지고 나면 어차피 청와대 쪽으로 사진 찍는 것 감시는 할 필요가 없어지니 말이다.

사실, 청와대 근처에 있는 산들에 우리가 이 정도라도 접근하여 등산을 할 수 있게 된 건 생각보다 오래 되지 않았다.
21세기 이전엔 그런 거 없었다. 1968년 1월에 북한 무장공비가 청와대 바로 근처까지 쳐들어왔던 전대미문의 사건의 여파로 인해, 북악산과 그 일대의 산들은 민간인 접근 절대엄금으로 봉인돼 버렸기 때문이다.

서울 지리를 잘 모르던 시절에는 난 북한산과 북악산의 차이도 잘 몰랐다. 북악산은 북한산보다 훨씬 서울 중심부 안에 있다. 본인은 북악산을 오르기 위해 무작정 '창의문'으로 향했다. 예전에 인왕산을 올랐다가 돌아오면서 버스 차창 밖으로 스쳐 지나쳤던 곳이다.

사용자 삽입 이미지

창의문의 바로 옆에 있는 최 규식 경무관의 동상을 가까이에서 다시 접했다.

그는 용감한 정의인으로 종로 경찰서장에 재직 중, 1968년 1월 21일 청와대를 습격하여 오는 공산 유격대와 싸우다가 장렬하게도 전사하므로 정부는 경무관의 계급과 태극 무공 훈장을 내렸다.
비록 한때의 비극 속에서 육신의 생명은 짧았으나 의를 위하는 그의 정신은 영원히 살아 남으리라.
1969년 1월 21일
조각 및 제작: 이 일영
글: 이 은상
글씨: 김 충현


알고 보니 저 동상은 고인의 순직 1주기를 기념해서 만들어졌다.
태극 무공 훈장은 우리나라의 무공 훈장 중 최상위 등급으로, 이 정도 훈장은 6· 25 전쟁에서 나라를 구한 급의 영웅이 아니면 살아서는 못 받는다고 생각하면 된다. 또한 군인이 아닌 경찰에게 이런 훈장이 추서된 사례도 현재까지 저분만이 유일하다.
바로 몇 년 전(1965), 강 재구 소령이 수류탄 투척 훈련 중에 부하가 실수로 떨어뜨린 수류탄을 몸으로 감싸고 산화하여 동일한 태극 무공 훈장이 추서됐다는 것도 기억해 두면 좋다.

사용자 삽입 이미지

북악산을 오르면서 작년에 갔던 인왕산과 부암동 쪽을 본 모습이다. 인왕산과 북악산은 모두 산 속에 성곽과 감시 초소가 있고, 아예 군부대도 있다.

사용자 삽입 이미지

산을 오르는 길은 성곽을 따라 대략 이런 형태였다. 이 사진에는 보이지 않지만 성벽 너머로는 철조망이 둘러져 있다.
계단을 따라 산을 오를 수 있었는데, 경사가 꽤 가파른 편이었다.

사용자 삽입 이미지

북악산 주변은 경치가 이러했다.
우리가 평소에 서울 시내 쪽에서 바라보는 북악산의 전면은 바위가 참 인상적이다. 하지만 지금 여기는 이미 북악산의 뒤쪽으로 가는 것이고, 산을 타면서 딱히 그런 바위를 볼 일은 별로 없었다. 앞쪽은 영구 봉인돼 있으니 말이다.

사용자 삽입 이미지

저기가 바로 북악산과 북한산 사이에 조성된 마을인 평창동이다. 각종 고급 카페와 레스토랑, 그리고 부자· 유명인사들이 사는 단독 주택들이 가득하여 마치 서울 안의 딴 세상 같다. 교통이 왕창 불편하겠지만, 다들 차를 끌고 다닐 테니 별 문제가 되지 않을 것이다.

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

북악산의 정상은 생각보다 금방 도달할 수 있었다. '북악산'이 한때는 '백악산'이라고도 불렸다. 창의문에서 북악산 정상까지는 지도상의 직선 거리가 짧은 만큼 경사가 굉장히 급하다.

사용자 삽입 이미지

1· 21 사태 때 북한군과의 교전 중에 총알이 박힌 소나무라고 한다. 그런데 일부러 저렇게 표시를 해 놓은 게 좀 징그럽게 보인다.

사용자 삽입 이미지

성곽을 따라 가다가 '청운대'라고 불리는 다른 봉우리에도 도달했다.

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

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

그 뒤 걷는 길은 성곽 안에 있기도 하다가 성 밖으로 나가기도 했다. 철조망이 저렇게 있으니 무슨 GOP 철책처럼 보였다.
이거 사진이 도대체 어떻게 찍혔는지 광량 조절이 이상하게 됐다. -_-;;;

사용자 삽입 이미지

정상을 도착한 뒤에 지금까지 걸어 온 길이 저렇다.

사용자 삽입 이미지

그리고 '숙정문'이라고 불리는 대문에 도착했다. 나름 사대문 중 하나이며 '북대문'에 해당하는 대문이다. 얼마 전에 남한산성을 본 적이 있다 보니 모습이 친근했다.
본인은 조선 시대에 있었던 서울 성곽과 '대문'에 대해서 지금까지 진지하게 생각해 본 적이 없었는데 이제야 좀 개념이 생겼다.
남대문은 서울 역 근처에 있는 그 숭례문이고, 동대문은 국도 6호선상에 있는 그 흥인지문이다.

서대문(돈의문)은 서울 지하철 5호선 서대문 역 근처에 있긴 했지만 일제 강점기 때 헐려서 현재 전해지지 않는다. 옛날엔 노면 전차가 이 문을 통과했는데, 전차 노선을 복선화하려다 보니 이 성곽이 걸림돌이 됐다고.. 얘는 사대문 중 유일하게 복원이 못 되고 2016년 현재 존재하지 않는 문이다.

마지막으로 북대문이 바로 저 숙정문이지만, 높은 산 속에 있는 관계로 다른 문들만치 유명하거나 사람들이 막 드나들지는 않았다고 한다. 쉽게 말해 존재감이 별로 없다. 남대문하고는 접근성이 가히 넘사벽급으로 차이가 나지 않은가..;;

사용자 삽입 이미지

난 처음에는 창의문에서 숙정문, 와룡 공원까지 북악산을 성벽을 따라 수평으로 횡단하는 코스를 생각하고 왔다.
차를 이용해서 북악산을 오르면 아까 같은 정상으로는 못 가지만, 그래도 성벽 둘레길보다 높은 곳으로 가서 '팔각정'이라고 불리는 정자에 도달할 수 있다.

그러면 도보 등산로와 자동차 길은 서로 완전히 분리되어 있느냐 하면 그렇지 않다.
창의문과 와룡 공원 사이에, 청와대와 더 가까운 지점에 '삼청 공원'이 있고 거기에도 북악산 숙정문을 경유하여 팔각정까지 가는 등산로가 있다. 이건 북악산을 횡단이 아니라 종단하는 코스인 셈이다.

북악산에는 일명 '김 신조 루트'도 있고 북한산 형제봉과 연결되는 '하늘다리'도 있는데 거기로 가려면 숙정문의 밖으로 나가서 서울 성곽보다 훨씬 더 북쪽으로 계속 올라가야 한다.
위의 사진은 그 종단 등산로를 위에서 내려다보면서 찍은 것이다. 이 등산로는 나중에 북악산에 다시 와서 개척하게 됐다.

사용자 삽입 이미지

건물이 이 정도로 보이기 시작하니 이번 등산도 거의 끝이 난 것 같다. 옛날에는 저기도 다 산이었을 텐데 산중턱까지 다 개발되고 도로가 생기고 길이 닦인 것이다.

정작 와룡 공원에는 가 보니 별 거 없었다. 공 병우 박사가 운영하던 한글 문화원의 소재지가 와룡동이었던 걸로 기억한다.
여기서는 마을 버스를 타고 지하철역으로 가면서 지금까지 말로만 듣던 성균관 대학교 서울 캠퍼스, 감사원, 통일부 같은 건물들을 구경할 수 있었다. 등산을 하면서 서울에 이런 곳도 있다는 걸 알아 가는 건 즐거운 일이다.

안국 역과 혜화 역이 지리상으로는 생각보다 굉장히 가까이 있다는 걸 처음 알았다.

Posted by 사무엘

2016/05/30 08:26 2016/05/30 08:26
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1232

Windows에서 C/C++ 언어로 EXE를 만들 때는 시작점으로 WinMain이라는 함수가 쓰인다.
얘는 먼 옛날 16비트 시절과, 지금의 32/64비트 사이에 바뀐 게 거의 없다. HINSTANCE hInst, HINSTANCE hPrevInst, PSTR pszCmdLine, int nCmdShow 라는 네 종류의 인자 중에서 32비트로 오면서 바뀐 것은 hPrevInst이 언제나 NULL이라는 것밖에 없다. 그것도 과거에는 복잡하던 게 더 간결해진 변화이기 때문에 실질적으로 신경 쓸 필요가 없다.

옛날 16비트 시절에 HINSTANCE는 파일 차원에서 동일한 프로그램이 중복 실행되었을 때 각 실행 문맥을 구분하는 일종의 메모리 번호표였다. 한 프로그램이 완전히 처음 실행될 때는 hPrevInst가 NULL인데 두 번째 실행되면, 먼저 실행된 프로그램이 받았던 hInstance가 다음 인스턴스의 WinMain 함수에서 hPrevInst로 전달되고..
세 번째 중첩 실행되면 아까 그 두 번째 프로그램의 신규 핸들이 거기의 hPrevInst로 전달되는 형태였다. 단일 방향 연결 리스트의 head 노드 같은 느낌이다.
자기 자신 말고는 주변에 무엇이 있는지 일부러 특수한 API를 써서 조회를 하지 않으면 도무지 알 수 없는 32비트 이상 보호 모드에서는 정말 상상하기 힘든 관행이다.

EXE는 그렇고 그럼 DLL은 어떨까? DllMain이라는 기본적인 형태는 동일하지만 16비트 시절에는 아무래도 멀티스레드 같은 건 존재하지 않았으니까 DLL_PROCESS_(ATTACH/DETACH)만 있었고, 나중에 DLL_THREAD_*가 추가된 정도일까?

사실은 그렇지 않다.
옛날에는 BOOL DllMain(HINSTANCE hInst, DWORD fdwReason, PVOID pReserved)라는 형태의 함수 자체가 없었다.
그 대신 완전히 다른 int FAR PASCAL LibMain(HANDLE hInst, WORD wDataSeg, WORD wHeapSize, LPSTR lpszCmdLine) 라는 함수가 있었으며, DLL이 처음 로드되었을 때에 이게 한 번만 호출되곤 했다.

16비트 시절에 DLL은 프로세스 독립성이 보장되지 않았다.
지금이야 B.DLL을 사용하는 A.EXE가 두 번 중첩 실행되면 두 인스턴스에 대해서 B.DLL이 제각각 로드되어 DLL_PROCESS_ATTACH가 오지만..
옛날에는 A.EXE가 중첩 실행되었더라도 B.DLL에서 LibMain은 첫 로딩될 때 한 번만 실행되었다. 그리고 자신이 A의 두 번째 인스턴스에 의해 중첩 로드되었다는 사실을 알 길이 없었다. A가 B.DLL에 별도로 정의되어 있는 초기화 함수 같은 것을 호출하지 않는다면 말이다.

LibMain 함수의 인자를 살펴보면, 첫 인자는 자기 자신을 식별하는 인스턴스 핸들이다.
하지만 16비트 시절에는 DLL은 중첩 로딩이 되지 않고 자신의 전역변수 값이 모든 프로그램에서 공유되었다. 그렇기 때문에 저 값은 EXE의 WinMain에서 전달되는 인스턴스 핸들과는 달리 딱히 변별성은 없었을 것이다. 시스템 전체를 통틀어 같은 값이 들어왔으리라 생각된다.

그 다음 wDataSeg와 wHeapSize는 딱 보기만 해도 16비트스러운 암울한 값이다. 이게 어떤 의미를 갖고 이것으로 무엇을 할 수 있는지 잘 모르겠다.
데이터 세그먼트(DS) 레지스터 값은 뭐 어쩌라는 건지 잘 모르겠지만 어쨌든 실행할 때마다 다른 값이 들어올 수는 있어 보인다. 그 반면 wHeapSize는 이 DLL을 빌드할 때 def 파일에다가 지정해 줬던 로컬 힙의 크기이다. 즉, 이 DLL이 지금 형태 그대로 존재하는 한 언제나 고정된 값이 넘어온다.

마지막으로 lpszCmdLine은 더욱 기괴하다. EXE도 아니고 DLL을 어떻게 인자를 줘서 로딩한단 말인가? LoadLibrary 함수에 인자를 전달하는 기능이 있지도 않은데 말이다. 호스트 EXE에 전달된 인자를 되돌리는 것도 아닌 듯하다. 실제로 거의 대부분의 경우 이 인자의 값은 어차피 그냥 NULL이라고 한다.

16비트 DLL의 첫 관문인 LibMain은 기괴한 점이 여기저기서 발견된다.
DLL에 배당되어 인자로 전달된 데이터 세그먼트는 앞으로 빈번하게 사용되는 것을 염두에 두고 메모리 상의 주소가 바뀌지 않게 lock이 걸린다고 한다. 운영체제는 아니고 컴파일러가 lock을 거는 코드를 기본적으로 추가해 넣는 듯하다.
그래서 옛날 소스 코드를 보니, 이유는 알 수 없지만 LibMain에 보통 이런 코드가 들어갔다고 한다.

if (wHeapSize > 0) UnlockData (0);

즉, 아직은 lock을 걸지 말고 도로 재배치 가능한 상태로 놔 두겠다는 뜻이다. 그리고 LockData/UnlockData는 Windows 3.1의 windows.h에 이렇게 매크로로 정의돼 있다.

#define LockData(dummy)     LockSegment((UINT)-1)
#define UnlockData(dummy)   UnlockSegment((UINT)-1)

옛날에는 (Un)LockSegment라는 함수가 있었다. 그리고 Windows 3.x보다도 더 옛날에는 (Un)LockData라는 함수도 별도로 있었는데, 용례가 간소화돼서 Data의 기능이 Segment로 흡수된 듯하다. (가상 메모리라는 게 없던 Windows 2.x 리얼 모드 시절의 잔재라고 함.) 그러니 Data는 레거시 호환을 위해 매크로로 바뀌고, 인자 역시 쓰이지 않는 dummy로 바뀐 것이다.
평소에는 특정 세그먼트 lock/unlock을 하는데, (UINT)-1을 주면 모든 영역을 그렇게 하는 것 같다. 어떤 경우든 wDataSeg의 값이 직접 쓰이지는 않는다.

LibMain은 초기화가 성공하면 1을 되돌리고 그렇지 않으면 0을 되돌려서 DLL의 로딩을 취소하게 돼 있었다. 이것은 오늘날의 DllMain과 동일한 점이다.
그럼 16비트 시절에는 시작 다음으로 DLL의 종료 시점을 감지하려면 어떻게 해야 했을까? EXE와는 달리 DLL은 main 함수의 종료가 곧 프로그램의 종료는 아니니까 말이다.
또한 16비트 시스템의 특성상 비록 매 프로세스의 종료 시점을 감지하는 건 불가능하겠지만, 그래도 아까 중복 실행되었던 A가 최후의 인스턴스까지 모두 종료되어서 B.DLL이 메모리에서 사라져야 하는 시점이 언젠가는 올 테니 말이다.

이것도 방법이 굉장히 기괴했다. DLL이 메모리에서 제거되기 전에 운영체제는 해당 DLL에서 'WEP'라는 이름을 가진 함수를 export 테이블에서 찾아서 그걸 호출해 줬다.

//16비트 시절에 _export는 오늘날의 __declspec(dllexport) 와 비슷한 단어임.
int FAR PASCAL _export WEP (int nExitCode);

이 함수 역시 성공하면 nonzero를 되돌리게 돼 있지만, 어차피 프로그램이 일방적으로 종료되는 상황에서 함수의 인자나 리턴값은 무시되다시피할 뿐 거의 의미가 없었다.
하다못해 오늘날 DllMain의 DLL_PROCESS_DETACH처럼 자신이 FreeLibrary에 의해 해제되는지, 프로세스의 종료에 의해 일괄 해제되는지라도 알 수 있으면 좋을 텐데 그 시절에 그런 정보를 바랄 수는 없었다.
참고로 WEP는 그냥 Windows Exit Procedure의 약자였다. -_-;;

이렇듯, 형태가 거의 바뀐 게 없는 WinMain과는 달리, DLL의 입구 함수는 16비트 시절과 지금이 달라도 너무 달라서 문화 충격이 느껴질 정도이다. 예전에도 16비트 Windows 프로그래밍에 대해서 글을 종종 쓰고 DLL에 대해서도 언급한 적이 있었는데 이런 내역에 대해서 정리한 적은 없었기 때문에 또 글을 남기게 됐다. 옛날에는 이렇게 불편한 환경에서 도대체 프로그램을 어떻게 만들었나 싶다.

LibMain과 WEP를 DllMain으로 통합한 것은 백 번 잘한 조치였다.
16/32비트 이식성을 염두에 둔 코드라면 DllMain에다가 LibMain과 WEP를 호출하고, 반대로 LibMain과 WEP에서 적절하게 서로 다른 인자를 줘서 DllMain을 호출하는 계층도 생각할 수 있으며, 과거에는 이런 관행이 실제로 존재했다고 한다. 마치 윈도우 프로시저와 대화상자 프로시저의 형태를 통합한 계층을 따로 만들어 썼듯이 말이다.

Posted by 사무엘

2016/05/27 08:38 2016/05/27 08:38
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1231

지난 3월 초, 봄비가 촉촉히 내리고 있을 때 또 무작정 산을 올랐다. 이번에는 지금까지 말로만 수도 없이 들었지 직접 가 본 적은 한 번도 없었던 남한산성을 구경하러 청량산으로 갔다.
전에 불암산을 오를 때는 서울 지하철 4호선의 종점인 당고개 역으로 갔고, 하산은 남양주 쪽으로 했다. 이와 대조적으로 이번에는 5호선의 종점인 마천 역으로 갔고, 하산은 하남 쪽으로 했다.

또한 불암산은 하산한 뒤 남양주의 산기슭에 군부대가 있던데, 여기 청량산은 반대로 등산 전 서울의 끝자락 지점에 군인 간부 아파트와 군부대가 있었다. 듣자하니 특전사 부대라고 함.
지하철 운임에 조조할인이 적용될 정도로 굉장히 이른 시간에 산행을 했다. 덕분에 아침 7시 정각이 되자 군부대에서 기상 나팔 소리가 울려 퍼졌다. 그리고 이어지는 군가 BGM들..;; 단 4주간의 짧은 경험이지만 훈련소 시절 생각이 났다.

인근 주민들은 이거 듣는 게 일상이 돼 있겠구나. 단, 지도를 보니 이 군부대는 위례 신도시의 개발로 인해 딴 데로 이전하고 부지가 재개발될 계획인가 보다. 서울 2기 지하철이 없던 시절에는 여기만 해도 굉장한 외곽이고 오지였겠지만, 지금은 그렇지 않으니 말이다.

본격적으로 산을 오르기 전, 아직 맛집들이 즐비한 골목을 지나고 있는데 "서울 빠이빠이. 여기부터는 하남시입니다" 이런 표지판이 눈에 들어왔다. 산이 행정구역상 하남에 있는가 보다. 단, 나의 목적지인 남한산성은 하남이 아니라 광주 소재였다.

사용자 삽입 이미지

남한산성은 도립공원이며 여기 일대는 유명한 등산 코스이다. 그래서 등산로는 내가 가 본 산들 중 가히 톱급으로 잘 닦여 있었다. 난간에다가 바닥은 미끄럼 방지용 매트까지.. 비가 내린 직후의 날씨이지만 진흙 진창을 밟을 일이 거의 없을 정도였다.

사용자 삽입 이미지

본인은 딱히 체력이 좋은 편이 아니며 산을 남들 이상으로 빠르게 잘 타지는 못한다. 하지만 1시간 남짓 느릿느릿 쉬기를 반복하면서 산을 오르니 남한산성엔 생각보다 금방 도달할 수 있었다. 저기는 서문(west gate)이었다.
아침 7시 남짓한 이른 시간이어서 산은 한산했지만, 그래도 하산하는 몇몇 일행과 마주치기도 했다.

사용자 삽입 이미지

연주봉 옹성에 들렀다가 왔다. 아무 산에나 이런 구조물이 있는 게 아니니 남한산성은 확실히 레어템이긴 하다.

사용자 삽입 이미지

내가 올라온 길 방향을 내려다보며 찍은 사진. 날씨가 흐리고 어두워서 전망이 그리 좋지는 않다. 또한 그렇게 막 높게 올라온 것도 아니다.

사용자 삽입 이미지

이번엔 내가 하산할 지점(하남시 춘궁동)을 내려다보며 찍은 사진이다. 좌우로 산(언덕?)에 둘러싸인 일종의 계곡 같은 지형이다.

사용자 삽입 이미지

남한산성의 안팎은 대충 이런 형태였다. 대포와 폭격기가 발달하면서 지금이야 이런 성 같은 건 군사적 가치가 전혀 없어졌지만, 옛날에는 가파른 산들 사이에 분지가 조성된 여기가 천혜의 요새 그 자체였다고 한다.

사용자 삽입 이미지

여기는 북문이다. 본인은 하산은 이쪽으로 했다.

사용자 삽입 이미지

산성 로터리. 남한산성 내부에는 아예 각종 맛집 마을이 조성돼 있으며, 자동차가 들어오는 정도를 넘어서 정규 노선 버스가 다닌다. 물론 산중턱이니 올라가는 데 기름이 많이 들 것 같다. 북한산성 주변은 이런 거 없음.
주변엔 한옥 형태의 한식당이 가득하다. 내가 갔을 때는 시간 관계상 아직 문을 연 곳은 없었음. 그래도 다들 가격이 왕창 셀 것 같았다.

저기서 방향을 꺾어서 조금만 더 가면 남한산성 행궁을 볼 수 있었을 텐데 그건 미처 생각을 못 했다.

사용자 삽입 이미지

이제 북문으로 나가서 하산을 시작했다. 지도에서 봤을 때 고도 대비 등산로가 좀 짧다는 생각을 했는데 역시나 지그재그 스위치백이 있었다.

사용자 삽입 이미지

산을 벗어나서 버스 정류장이 나올 때까지 한참을 걸었다. 서울 외곽에서 산 하나만 넘으면 이렇게 전원적인 마을이 펼쳐진다는 게 신기하다.

사용자 삽입 이미지

미리 봐 뒀던 버스 종점 겸 공영주차장에 도달했다. 공간이 얼마나 여유로운지, 저 주차장은 관리인도 없고 전면 무료이다. 그러니 마음만 먹으면 차를 여기에다 두고 안심하고 등산을 하는 것도 얼마든지 가능하다.
하지만 본인은 등산 원칙이 "갔던 길로 돌아오지 않는다"이기 때문에 어지간히 장거리 등산 원정을 떠나는 게 아닌 이상, 차는 가져가지 않는다. 여기서는 옆에 세워져 있던 마을 버스를 탔다.

사용자 삽입 이미지

그 뒤 하남 시내에서 내려서 서울로 가는 버스를 갈아탔는데...;; 시가지 도로의 모습은 약간 문화 충격을 느낄 정도였다. 나름 광역버스 9301이 지나는 길인데도 시내 도로가 이렇게 작다니.
하남대로라고 불리는 국도 43호선 구간을 제외하면 다 저런 것 같았다.

서울 역까지 가장 깊숙이 들어가는 버스는 9301뿐이고, 나머지 도시형 버스들은 다들 동서울 터미널 정도까지만 갔다. 물론 어느 것이든 국도 43호선의 천호대로 구간으로 들어가서 5호선 강동 역을 경유하는 건 변함없으므로 본인은 아무 거나 타고 귀가했다. 하남시와 인접한 서울 동쪽 끝자락에도 그린벨트가 풀리고 아파트가 곳곳에서 지어지는 게 보였다.
어쩌다 보니 남한산성 답사기는 다른 등산기보다 글이 좀 길어졌다.

Posted by 사무엘

2016/05/24 08:34 2016/05/24 08:34
,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1230

다음 버전 개발 근황

<날개셋> 한글 입력기 8.4의 다음 버전은 8.5이다. 6월 말쯤에 나올 예정이다. 아울러, 타자연습도 3.5가 나올 예정이다.

8.5의 변화 사항들은 대부분 GUI 등 사소한 것들이다. 그러나 예전보다 센스 있게 동작하도록 기능이 추가되거나 변경된 건 있어도, 지난 8.4에서 뭔가 크게 잘못 동작하던 것이 바로잡혔다거나 버그가 고쳐진 것은 없다. 그만큼 8.4는 완성도 높게 잘 만들어졌으며 <날개셋> 한글 입력기도 '더 고칠 게 없는' 안정화 고정 단계에 근접한 듯하다.

8.5의 존재 의미라 할 수 있고 한글 입력 엔진 차원에서 바뀐 유일한 과업은 바로 '이벤트 핸들러'의 구현이다. 사실, 8.4에서 들어가려 했으나 이론 검증과 확신이 서지 않아서 차마 마무리를 못 하고 한 버전 더 거쳐 가게 됐다.
입력 스키마(현재 사용 중인 놈 한정)와 보조 입력 도구는 한글 입력 엔진으로부터 다음과 같은 상황에서 7종류의 이벤트를 받아서 이때 자신만의 처리를 할 수 있다. 주로 사용자(소문자 a~z) 변수를 초기화하는 수식이 실행된다.

(1) 시스템: <날개셋> 한글 입력기를 사용하는 프로그램 전체가 활성/비활성화됐을 때. 그리고 외부 모듈의 경우, 해당 UI 스레드 차원에서 IME가 날개셋으로 바뀌었거나 해제됐을 때. on/off 경우에 모두 호출된다. 단, 입력 패드는 언제나 시스템 차원에서 global하게 구동 중이므로 이 이벤트를 따로 보내지 않는다.

(2) 포커스: 한 프로그램 안에서 <날개셋> 한글 입력기를 사용하는 창의 포커스가 여기서 딴 데로 바뀌었을 때. 그리고 외부 모듈의 경우 창 포커스는 여전하더라도 내부적으로 사용하는 컨텍스트가 바뀌었을 때(HIMC). 역시 on/off 때 모두 호출된다.
포커스/컨텍스트가 바뀌었으며 잃었다가 얻었다는 사실 자체만 알 수 있지, 구체적으로 그 값을 구분해서 인식할 수 있지는 않다.

(3) 입력 항목(글쇠배열) 전환: 원래 있다가 교체되는 놈(off)과 새로 지정되는 놈(on)이 모두 이벤트를 받는다. 또한, 제어판을 구동하여 입력 설정이 바뀐 뒤에도 디폴트로 지정된 입력 항목은 처음에 on 이벤트를 받는 게 보장된다.
보조 입력 도구에는 요런 통지를 받는 게 이미 있다. 그래서 '화면 키보드' 도구가 지금 사용 중인 글쇠배열을 실시간으로 업데이트 해서 표시해 준다.

(4) 외부에 의한 조합 강제 종료: 한글 입력 중에 마우스 클릭, 포커스 변경, 우리 입력 스키마가 처리하지 않는 글쇠 등의 이유로 조합이 종료되었을 때 이벤트를 받는다. on/off 개념은 없고 그냥 단일.

(5) 문자 연속 입력 단절: 조합 강제 종료와 비슷하지만 이와 완전히 동일하지는 않은 개념이다. 굳이 조합을 만들지 않더라도 문자를 계속 입력하거나 bksp 하고 있었는데 갑자기 비문자 글쇠나 마우스 클릭, 포커스 변경 등이 감지되면 이 이벤트가 한번 날아온다.

지금도 "bksp 연타 시 한번 정해진 동작을 계속 적용" 옵션이 이 이벤트 비슷한 개념을 사용하고 있다. 그런데 이를 개념적으로 더 확장하여, 굳이 한글 조합 중일 때가 아니라 연속 입력 중일 때에 '낱자 단위로', 연속 입력이 끊어졌을 때는 '글자 단위로' 한글을 지우도록 할 수도 있게 했다.

(6) 변수값 변화: 입력 스키마의 글쇠배열 내지 문자 생성기의 오토마타에서 수식 계산으로 인해 변수값이 바뀐 것을 보조 입력 도구가 알 수 있게 한다.
그래서 보조 입력 도구를 이용해 변수값 디버거를 만들 수 있게 된다. 그리고 '화면 키보드' 도구가 아예 context-sensitive하게 지금 입력되는 문자를 화면에다 업데이트 가능하게 된다. 즉, 복벌식 입력기라면 내부 변수값에 따라 두벌/세벌 모드가 됐을 때 글쇠배열 전체가 두벌식이나 세벌식 모양으로 바뀐다.

(7) 타이머: 지금은 천지인 모바일 입력기처럼 특정 상황에서 일정 시간이 경과했을 때 조합을 강제 종료시키는 기능을 구현할 때 타이머가 제한적으로 지원되고 있다. 타이머는 그 기능을 더 일반화해서 겉보기로 조합은 유지하더라도 오토마타의 내부 상태만 바꾸는 것, 임의의 글자를 입력시키는 것, 타이머를 1회가 아니라 계속 동작시키는 등 더 다양한 처리를 할 수 있게 된다.

이렇듯, 통합적인 이벤트 핸들러는 한글 입력기의 아키텍처에서 매우 중요한 기능이다. 오랫동안 필요성만 인지하고 있었을 뿐 작업을 할 엄두를 못 내고 있던 곳에 대대적인 수정이 가해졌다. 이 기능 하나에다가 다른 UI 쪽의 변화 사항들을 합치면 +0.1 버전업은 충분한 가치와 의미를 지닌다.
이벤트 핸들러 수식을 지정하는 UI는 글쇠배열의 추가 옵션을 지정하는 대화상자에 들어갈 예정이다. 어차피 글쇠배열 내부에서 쓰이는 변수들을 초기화하는 수식이 들어갈 테니 말이다.

이것 말고 가볍게 읽을 만한 새 버전 변화 사항들은 다음과 같다. 8.5가 어서 완성됐으면 좋겠다.

1. 한글 낱자 종류 변환에 filler를 안 집어넣는 옵션

텍스트 필터 중에 '한글 낱자 종류 바꾸기'라는 게 있는데, 이건 호환용 한글 자모(U+31??)와 표준 한글 자모(U+11???) 사이를 변환하는 나름 중요한 기능이다.
표준 한글 자모에는 정규화 규칙이라는 게 적용되기 때문에 자음 하나, 모음 하나만 있을 때에도 초/중성의 빈 자리에는 채움 문자(filler)가 꼭꼭 들어간다. 하지만 채움 문자 없이 호환용 자모를 문자 그대로 표준 한글 자모로 일대일 치환만 해 주는 옵션이 이번 버전에서 추가되었다.

이 옵션을 사용하면 정규화 규칙에 어긋나는 문자열을 생성할 수도 있지만, 한편으로 "ㅎㆍㄴ" 같은 풀어 쓴 호환용 자모로부터 모아 쓴 옛한글을 곧바로 만들어 낼 수 있다. 채움 문자가 없으니 각 자모가 그대로 한 글자를 구성하게 됐기 때문이다.

2. 외부 모듈에서 문자표 대화상자의 동작 방식 변경

<날개셋> 편집기와 외부 모듈은 모두 문자를 입력하는 프로그램이니 키보드에 없는 특수문자를 입력하는 '문자표' 기능이 있다.
편집기야 내부의 모든 데이터 입출력이 100% 자가통제가 가능하기 때문에 문제될 게 없지만 외부 모듈은 문자표로부터 받은 문자를 응용 프로그램에서 보내는 것만 가능하고 그 프로그램이 실제로 문자를 접수하는지를 완벽하게 알 수는 없다.

그래서 문자표라는 대화상자가 키보드 포커스를 얻어 있는 상태에서 본문 창에다가 계속해서 문자를 보내는 게 기술적으로 가능한 프로그램도 있고 가능하지 않은 프로그램도 있었다. 즉, 외부 모듈에서 문자표 대화상자는 사실상 반쪽짜리 기능이었던 것이다. 텍스트 필터가 TSF A급에서만 사용 가능한 반쪽짜리 기능인 것처럼 말이다. 이런 이유로 인해, 이 버튼은 프로그램을 처음 설치했을 때는 기본적으로 도구모음줄에 나타나 있지도 않았다.

이 점을 감안하여 이번 버전에서는 외부 모듈의 문자표의 동작 방식을 바꿨다. 연속 입력 기능을 희생시켰다. 엔터를 누르면 문자표 대화상자는 곧장 닫혀 버린다.
그 대신 글자 단 하나를 입력하더라도 그 기능만은 IME, TSF A/B 등을 가리지 않고, 또 BMP와 surrogate를 가리지 않고 모든 프로그램에서 제대로 동작하게 정책을 바꿨다. 동작을 차라리 이렇게 바꿔 버릴까 오랫동안 고민했는데 결국 이제야 결정을 내렸다.

문자표를 꺼내 놓은 채로 여러 문자를 입력하고 싶으면, 이런 대화상자가 아니라 '보조 입력 도구' 중 하나인 문자표를 사용하면 된다. 얘는 반대로 문자표 내부에서 키보드 조작을 할 수는 없지만, 키보드 포커스를 차지하지 않기 때문에 창이 떠 있는 상태에서도 다른 프로그램의 UI에 영향을 주지 않는 게 가능하다.

3. 문자표에 Ctrl+클릭

요즘은 그냥 클릭에 뭔가 2% 부족한 면모가 있을 때 Ctrl+클릭을 추가하는 게 새로운 UI 트렌드인 것 같다.
후보 데이터를 추가할 때 Ctrl+클릭을 하면 입력된 문자열이 각각의 글자 단위로 따로 후보로 추가된다. 그리고 낱자 결합 규칙에서도 Ctrl+클릭을 하면 추가 후에 입력란의 값과 키보드 포커스가 그냥 클릭과는 다르게 바뀐다.
외부 모듈의 후보 목록에는 Ctrl+클릭(Ctrl+엔터 포함)뿐만 아니라 Shift+클릭도 있어서 단순히 한자 변환뿐만 아니라 한글(한자) 또는 한자(한글) 형태를 지정할 수도 있다.

이와 같은 맥락에서, 문자표에도 Ctrl+클릭 동작을 추가했다.
그냥 '추가'를 누르면 선택된 문자가 본문에 삽입되고 대화상자가 그대로 남아 있는 반면, Ctrl+클릭을 하면 이제 문자가 삽입됨과 동시에 대화상자가 닫히게 했다. 이 기능이 있으니 정말 편하다. 물론 애초부터 연속 입력이 가능한 편집기의 문자표 같은 곳에서 말이다.

4. 글자가 많이 존재하는 부수는 진하게 표시 (부수로 한자 입력 기능)

오늘날 수만 자에 달하는 한자들을 분류하는 데는 부수라는 게 쓰인다. 부수는 총 214개가 존재하는데, 한자에 식견이 있는 분이라면 다 아시겠지만 이 부수들이 골고루 쓰이는 게 아니다. 분포가 전혀 균일하지 않으며, 소수의 특정 부수에만 쏠림이 매우 심하다.

예를 들어 요일을 나타내는 한자들(火, 水, 木, 金 같은. 단 月은 제외), 人, 車, 言, 鳥처럼 만만하고 보편적인 뜻을 가진 부수에는 한자가 수백~심지어 1000개가 넘게 들어있고 새로운 글자가 또 만들어지기도 한다. 그러나 匕, 至, 臣, 牙, 首, 父, 龜, 鼠 같은 나머지 대부분의 부수들은 듣보잡이다. 그 제부수자 자체는 首, 父, 高, 非, 長처럼 아주 기초적이고 친숙한 반면, 거기서 파생된 한자는 거의 없는 경우도 있다.

이 점을 감안하여, 다음 버전에서는 "부수로 한자 입력" 도구에 한자가 매우 많이 들어있는 상위 10% 정도의 부수는 약간 진하게 표시해서 사용자의 눈에 미묘하게 더 잘 띄게 했다.
이것도 시각 피드백을 어떻게 줄지 무척 고민했다. 색깔을 달리 하는 건 제일 간단하긴 하지만, 실험 결과가 좋지 않아서 관뒀다. 이미 색깔로 변별하는 다른 요인들도 있는데(한자의 등급, 현재 선택된 부수와 획수가 같은 부수) 거기에다 색깔 변화를 더 주면 비주얼이 너무 튀고 더 혼란스러워졌다.

그 다음으로 생각한 건, 글자 크기에 변화를 주는 것이었다. 하지만 이 역시 결과가 별로 좋지 않아서 최종적으로는 '볼드' 속성이 낙찰됐다. 요렇게 해 주니 딱 봤을 때 너무 튀지 않으면서도 자주 쓰이는 메이저 부수만 빨리 찾는 데 확실히 도움이 된다. 나만 그렇게 생각하는 게 아니었으면 좋겠다만..;;

5. 타자연습: 계정 import/export, 그리고 파일 기반 custom 연습글

타자연습에는 로그인 화면에서 계정 파일을 다른 디렉터리로 내보내거나 거기서 계정 파일을 가져오는 import/export 기능을 추가했다.
단순한 파일 copy 기능에 지나지 않지만, 사용자 계정을 컴퓨터끼리 옮길 수 있게 하는 건 진작부터 필요했던 기능인데 이제야 도입됐다.
궁극적으로는 서버를 통한 동기화도 지원해야 할 텐데 그건 내 혼자 할 수 있는 일은 아니고..

그리고 거의 10년 가까이 유지되던 연습글 목록 관리 방식이 바뀌었다.
XML 파일 기반인 것은 변함없지만, 이것은 프로그램이 기본 제공하는 고정 붙박이 연습글에만 적용된다.
이전처럼 사용자가 XML 리스트를 직접 고치는 것은.. 이제는 더 권장되지 않는 지저분한 관행으로 deprecate됐다. 프로그램 UI에는 예전과 같은 '연습글 추가/삭제' 같은 버튼과 기능이 사라졌다.

그 대신, 사용자의 custom 연습글은 특정 디렉터리에다가 txt 파일들을 갖다 놓기만 하고 '새로 고침'을 누르면 거기에 있는 것들을 프로그램이 알아서 추가로 등록해 주는 형태로 바뀌었다. 하위 디렉터리가 있으면 물론 그것까지 알아서 찾기 때문에 재귀적인 트리 구조를 만들 수 있다. 디렉터리는 꾸러미, 파일은 연습글로 그대로 대응되는 거다.

custom 연습글은 크게 두 종류가 있다. (1) 이 컴퓨터를 사용하는 모든 사용자가 똑같이 공유하는 놈, 그리고 (2) 현재 사용자 계정에서만 보이는 놈.
(1)의 위치는 답정너로 고정돼 있다. "운영체제의 공용 문서\YmSoft\NgsType"이다. 여기에다가 txt 파일들을 심어 놓으면 <날개셋> 타자연습에서 어느 계정으로 로그인 하건, 아니 로그인하지 않고 익명으로 사용하더라도 연습글들을 볼 수 있다.

또한, 여기에 덧붙여 임의로 지정된 디렉터리를 하나 더 동일한 방식으로 수색하게 할 수 있다. 이 위치는 각 계정별로 달라질 수 있다.
기본 제공되는 보급 연습글은 맨 위에 표시되며 꾸러미가 예전처럼 자주색이다. 그러나 (1) 공용 custom 연습글은 꾸러미가 밝은 분홍색이며, (2) 개인용 custom 연습글은 꾸러미가 파란색이다.

"문장/글 연습" 탭에 가 있는 상태에서 '환경설정' 버튼을 누르면, 예전에는 '외형'과 '타자 연습'이라고 탭이 2개 있는 대화상자가 떴는데, 이제는 '추가 연습글'이라는 제3의 탭이 추가되었다. 여기에서 공용 연습글 디렉터리가 어디인지 정확한 경로를 확인하고 그 창을 탐색기로 열어 볼 수 있다. 그리고 개인 연습글 디렉터리는 위치도 사용자가 지정하고 탐색기로 여는 것도 가능하다. 이제 나만의 연습글을 추가하는 건 이런 식으로 하면 된다.

여담이지만, 이번 버전에서는 기본 제공되는 연습글들도 좀 현실화했다.
잉여도가 너무 높아 보이던 옛한글 연습글을 삭제하고, 성경도 잠언과 요한복음만 남겼다. 잠언은 '슬기로운 이야기' 카테고리에 있던 것을 '영적 생활'로 옮겼다.
우리말 우리글 카테고리에 있던 글들을 삭제하고 '한글 노래' 하나만 남겨서 '마음의 양식' 카테고리에다 옮겼다.
그래도 <날개셋> 타자연습은 안 창호 선생의 글과 김 성모 화백 어록, '어둠에다크에서'가 한 자리에 놓여 있는 타자 연습 프로그램이다. 제작자가 인터넷 병맛 개그를 좀 좋아하기 때문에..;;

* 그 밖에,

(1)
 <날개셋> 편집기는 상태 표시줄(status bar)에 있는 글자판(입력 항목)을 우클릭하면 글자판을 선택하는 메뉴가 나타난다. 그래서 한영 내지 Shift+Space 같은 단축글쇠를 안 누르고도 마우스로 입력 모드를 전환할 수 있다.
그 중 '빈 입력 스키마'는 아시다시피 <날개셋> 한글 입력기가 제공하는 특정 입력 모드가 아니라 그냥 운영체제가 제공하는 IME를 그대로 받아들여서 문자를 입력하는 모드이다.

빈 입력 스키마를 사용하고 있는 상태에서 이 메뉴를 통해 동일한 빈 입력 스키마를 또 선택하면 그때는 운영체제의 한영 상태를 전환하는 기능을 추가했다. 중국어나 일본어 IME를 사용하고 있다면 해당 언어의 자국 문자 모드와 영문 모드가 전환된다.

(2)
대화상자에서 리스트 박스의 아이템을 더블 클릭하면 그 아이템을 고치거나, 그걸 선택한 채로 '확인'을 바로 누르는 shortcut 동작이 수행되곤 한다. 그에 비해 라디오 버튼의 더블 클릭은 잘 알려져 있지 않지만, 이 역시 MS가 권장하는 UI 동작이다. 대표적인 예가 MS Office 프로그램에서 화면 확대 대화상자인데, 100, 200같은 퍼센트를 라디오 버튼으로 선택하고 그걸 더블 클릭하면 곧바로 대화상자가 종료된다.

<날개셋> 한글 입력기는 다음 버전부터 주요 UI에 라디오 버튼의 더블 클릭이 지원될 예정이다. 라디오 버튼의 선택이 해당 대화상자의 동작 방식이나 옵션을 거시적으로 결정하는 대화상자들이 그 대상이다. 대소문자 전환(전환 방식), 기본 입력기 빠른설정(사용할 글자판) 등등에서 아이템을 더블 클릭하는 것만으로 대화상자를 확인 종료할 수 있게 된다.

(3)
Windows의 한글 IME 지원 체계에는 좀 이상한 문제가 있다.
TSF를 응용 프로그램이 직접 지원하는 A급 환경 말고, 그냥 IME 호환 계층을 통해 지원하는 B급 환경에서는..
처음에 2글자 이상의 조합을 만들면 조합이 그냥 끊어져 버린다. 이건 이유는 모르겠지만 운영체제가 한글 IME에 대해서 거의 일부러 강요하는 동작이다. 9x/XP 시절, IME 모듈조차도 안 이랬는데 말이다.

이런 이유로 인해 TSF B급 프로그램에서는 한글 조합은 반드시 1글자짜리 호환용 한글 자모로 시작해야 하고, 2~3글자짜리로 정규화된 표준/옛한글 자모로 시작할 수 없다. 첫 타 이후에 다음 타로 인해 계속된 조합의 길이가 2글자 이상으로 가는 건 괜찮다.
이번 새 버전에서는 TSF B급 프로그램에서 2글자 이상의 조합을 만들려 해서 조합이 끊어졌다면 이를 감지해서 이 현상에 대한 간단한 안내 메시지와 도움말 링크를 표시하게 했다. 그래서 이건 설정 문제이지 프로그램의 버그가 아님을 사용자가 알 수 있게 했다.

(4)
좀 어이없는 실수이긴 한데..
드보락이라는 영문 글쇠배열을 만든 사람은 미국의 교육심리학자인 '어거스트 드보락' 박사이다. Dvorak Simplified Keyboard라는 이름으로 이 글쇠배열이 공표된 것은 1932년이고 특허를 얻은 것은 1936년이다.
하지만 지금까지 <날개셋> 한글 입력기의 빠른설정 UI와, 타자연습 도움말의 '세벌식과 드보락의 관계는?'에는 이게 '안톤 드보락이 1930년에 고안한 글쇠배열'이라고 잘못 소개되어 있었다.

이 사람의 이름은 체코의 작곡가 이름인 '안토닌 드보르작'과 매우 혼동되는 편인데, 그거 영향을 받은 것 같다.
우연히 간단한 구글링을 하다가 이 사실을 발견하고는 바로잡았다. <날개셋> 한글 입력기와 타자연습의 다음 버전에서 반영될 것이다.
이거 실수의 근원을 추적해 보니.. 어이없게도 아래아한글의 도움말이었다. 2007 버전만 해도 글자판 소개에서 드보락 설명을 보면 "쿼티 글자판의 단점을 보완하여 1930년 안톤 드보락 박사가 고안한 글자판"이라고 설명되어 있기 때문이다.

Posted by 사무엘

2016/05/21 08:24 2016/05/21 08:24
, ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1229

DOS 회상

1. 들어가는 말

오늘날의 거대하고 복잡한 운영체제와는 달리, 도스는 이니셜 D-_-가 암시하듯이 달랑 플로피디스크 한 장만으로 부팅이 가능할 정도로 참을 수 없이 작고 가벼웠다. 정말 필수불가결인 파일은 부팅에 쓰이는 io.sys, 그 뒤 셸 역할을 하는 텍스트 명령 해석기인 command.com이 전부다.
msdos.sys라는 파일도 있는데 얘는 정확하게 무슨 존재인지 모르겠다.

그리고 사실은 config.sys의 DEVICE 명령을 통해 실행되는 sys 파일과, com 실행 파일이 서로 무슨 차이가 있는지도 모르겠다. 마우스, 그래픽 카드 에뮬(simcga, msherc ^^), 사운드(sound, unsound) 같은 여러 램 상주 드라이버들은 com이었지만, 씨디롬 드라이브는 sys였으며 그것도 주 메모리를 꽤 많이 차지하는 드라이버였다. 단, 부팅 후에 sys 파일을 별도로 실행해 주는 유틸리티가 있기도 했다.

디스크로부터 파일을 읽으려면 파일 시스템이 정립돼 있어야 하며, 이건 운영체제가 하는 일 중 하나이다. 그런데 그 운영체제를 로딩하는 프로그램도 파일 형태로 저장돼 있다. 이런 '닭이 먼저냐 계란이 먼저냐' 딜레마를 해소하기 위해서는, 부팅에 쓰이는 운영체제 프로그램은 디스크에 단순히 파일 형태로만 존재하는 게 아니라, 컴퓨터 바이오스가 물리적이고 원초적으로 인식 가능한 첫 지점에 저장돼 있어야 한다. 이건 굳이 도스뿐만 아니라 어느 운영체제라도 마찬가지이다.

도스는 단일 사용자 단일 프로그램 구동 체계이다 보니, 한 프로그램이 그야말로 컴퓨터 하드웨어를 전부 있는 그대로 조종 가능하게 허용하는 백지수표, 열린 허허벌판 같은 환경이었다. 프로그램의 인터페이스도 명령 기반, TUI, GUI 등 제각각이었고 정말 창의적이었다. 요즘 프로그램들만치 UI가 획일화됐다는 느낌이 없이 형형색색 컬러풀했다.

물론 그건 거시적인 관점에서는 그리 효율적이지 못하다. 이런 빵빵한 컴퓨터 자원에서 여러 프로그램을 동시에 실행하고 작업 전환을 할 수 없다면 그것도 컴퓨터에 대한 예의-_-가 아니다.
그러니 운영체제가 더 강력하게 모든 걸 통제하는 지금 같은 환경으로 궁극적으로는 바뀌는 게 맞긴 하지만.. 인제 와서 도스가 다시 새삼스럽게 그리워질 때도 있다.

2. 역사

본인이 경험한 MS-DOS의 가장 옛날 버전은 학교 내지 컴퓨터 학원에서 봤던 3.2/3.3이다. 2.x 이하나 4는 실물로 구경을 못 해 봤다. 다만, 5.0과 6.2는 집 컴퓨터에 내장돼 있던 물건이다 보니 개인적으로 친숙하다.

1981년에 첫 출시되었다고 전해지는 MS-DOS 1.0은 그야말로 정말 골동품 폐물이었다고 한다. 그리고 Windows 1.0이 프로그램 창을 겹치게 배열하는 걸 지원하지 않았다면, DOS 1.0은 디스크에 서브디렉터리를 만드는 걸 지원하지 않았다..;;
그나마 도스가 최소한의 도스다운 틀을 갖춘 건 2를 거쳐서 3.x대에 와서부터이다. 특히 5.25내지 3.5인치 고밀도(1.2, 1.44MB) 플로피디스크를 지원하기 시작한 첫 버전이 이 버전이기 때문이다. 3.x에 와서야 좀 물건다운 물건이 나왔다는 점에서는 도스와 Windows가 역사가 서로 비슷한 것 같다.

그 다음 4.0의 아주 기념비적인 업적은 파일 시스템이 FAT12에서 FAT16으로 확장되어, 이론적으로 지원 가능한 디스크 볼륨의 용량이 2GB로 커진 것이다.
그 시절에 기가바이트는 가히 꿈의 규모였기 때문에 홍보 자료에서는 그냥 '제한이 없어졌다'라는 표현이 관용적으로 쓰였다. 참고로, FAT12 시절의 하드디스크의 용량 한계는.. 고작 32MB였다. =_=;;

또한 MS-DOS shell이라고 나름 드래그 드롭도 지원하고 Windows GUI를 어설프게 베낀 듯한 파일 관리자 셸이 추가된 것도 4부터이다. 하지만 MS-DOS 4는 구체적인 내역은 모르겠지만 불안정하고 버그가 많아서 좀 문제작으로 남았다고 한다.

도스 5.0에서 기념비적인 업적은 그 이름도 유명한 HIMEM.SYS와 DOS=HIGH일 것이다. EMM386은 4.0 때 SYS 버전이 있었지만 5.0부터는 EXE로 형태가 바뀌었다고 한다.
또한 이 버전에서는 과거의 불편하던 EDLIN을 대체하는 QBASIC 기반의 텍스트 에디터가 추가되었으며, 명령 프롬프트에서 cursor 이동을 자유롭게 할 수 있게 하고 히스토리 기능도 넣어 주는 DOSKEY 유틸도 이때 추가됐다.

지워진 파일을 첫 글자 이름을 집어넣어서 복구하는 undelete 역시 아마 6이 아닌 5에서 첫 추가됐지 싶다. 이건 PC-tools나 노턴 유틸리티가 먼저 제공하던 꼼수 기능이었는데 동일 기능을 도스에서 직접 수용한 것이다.

그 뒤 6.0은.. 변한 게 많았다.
가장 유명한 건 하드 디스크를 압축해 주는 '더블 스페이스'라는 유틸리티의 도입이다.
이건 무슨 요술을 부리거나 하드 디스크를 물리적으로 어떻게 하는 게 아니라, 그냥 파일 시스템 차원에서 데이터를 zip 같은 소프트웨어 압축을 적용하는 것일 뿐이다. 당장 용량 확보에는 도움이 되지만 디스크의 액세스 속도가 좀 느려지고 에러에 취약해지며, 하드웨어를 좀 험하게 다루는 일부 프로그램과는 트러블의 여지가 생긴다.

참고로 1993~1994년이면 Windows 3.1이 보급되고 어지간한 PC의 하드디스크는 몇백 MB 정도이던 시절이다.
더블 스페이스는 그렇잖아도 꽤 중요하고 민감한 간판 기능인데, 버그를 많이 잡고 안정화를 더 시켜서 6.2가 나왔다.
그런데 이게 '스태커'라는 타사의 제품을 무단 도용한 것으로 판결이 나서 '더블 스페이스'를 뺀 6.21이 나왔고, 저작권 문제를 해결하여 '드라이브 스페이스'를 대신 도입한 6.22로 6.x대가 마무리 되었다. 지금이야 마소에 대해서 IE 브라우저의 독점 소송이 유명하지만, 1990년대 중반엔 저거 저작권 침해 소송이 IT 업계에서 굉장한 화두였다.

압축 유틸리티 말고도 6.x대엔 멀티 부팅이라는 매우 유용한 기능이 추가됐다. 즉, C/C++의 조건부 컴파일처럼 사용자가 선택한 옵션 방식대로 디바이스 드라이버를 로딩하여 부팅할 수 있게 됐다는 것이다.
그리고 디스크 점검 scandisk, 조각 모음 defrag, 시스템 점검 msd, 주 메모리 확보 유틸리티 memmaker 등이 추가되고 PC-Tools로부터 라이선스 받은 안티바이러스 msav 같은 유틸도 도입됐다. 덕분에 노턴 유틸리티가 예전보다는 좀 덜 필요해졌다.

모든 내부/외부 명령에 /? 옵션을 줬을 때 도움말이 나오는 것도 처음부터 존재한 게 아니었다. 6이거나 아니면 5부터인데 그건 정확하게 기억이 안 난다. 옛날에는 도움말 텍스트를 일일이 내장시켜 줄 정도로 컴퓨터의 메모리나 디스크 용량이 충분하지 못했기 때문이다.

단독 제품으로서 MS-DOS의 역사는 1994년에 출시된 6.22가 끝이었다. 도스는 Windows 95/98/ME와 함께 7.0. 7.1. 8.0 버전으로 명맥을 유지하다가 2000년에 드디어 20여 년의 긴 수명을 마치고 역사 속으로 사라졌다.
도스 외부 명령어 중에서 몇몇 필요한 건 Windows 9x 계열에서는 Windows\command로 갔고, NT 계열은 그냥 system32 디렉터리에 있다. 그리고 NT 계열은 format이나 diskcopy 같은 유틸리티도 콘솔에서 실행될지언정 도스가 아니라 Windows용 프로그램이라는 차이가 있다.

3. 그 당시의 유사품/경쟁자

한편, 도스의 바리에이션으로는..
PC-DOS는 그냥 MS-DOS가 IBM 브랜드만 달고 나온 동일 제품이었다고 한다. 한동안 그러다가 6.x대부터는 서로 다른 길을 가기 시작했는데 이미 그때는 PC 환경이 Windows로 충분히 넘어가기 시작했으니 별 의미는 없다. 따지고 보면 IBM은 OS/2가 망한 데다, 도스 분야도 뒷북으로 끝나고 별 재미를 못 본 셈이다. "IBM 호환 PC"라는 걸출한 대인배 이름만 남긴 채 PC 시장에서는 철수했다.

DR-DOS는 MS-DOS의 전신인 CP/M을 직접 만든 게리 킬달이라는 엔지니어가 '디지털 리서치'라는 회사를 세워서 따로 만든 MS-DOS의 대항마이다. '디알'이지 '닥터 도스'는 아님.. 뭔가 기능이 MS-DOS보다 뛰어났다고 얘기는 들었는데 구체적인 내역은 잊어버려서 기억이 안 난다.
DR-DOS를 '노벨' 사가 인수하여 새로 내놓은 것이 '노벨 도스'이며, 이건 1990년대 초중반까지 나왔다.

한편, 4DOS는 커널을 처음부터 새로 만드는 건 아니고 명령 인터프리터인 COMMAND.COM만 대체하는 기능 확장판으로 컴덕들에게 많이 알려져 있었다. 이걸 시먼텍(Symantec) 사에서 인수하여 자신들이 인수한 다른 유명 솔루션인 '노턴 유틸리티'에다가 집어넣은 것이 NDOS이다. 각종 도스 명령들에서 2% 부족하던 것을 보완하는 편의 기능이 굉장히 많았던 걸로 기억한다. (가령, 중간에 파일이 사라져도 괜찮은 batch-to-memory 배치 파일)

그리고 8.3 짧은 파일 이름의 한계를 보완하기 위해, 내부적으로 descript.ion이라는 숨김 파일을 만들어서 파일명에 대한 '주석'을 표시하는 것도 4DOS의 작품이었다. 옛날에 MDIR도 이걸 지원했다. 파일이 복사· 이동· 개명· 삭제됐을 때 주석도 같이 관리하는 게 좀 번거로운 일이 됐으니까.. NTFS처럼 운영체제의 파일 시스템 차원에서 메타데이터를 관리하는 기능이 없으면 어쩔 수 없이 셸 유틸리티가 뒷감당을 해야 한다.

4. MS-DOS의 한글화

MS-DOS가 최초로 한글판이 나온 것도 2나 3 버전부터이지 싶다. 정말 먼 옛날에는 마소가 잠깐 동안 조합형 코드 기반으로 도스를 한글화화기도 했다는데 지금으로서는 거의 Windows 2.1의 한글판 같은 도시전설이 돼 간다.
허나, 1987년에 지금의 KS X 1001, 그 당시의 KS C 5601 완성형이 제정되자마자 표준을 잘 지키는 마소는 완성형으로 광속으로 갈아탔다. 그게 이미 도스 3 시절의 일이다. 마소는 그냥 표준을 따른 것일 뿐이지만, 결과적으로 조합형 코드를 죽이고 한글을 파괴한 원흉(?)으로 일부 진영으로부터 좀 지탄받곤 했다.

그런데 한글 MS-DOS가 텍스트 모드에서 한글 입출력을 구동해 주는 바이오스 유틸리티를 처음부터 내장하고 있지는 않았던 것 같다. 쉽게 말해 hbios와 그 특유의 바탕체 글꼴을 구경한 건 최소한 도스 5나 6부터이다. 3이나 4 시절에나 그런 게 없었으며, 한글 바이오스는 다른 프로그램으로 구동했었다. 이건 내 기억이 잘못됐을 수도 있음.

hbios는 Windows 95로 가면서 mshbios로 이름이 바뀌었으며, 그 당시의 고유 글꼴은 <날개셋> 편집기에 '마소바탕'이라는 글꼴을 통해 구경할 수 있다. 도깨비나 태백한글 같은 싸제 한글 바이오스들은 조합형/완성형, 두벌식/세벌식, 명조/고딕 등 글꼴과 글자판과 코드를 다 선택 가능했지만, 마소의 보급 바이오스는 당연히 완성형, 두벌식, 명조로 다른 선택의 여지가 없었다.

전에도 한번 얘기한 적이 있었지만, 마소에서 한글화한 프로그램들은 2바이트 문자에 대한 처리가 굉장히 잘 돼 있었다. 2바이트를 구성하는 앞뒤 문자 중 하나가 가려지거나 지워지면 다른쪽 문자도 반드시 같이 사라졌기 때문에 텍스트 모드에서 메뉴나 대화상자가 표시될 때도 문자가 깨지는 걸 보이는 법이 없었다. 이에 대한 처리가 세심하게 돼 있었다.

5. 도스 시절의 멀티태스킹

비록 그래픽은 아니고 텍스트 기반이긴 하지만, Windows 3.x 비스무리한 도스 기반 멀티태스킹 운영환경(운영체제는 아니고..)으로 DESQView 같은 프로그램이 있었다. 난 이름만 들어 보고 실제로 구경은 못 했다. 외국에서는 그럭저럭 쓰는 사람이 있었던 듯하지만 Windows의 등장 이후에는 조용히 역사 속으로 사라졌다.

그리고 사실은 더 발전된 멀티태스킹 운영체제를 마소에서 직접, 그것도 Windows나 OS/2와는 별개로 만들려는 시도를 한 적이 있었다. 무려 1986년, Windows조차 이제 막 개 허접한 1.0이 나왔던 시절에 MS-DOS 3을 기반으로 일명 '멀티태스킹 MS-DOS 4.0'이 계획되었던 것이다. 이것은 앞서 언급한 그 도스 4.0과는 무관한 새로운 개발 브랜치였다.

멀티태스킹 MS-DOS 4는 제품이 나오기는 했고 의도도 나쁘지 않았지만, 1980년대 중반에 시대를 너무 앞서간 문제작이었다. 그 옛날에 그 열악한 하드웨어 환경에서 도대체 뭘 더 바라겠는가? 컨셉에 비해 상품성이 떨어졌다.
게다가 그 당시 마소는 지금처럼 독자적인 불특정 다수용 유명 소프트웨어를 독점 판매하는 공룡 기업이 아니었으며, 여전히 하드웨어 제조사에다 소프트웨어를 납품하면서 먹고 사는 기업이었다. 즉, 지금으로서는 상상이 잘 안 되지만, 업계에서의 위상이 '갑'이 아니라 '을'이었다.
프로젝트를 발주했던 IBM이 이 물건을 더 구입해서 사용하지 않겠다고 선언하자 프로젝트는 흑역사가 되었고, 이 멀티태스킹 MS-DOS 4는 오히려 유럽의 일부 컴퓨터에 OEM 형태로 공급되는 걸로 개발 계보가 끝났다.

멀티태스킹 MS-DOS 4는 비록 GUI 환경은 아니지만 Windows의 전유물로만 알려졌던 NE (new executable) 실행 파일도 지원하고 지금으로서는 무척 신기한 면모가 많았다고 한다. 정작 NE를 사용하던 Windows는 NT가 등장하기 전에는 콘솔 모드라는 게 없었는데, GUI 기반이 아니던 멀티태스킹 도스가 NE를 어떤 형태로 사용했는지 궁금하다.

6. 맺는 말

도스 시절에 메모리 관리를 하는 건 요즘으로 치면 연봉별로 돈 관리하는 요령과 비슷했다. 램이 1MB 이하일 때, 2MB일 때, 4MB일 때, 8MB 이상일 때... HIMEM.SYS와 EMM386을 세팅하는 법, 기본 메모리를 최대한 확보하는 법, 메모리가 왕창 많이 있다면 램 드라이브와 디스크 캐시를 운용하는 요령 등.. 그런 게 1990년대 컴퓨터 잡지들이 고급 정보랍시고 많이 다룬 정보였다.
지금으로서는 그저 격세지감이 느껴질 뿐이다. 그 당시에 기본 메모리라는 개념은 돈에다 비유하자면 당장 손에 있는 현금이고, 나머지 확장 메모리는 통장 잔고나 신용카드 같다는 생각도 든다. =_=;;

MS-DOS의 역사를 살펴보면 많은 걸 느낀다. 금수저 출신의 독종에 천재에 똘끼와 운, 엔지니어 기질과 사업가 기질을 모두 갖고 있는 사람이라면 무슨 여건에다 던져 놔도 결국은 성공했겠다 싶다. 공부만 계속했어도 교수나 변호사가 됐을 사람이 결국은 소프트웨어의 황제로 등극해서 교수· 변호사보다 더한 억만장자가 됐으니까.

물론 빌 역시 그 과정에서 언제나 실력만으로 정정당당하게 승부하지는 않았으며, 경쟁자 치사하게 죽이기 같은 짓을 전혀 안 했다는 건 아니다. MS의 모든 기술과 제품이 100% 빌의 머리에서 비롯된 원천기술인 건 아니며, 그가 미래에 대해 예측한 것이 전부 적중한 것도 아니었다. 그래도 그는 자기보다 더 똑똑한 엔지니어들을 한데 통솔하고 이끌어서 시너지 효과를 잘 낼 줄을 알았다. 그리고 실수를 하고 병크를 저지르더라도, 회사를 완전히 말아먹을 정도로 치명적으로 하지는 않았으며 곧 수습했다.

한편, 게리 킬달은 뭔가 스티브 워즈니악 같은 포스가 느껴지는 공돌이로 보이는데, 실력에 "비해" 빛을 못 보고 좀 어이없게 훅 가 버린 게 안타깝게 느껴지기도 한다.
기술만 있고 너무 고지식하기만 하면 저렇게 되기 쉬운데, 나부터가 딱 그런 스타일이라는 게 문제임.. -_-;;

Posted by 사무엘

2016/05/18 08:39 2016/05/18 08:39
,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1228

오늘날이야 우리들의 눈을 현혹하는 온갖 사진과 짤방, 동영상들이 인터넷을 통해 컴퓨터로 현기증 날 정도로 범람하고 터져 나가는 시대이다.
하지만 불과 2~30년 전만 해도 PC는 글이 아닌 그림을 처리하기에는 용량과 성능이 꽤 버거운 물건이었다. 컴퓨터로 뭔가 실사 사진 자체를 구해다 보기가 쉽지 않았다. PC 통신으로 인기 연예인 사진을 단 한 장 다운로드 해서 보는 것조차도 단단히 작정하고 기다릴 준비를 하고서 해야 했다. 그리고 그것도 출처는 종이 화보나 필름 사진 스캔, 또는 아날로그 TV 화면 캡처였다..

21세기에 태어난 애들이 이런 얘기를 듣는 건.. 우리 세대가 부모님에게서 1950, 60년대에 나라가 얼마나 폐허였고 못살았는지를 듣는 것과 비슷한 느낌일 것이다. 아아~ 나도 이런 식으로 올드 타이머 꼰대의 대열에 합류하는구나..;;
그래도 난 옛날 컴퓨터 환경 회상이 좋다. 그러니 얘기를 계속하겠다.

그 시절엔 bmp, pcx를 넘어 gif 정도만 돼도 디코딩이 만만한 작업이 아니었다. 아래아한글 도스용에서 그림을 삽입해 보면 gif는 유독 렌더링이 더뎠다. 그런데 하물며 jpg는... 전용 뷰어가 필요하고 386에 램 얼마 이상, 부동소수점 코프로세서는 필수 이런 걸 요구하는 엄청난 포맷이었다. png 역시 그 당시로서는 신생인 만만찮게 무거운 포맷이었고.

이런 이유로 인해 도스에서 그래픽 뷰어는 나름 단순 텍스트/헥스 뷰어 이상의 유니크함과 전문성(?)을 지녔고 또 그래픽 에디터와는 별개의 입지를 가진 프로그램이었다. GUI 운영체제의 셸이 제공하는 기본 중의 기본, 필수 중의 필수 기능이 그때는 그렇게나 특별한 기능이었다. 도스까지 갈 것도 없이 무려 Windows 95 시절, 웹 브라우저 같은 게 없던 때엔 운영체제 차원에서 jpg 파일을 바로 볼 수 있지 않았다. 그림판은 bmp/pcx 전용이었으니까.;;

그래픽 뷰어는 완전 상업용 제품이라기보다는 셰어웨어로 만들기에 좋은 소재였다. 디렉터리 이동 + 파일 리스트 선택 기능을 구현한 뒤, 사용자가 엔터를 누르면 그 그림을 표시해 주는 게 기본 형태이다.
그런데 그것만으로는 좀 단조로우니 그래픽 뷰어에는 여러 장의 그림을 슬라이드 쇼처럼 보여주는 기능이 응당 추가됐다. 현란한 화면 전환 효과는 덤이고. 요즘 같으면 화면 보호기와 역할이 비슷해졌다.

비주얼 쪽 말고 다른 방면으로는.. 파일 관리 기능이 있다는 점에 착안하여 단순히 뷰어 이상으로 많은 그림 파일들을 일괄적으로 포맷을 변환하고 크기를 보정하고 효과를 주는 기능이 들어갔다. 이건 전문적인 그래픽 에디터와도 기능이 겹치는 구석이 있지만, 이쪽은 드로잉 기능이 없으며 한 파일이 아니라 여러 파일들에 대한 일괄 편집에 더 최적화되었다.
이런 분야에 속하는 프로그램으로 본인은 현재까지 다음과 같은 제품들을 기억하고 있다.

1. Graphic Workshop

사용자 삽입 이미지

모 컴퓨터 잡지/서적을 통해 알게 됐다. 1990년대 초인 꽤 옛날부터 개발되어 온 프로그램이며, 내 기억이 맞다면 GIF를 굉장히 일찍부터 지원해 온 걸로 유명했다.
스크린샷을 보면 알 수 있듯, 전반적으로 셸은 파란 배경의 단순한 텍스트 모드에서 동작했고 단순 표시뿐만 아니라 포맷 변환, 크기 조절 같은 그림 파일 관리 기능도 갖추고 있었다.

1989년에 처음 개발됐는데 91년에 벌써 버전이 6을 넘어간 건 도대체 개발과 버전업이 어떻게 돼 왔다는 뜻인지 모르겠다. MS Word는 다른 제품과 번호를 맞추기 위해서 2에서 바로 6으로 넘어가긴 했다만..;;
개발사인 Alchemy Mindworks라는 회사는 지금도 살아 있으며, 이 프로그램은 Windows용으로 계속 개발 중이다.

2. SEA

사용자 삽입 이미지

그래픽 뷰어 중에서는 느낌이 굉장히 인상적이었다. 일단, 왓콤 C/C++ 32비트 에디션으로 만들어진 덕분에, 게임도 아닌 것이 첫 실행 때 DOS/4GW(도스 익스텐더) 로고가 떴다.
성능면에서는 jpg 파일의 디코딩이 경쟁 프로그램들 중 가장 빠르다고 자처했다. 그림뿐만 아니라 소리 파일 재생이 됐으며, 동영상도 AVI 중에 1990년대 중반 런렝쓰 정도의 간단한 방식으로 압축 된 건 바로 재생 가능했다.

스크린샷을 보면 알 수 있듯 일괄 변환과 슬라이드 쇼 기능 정도는 물론 갖추고 있었으며,
이 모든 것에 더해서 전반적인 GUI 껍데기도 NextStep 운영체제를 흉내 낸 듯한(바탕에 검정 제목 표시줄) 상당한 고퀄이었다.
여러 모로 인상이 좋고 장인 정신이 느껴지는 잘 만든 프로그램이었다. 비등록 셰어웨어 버전도 첫 실행 때 '등록 해 주세요. press any key'가 뜨는 것 말고는 별다른 제약이 없어서 상당한 대인배이기까지 했다.

3. ACDSee

운영체제에 gif/jpg/png급 그림 파일을 보는 기능이 자체적으로 없던 Windows 95~98/2000 시절에는 개인적으로 이 프로그램을 유용하게 썼다. 이름이 똑같이 '씨'인데 앞의 도스용 프로그램은 sea이고 요 프로그램은 see이다.
얘도 한때는 내가 운영체제를 새로 설치한 뒤에 MDIR만큼이나 곧장 설치하는 필수 프로그램 중 하나였다. 굉장히 유용하게 썼다. SEA의 Windows 버전이나 마찬가지였는데, 해당 기능을 운영체제가 흡수한 뒤에는 정말 자연스럽게 존재감이 싹 없어져 버렸다.

그 첫 신호탄은 Windows에 IE 웹브라우저가 포함돼 들어가면서 기본적인 그래픽 뷰어 문제는 사실상 제공되기 시작한 사건이다. 월드 와이드 웹이라는 게 글과 그림으로 이뤄져 있으며 웹브라우저는 그 자체가 훌륭한 단백질 공급원은 아니고 훌륭한 그래픽 뷰어였기 때문이다. 단, IE는 옆 파일을 바로 열람하는 기능조차 없고 진짜 보는 것 하나만 가능하기 때문에 전문 뷰어/슬라이드 쇼 프로그램이 여전히 존재 의미가 있었다.

한 디렉터리 안에 있는 그림 파일들을 IE 창에서 쭈욱 열람하기 위해서 그 디렉터리를 기준으로 <img src="...."/> 태그를 쭈욱 나열하는 html 파일을 '생성하는 프로그램'을 짜서 개인적으로 활용했던 기억이 있다. 물론 이건 썸네일만 읽어들이는 게 아니라 파일들을 몽땅 한 페이지에다 읽어들이는 것이니 성능면에서는 좀 안습한 짓이긴 하다.

그리고 둘째 확인사살은 Windows XP이다. 얘부터는 탐색기 내부의 파일 리스트에서 그림 썸네일을 보는 편의 기능이 크게 강화되었으며, 그럭저럭 가볍고 괜찮은  그래픽 뷰어까지 내장됐기 때문이다. 그러니 별도의 싸제 그래픽 뷰어 프로그램에 대한 필요는 거의 사라졌다. 이런 이유로 인해 기존의 그래픽 뷰어들은 생존을 위해서 포토샵 같은 이미지 보정 기능을 더 강화한다거나 디지털 카메라 사진 관리 같은 더 차별화되고 전문적인 영역으로 넘어갔으며, 내 기억 속에는 현업에서 다들 물러나고 추억의 영역만 남게 되었다.

한때는 Paint Shop Pro에 내장돼 있는 Browse 기능도 유용하게 썼던 것 같은데 지금은 그냥 MS Office에서도 2003부터 Picture Manager라는 유틸리티가 생겨 있다. 예전에는 희귀했던 기능들이 지금은 다 기본으로 내장되고 대중화가 된 것이다.
단, Windows XP의 기본 그래픽 뷰어는 애니메이션 GIF를 재생하는 것까지도 지원했는데 Vista 이후부터는 그 기능은 없어졌다. 왜 빠졌는지는 알 길이 없다.

여기까지가 그래픽 뷰어 프로그램에 대해 본인이 갖고 있는 추억이다.
하긴, 음악을 듣는 것도 한때 꽤 먼 옛날엔 거원 제트오디오, WinAmp 같은 프로그램을 따로 썼다. 그러다 언제부턴가 그냥 WMP만 쓰지 다른 건 안 쓰게 됐다.
그래도 동영상은 WMP가 코덱과 자막 등 부족한 구석이 많이 있어서 팟/곰 같은 제3자 프로그램이 여전히 살아 있다. 내가 알기로 마소에서 WMP도 거의 IE11만큼이나 이제 더 만들 게 없는지 별로 육성은 안 하는 것 같다.

Posted by 사무엘

2016/05/16 08:32 2016/05/16 08:32
, , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1227

1.
코코아, Win32 API, MFC 같은 플랫폼 종속적인 API를 전혀 쓰지 않고 순수하게 표준 C/C++ 라이브러리 함수만으로 백 엔드 엔진만 만들었다 해도 Windows + Visual C++로 작성한 코드가 안드로이드 내지 맥 같은 다른 플랫폼에서는 곧장 컴파일 되지 않거나, 빌드된 프로그램이 의도한 대로 동작하지 않을 수 있다.

개인적으로는 회사에서 wchar_t 때문에 굉장한 불편을 겪었다. 잘 알다시피 Windows에서는 이게 2바이트이지만 다른 플랫폼에서는 4바이트이다. 플랫폼을 불문하고 2바이트 문자 단위로 동작하는 strcpy, strcat, strlen, printf, atoi 등등은 직접 구현이라도 해야 하는지..? 특히 파일로 읽고 쓰려면 말이다.

C++ string 클래스야 typedef std::basic_string<unsigned short> string16; 부터 먼저 만들어 놓고 썼다지만 그렇게 처음부터 객체를 만드는 게 아니라 raw memory를 다루는 상황에서는 해결책이 되지 못한다.

이런 게 원초적인 애로사항이고 또, 소스 코드 내부에서 유니코드 문자열 상수를 표현하는 방식도 또 다른 난관이다.
언어가 제공하는 L"" 문법은 wchar_t형 기반이다. 그러니 wchar_t 말고 명시적으로 unsigned short 배열에다가는 문자열 상수를 쓸 수 없고 "가"를 { 0xac00, }로 표현하는 식의 삽질을 해야 한다.

거기에다 비주얼 C++은 C++ 소스 코드나 명령 프롬프트가 UTF8과 전혀 친화적이지 않다는 다른 문제점도 있어 더욱 불편하다. 유니코드가 등장하면서 플랫폼별로 문자열을 다루는 방식이 너무 심하게 파편화됐다는 생각이 든다.
문자열을 저장하고 메모리를 관리하는 방식이 난립하는 것 말고(string class!) 문자열을 구성하는 문자를 표현하는 방식 그 자체부터가 말이다.

2.
하루는 Visual C++에서 표준 C 함수만 사용해서 만들어 준 코드를 안드로이드 내지 맥 OS 플랫폼으로 넘겨 줬더니 컴파일 에러가 났다. wcslen 함수가 선언되지 않았다고 꼬장을 부리는데 도무지 원인을 알 수 없었다. strlen은 인식되는데 wcslen은 왜 인식이 안 되는 거지?

그런데 알고 보니 wcslen은 strlen과는 달리 string.h가 아니라 wchar.h에 선언되어 있었다.
Visual C++은 string과 wchar에 wcslen을 모두 선언해 줬지만 타 플랫폼은 그렇지 않았다. 흐음~ 나의 불찰이다.

malloc/free 함수는 stdlib.h에도 있고 malloc.h에도 있다.
memset/memcpy는 string.h에도 있고 memory.h에도 있다.
그런 예가 몇 가지 있는 건 알고 있었지만 wcs* 함수는 Visual C++에만 string/wchar 겸용으로 선언돼 있었던 듯하다.
C 인클루드 헤더는 한 함수가 오로지 한 헤더에만 유일하게 존재하지는 않기도 하다는 것이 흥미롭게 느껴진다.

3.
요즘 표준 라이브러리들의 헤더 파일을 보면 함수의 인자마다 타입과 이름만 있는 게 아니라 소스 코드 정적 분석을 위한 Annotation 정보가 같이 들어있다. 같은 포인터라 해도 이건 읽기 전용, 쓰기 전용.. 쓴다면 어떤 조건으로 얼마만지 써지는지(옆의 인자만큼~) 같은 거.

그래서 함수 하나만 봐도 선언도 정말 덕지덕지 길어졌다. 이 정보들이 처음부터 있지는 않았을 텐데, 그 수많은 API들의 선언에다 일일이 다 기입하는 건 완전 중노동이었을 것 같다.
한때는 정적 분석 기능은 개발툴의 유료 최상급(엔터프라이즈 같은) 에디션에서나 접근 가능한 고급 기능이었는데, 이것도 죄다 무료로 풀리는 듯하다. 유료 GUI 툴킷이 통째로 MFC에 들어갔듯이 말이다.

4.
요즘은 CPU 아키텍처야 x86 아니면 ARM만 살아 남아서 그런지, 이식성을 논할 때 비트 순서, 일명 endian-ness 얘기는 별로 안 나오는 것 같다. 우리 주변에서 흔히 볼 수 있는 x86은 요지부동 리틀 엔디언인 반면, 옛날에 매킨토시의 밑천이던 PowerPC는 빅 엔디언이었다. 트루타입 폰트 포맷이 빅 엔디언 기반인 건 이런 애플의 영향력이 닿아서 그랬던 걸까?

먼 옛날 대학 시절에 터미널에 원격 접속해서 거기서 C 컴파일러를 돌려 봤던 게 본인으로서는 빅 엔디언 컴퓨터를 직접 구경한 처음이자 마지막 경험이다. 큰 자릿수가 앞부분부터 저장되다니 굉장히 신기했다. 이건 앞으로 수동 변속기 차량이라든가 IA64 (Itanium) 컴퓨터만큼이나 앞으로 또 접할 일이 없는 초희귀템으로 남을 것 같다.

최신 CPU인 ARM은 하드웨어 차원에서 endian-ness를 모두 지원하기 때문에 아무 쪽으로든 취사 선택이 가능하다고 한다. 사람으로 치면 완벽한 양손잡이이고, 철도에다 비유하자면 좌측/우측통행 전용 복선 철도가 아니라 어느 쪽으로든 운용 가능한 단선병렬과 비슷한 격이다.
결국은 다 지원하는 것으로 가는구나. 한글 코드에서 조합형/완성형 논쟁, CPU 미시구조에서 CISC/RISC 논쟁, 리눅스에서 그놈/KDE 셸 논쟁도 다 비슷한 방식으로 종결됐듯이 말이다.

비트 순서 같은 하드웨어 특성을 타는 요소 말고 소프트웨어 플랫폼과 언어 차원에서.. 사소하지만 코드의 이식성을 은근히 저해하는 요소는 내 경험상 몇 가지 있었다. 그러니 GUI가 없고 특정 운영체제의 API를 사용하지 않았다고 해서 무작정 이식이 잘 될 거라고 기대할 수는 없다.

5.
당장 떠오르는 건, 64비트 상수를 나타내는 % 문자가 파편화돼 있다(%I64d, %lld). 그리고 long이 Windows에서는 64비트 플랫폼에서도 여전히 32비트이지만 타 플랫폼은 그렇지 않다. 그러니 이식성을 생각한다면, long은 파일 오프셋 계산에 영향을 주는 곳에서는 절대로 구조체 멤버로 쓰이거나 sizeof의 대상이 돼서는 안 된다. (앞서 논했던 char_t도 마찬가지이고!) 그런 데서는 정말 닥치고 int32, uint64처럼 비트수를 명시한 typedef를 쓰는 게 안전하다.

C#이나 Java, D는 아무래도 1990년대 중후반에 PC에서 32비트 CPU 정도는 확실하게 정착한 뒤에 등장한 최신 언어이다 보니, 32/64비트 플랫폼을 불문하고 long이 처음부터 일관되게 64비트였다. 하지만 C/C++은 그보다 훨씬 전부터 컴퓨터 하드웨어의 발전의 격변기와 동고동락했던 언어이다 보니, 저런 깔끔함을 기대할 수는 없는 노릇이 돼 있다.

그리고, fopen에다 주는 옵션에서 r/w/a (+)만 있고 b/t 모드가 지정되지 않았을 때..
Windows는 binary 모드로 동작하는 반면 맥에서는(타 플랫폼은 확인 안 해 봄) 디폴트가 text였다. 멀쩡한 코드가 완전 엉뚱하게 동작하고 파일이 쓰라는 대로 써지지 않고 읽으라는 대로 읽히지 않아서 한창 문제를 추적했더니.. 결국은 이런 데에서 차이가 있었다. 이것도 표준 규격이 정의돼 있지 않나 보다.

말이 나왔으니 말인데, Visual C++은 fopen조차 쓰지 말고 fopen_s를 쓰라고 권한다. printf_s, qsort_s 같은 *_s 물건은 안전하고 편리하긴 하지만 언제까지나 이식 불가능한 Visual C++만의 전유물로 남을지 궁금하다..

strdup와 _wcsdup는 표준처럼 생겼지만 진짜 표준인지 아닌지 알쏭달쏭한 놈이다. 앞에 괜히 밑줄이 있는 게 아니다. _wtoi 이런 것도 Windows를 벗어나면 컴파일되지 않을 가능성이 높은 지뢰이니 strtol, wcstol을 쓰는 게 안전하다.
strtok의 경우 Visual C++은 토큰 컨텍스트를 따로 받는 _s 버전을 추가한 반면, 타 플랫폼은 strtok, wcstok 함수 자체가 그렇게 고쳐진 것도 있다. 이런 것들도 너무 골치아프다.

6.
끝으로, 이건 이식성하고는 큰 관계가 없는 얘기다만..
형변환 연산자인 static_cast는 코드 생성 차원에서 하는 일이 전혀 없거나(base class* → derived_class*, enum → int), 뻔한 값 보정(float → int, char → int), 또는 다중 상속일 때는 컴파일 타임 때 결정된 고정된 상수만치 this 포인터 보정 정도만(derived_class_B* → base_class) 하는 걸로 으레 생각했다.

그런데 다중 상속을 다룰 때 꼭 그런 일만 하는 건 아니다. 포인터가 처음부터 NULL이었다면, 거기서 또 얼마를 뺄 게 아니라 cast된 포인터도 그냥 NULL을 주는 예외 처리를 해야 한다. 과연 생각해 보니 그렇다. 아래 코드를 생각해 보자.

struct A { int a,b; };

struct B { int c,d; };

struct C: public A, public B { int e,f; };

void foo(B *pm) { printf("Received %p\n", pm); }

int main()
{
    C m, *pm=&m;
    printf("Passing %p\n", pm); foo(pm);
    pm=NULL; printf("Passing %p\n", pm); foo(pm);
    return 0;
}

단일 상속과는 달리, 다중 상속에서 passing의 값과 received의 값이 서로 달라질 수 있다고 아는 것은 하나를 아는 것이다.
그러나 NULL일 때는 다중 상속이더라도 언제나 NULL이 유지된다는 것이 함정이다. 우와.. 지금까지 한 번도 그런 경우를 생각한 적이 없었는데.. 꽤 충격적이다. 간단하지만 다중 상속의 보이지 않는 오버헤드를 보여주는 요소 중 하나이다.

Posted by 사무엘

2016/05/13 08:29 2016/05/13 08:29
, ,
Response
No Trackback , 5 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1226

« Previous : 1 : ... 108 : 109 : 110 : 111 : 112 : 113 : 114 : 115 : 116 : ... 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:
3055368
Today:
1604
Yesterday:
2071