아이폰과 상상력

개발자로서 꽤 괜찮은 점이라면, 다른 사람이 만든 프로그램을 사용할 때, 대략의 사용법을 짐작할 수 있다는 것이다. 예를 들어 마우스 오른쪽 버튼을 누르면 당연히 팝업메뉴가 튀어나온다. 프로그래머가 제정신이라면 당연히 그렇게 만든다. 이점은 스마트폰에서도 비슷하게 동작한다. 윈도 모바일6.1을 운영체제로 사용하는 m480(미라지)에서는 화면을 누른 상태를 유지하면, 팝업메뉴가 튀어나왔다. 즉, 윈도모바일에서는 마우스 왼쪽, 오른쪽 클릭을 탭핑 시간으로 구분한다. 그것도 아니라면, 어딘가 관련된 메뉴를 화면에 보여줘야 한다. 이런 식으로, 윈도기반 UI에는 기본적인 룰이 있고, 대부분의 프로그래머는 이 룰을 잘 따른다. 사실, 그것을 거스르기가 더 힘들다.

이제, 아이폰 얘기다. 사람들이 애플의 UI는 직관적이라고 한다. 이 말이 사실로 받아들여질 수 있었던 데에는 하드웨어적 완성도와 운영체제가 받쳐줬기 때문이지만, 확실히 익히기 쉽다. 아마, 내가 개발자가 아니었다면, 그리고 MS의 UI에 익숙하지 않았더라면 더 쉬웠을 것이다. 아이폰에서 iTunes의 다운로드 목록을 지우는 방법을 모르겠다. 또 다운받은 Podcast를 지우는 방법을 모르겠다. 구글을 뒤져보니 혹자는 PC와 연결해서 iTunes에서 지워야 한단다. 그렇게 했다. 그렇지만 다운로드 목록은 지우지 못했다. 사용자 편의성이 좋아 그렇게 호평 받는다는 iTunes를 욕하며 구글을 좀 더 뒤졌다. 해당 항목을 좌우로 쓱~ 문질러주면 된다 길래 해보니 정말 삭제 메뉴가 떴다. 이로서 애플은 지저분한 ‘삭제’메뉴나 버튼을 만들지 않을 수 있었다. 이는 클릭, 클릭으로 동작하는 윈도모바일(적어도 6.5.2까지는)에서는 애당초 구현이 불가능한 방법이다. 윈도개발자인 나로서는 상상하기 힘들다. 그리고 그런 사용자는 분명히 많다.

어느 것이 좋고 나쁘고를 떠나서, 한가지 분명한 점은 MS의 UI가 나 상상력의 울타리로 작용했다는 점이다. 그리고 그것을 아이폰이 약간 걷어줬다. 이런 경험을 나뿐만이 아닌 많은 사람이 하게 되면서 더 많은 것이 바뀔 것이다. 나는 이런 변화를 즐겁게 바라볼 것이고, 좀 더 변하기 위해서 맥북도 질러야겠다. ㅋㅋ

WPTouch 설치

시대적 요구(?)에 의해서 WPTouch 를 설치했다. 이제는 아이폰에서 아주 예쁘게 보인다. 단, 소스코드는 잘리는 문제가 있는데…, 이런때에는 하단의 옵션을 끄면 일반 브라우저에서 보는대로 보인다.

이상은 대체로 아이폰 유저들을 위한 얘기.
결론? 대세는 아이폰.
이 포스트도 아이 폰에서 WP2어플로 작성 ㅋㅋ

앞으론, 아이폰앱 개발과 관련된 포스트도 쓸 수있는 기회가 있기를…

직접호출, boost::bind, mem_fun의 속도비교

‘boost::bind를 맘 내키는 대로 써도 될까?’라는 의문에 각 경우의 속도를 비교해보기로 했다.

우선, 재물로 사용될 클래스를 만들고…

class test_class
{
public:
    test_class()
    : _i(10)
    {}

void    show(int i)
{
    ++_i;
}

private:
    int _i;
};// class test_class

아래는 테스트코드의 일부. TIME_DURATION은 포함되는 블록의 수행시간을 마이크로 초단위로 돌려준다.

const int   repeat_num  = 100000;
hs_int64    d;

test_class  t;

TIME_DURATION(d)
{
    for (int i = 0; i < repeat_num; ++i)
        t.show(i);
}
cout    << "direct call: " << d << endl;

TIME_DURATION(d)
{
    for (int i = 0; i < repeat_num; ++i)
        boost::bind(&test_class::show, &t, i)();
}
cout    << "boost.bind call: " << d << endl;

boost::_bi::bind_t, boost::_bi::list2, boost::arg<1> > >   t_mem_boost = boost::bind(&test_class::show, &t, _1);
TIME_DURATION(d)
{
    for (int i = 0; i < repeat_num; ++i)
        t_mem_boost(i);
}
cout    << "boost.bind call via instance: " << d << endl;

TIME_DURATION(d)
{
    for (int i = 0; i < repeat_num; ++i)
        std::mem_fun(&test_class::show)(&t, i);
}
cout    << "mem_fun call: " << d << endl;

std::mem_fun1_t  t_mem_stl   = std::mem_fun(&test_class::show);
TIME_DURATION(d)
{
    for (int i = 0; i < repeat_num; ++i)
        t_mem_stl(&t, i);
}
cout    << "mem_fun call via instance: " << d << endl;

결과

direct call: 658
boost.bind call: 9152
boost.bind call via instance: 4034
mem_fun call: 1972
mem_fun call via instance: 950

테스트를 반복해도 결과는 대동소이하다. boost::bind는 직접호출보다 10배 이상 느리다. 그나마 mem_fun이 좀 낮다.
따라서…

‘boost::bind를 맘 내키는 대로 써도 될까?’ -> 살살 쓰자

나의 프로그래밍 언어 사용기

YDN 블로그 오픈 이벤트도 있고 하니, 블로그에 포스트 수라도 늘릴 겸, 내가 사용한 프로그래밍 언어들에 대해서 이야기하고자 한다. 심각하지 않게~

대략 87년쯤? 애플이라고 구라 치는 컴퓨터가 집에 들어왔다. 맞다. 교육용 컴퓨터라고 붐이 일어났던 그때다. 여기저기 컴퓨터학원이 생기고, 컴퓨터라는 물건은 공부하기 위해선 꼭 필요한 그런 거였다. 물론, 그런 게 아니라는 사실이 밝혀지는 데는 아주 짧은 시간만이 필요했다. 어쨌든, 그렇게 해서 내가 처음 접한 프로그래밍 언어는 BASIC이었다. 뭐, 사실은 그게 뭔지도 몰랐다. 그냥 컴퓨터를 사면서 딸려온 책에 나온 내용을 그대로 치면 화면에 몇 가지 간단한 도형이 그려지는 그런 프로그램이었다. 몇 년이 지나서는 BASIC으로 간단한 텍스트 게임을 만드는 수준이 되었다. 상황에 따라 몇 가지 선택이 주어지고 이야기가 진행되는 그런, – -; 그 다음은? 컴퓨터는 교육용이 아니라는 사실이 밝혀졌으므로 사용시간에 제한이 가해졌고, 중간에 잠깐 Borland C++을 접할 기회가 있었지만, 도무지 알 수가 없어서 포기. 그리고 대학에 갔다.

요즘은 Java를 먼저 배우는 게 일반적인 것 같던데, 내가 대학교에 입학했을 때는 C가 그 자리에 있었다. 내가 할 수 있었던 건 별로 없었다. 결정적으로 대학은 시간을 너무 많이 줬고, 그래서 감사히 놀았다. 그나마 다행인건 C++에 관심을 가지고 찝접댔다는 건데, 덕분에 1학년 겨울방학에는 Borland C++ Builder를 사용해서 뭔가 제대로 동작하는 프로그램을 만들 수 있었고, 당시 천리안에서만 5000회 이상의 다운로드를 기록했다. 이때부터 조금씩 프로그래밍 공부에 불이 붙기 시작했던 것 같다.

이후에 Borland Delphi를 잠깐 했지만, C++에 이미 익숙해진 터라 Object Pascal의 낯섦으로 인해 군대 가기 전까지의 숙제는 모두 Borland C++ Build로 처리했다. 일단, GUI가 들어가면 먹어줬다.

군입대 전까지 잡아둔 두 가지 목표가 있었는데, 하나는 Borland C++ Build로 세금계산서를 프린트하는 프로그램을 만드는 것과 Assembly로 바이러스를 만드는 거였다. 세금계산서는 실패했다. 내 수준으로는 쉽지 않았다. 그럼 바이러스는 성공했나? 굳이 말하자면 그렇다. 집에 있는 책과 자료란 자료는 다 뒤져서 만든 한 페이지짜리 Assembly코드는 간단히 자신의 디렉터리의 다른 COM파일을 간염 시킨다. 끝. 그래서 굳이 말한 거다.

웃기지만, 군대에서 프로그래밍을 공부하는 제대로 된 방법을 터득했다. 난 극적으로 Borland C++ Builder에서 Visual C++로 전향했다. 이미 Borland는 지는 해였다. 놀랍게도 MSND을 누군가가 우편으로 보내줬다. 고맙다고 전화했더니, 살다 보면 이런 행운도 있는 거란다. 그렇게 MSDN을 보는 방법을 알았고, 물어볼 사람이 따로 없기에 될 때까지 반복해야 했다. 그런 노력으로 빌 형의 품에 안겼다.

내가 웹을 처음 접한 게 정확히 95년이다. 모자익으로 겨우 접속한 배트맨 사이트의 그림은 엄청나게 감동적이었는데, 당시 나에게 도메인이라는 개념이 있었다면, 지금쯤 떵떵거리며 살 수 있었을 지도 모른다. 내 첫 번째 웹 스크립트는 PHP가 당첨됐다. C와 문법이 비슷하다는 게 이유였다. 근데, 이건 웹에 대한 개념을 이해하는 것이 더 힘들다. 결국 간단한 방명록 정도까지가 한계였다.

제대후의 주 무기는 Visual C++이었다. 아 물론 여전히 Borland C++ Build도 사용했고. 나중에 C#이 추가됐다. C#은 전천후처럼 생각하는 건 다 .Net Framework에 들어가있었다. 그리고, 지금에 와서는 그게 너무 많아서 감당이 힘들 지경이다. 현재도 C#은 유용하게 사용되고 있으며, 대부분의 툴 작업에는 C#을 쓰려고 한다. 왜? 빨리 만들 수 있으니깐~

아, 이제서야 말하지만 난 게임 서버 프로그래머다. 대학 때 졸업한 선배에게 우연히 게임 프로그래밍을 배우기 시작한 것이 계기가 되어서 여기까지 왔다. 아마 나의 사회생활 경험을 이해하기 위해서는 이런 배경이 약간 필요할 것 같아서 말해둔다.

첫 번째 직장에서는 Visual C++도 아닌 리눅스에서 g++, gdb, vi로 작업했다. 결론부터 말해서, 이거 매우 큰 도움이 됐다. g++이야 그렇다 치고, gdb라는 건 꽤 특이한 경험이었다. 그래서 난 요즘도 리눅스를 쓸 때 굳이 X-Window를 깔지 않는다.

이때쯤부터 Ruby가 우리나라에서 인가를 얻기 시작했다. 자고로 프로그래머는 잘 쓰는 스크립트언어 하나는 있어야 한다는 생각에 Ruby를 배웠다. 이때부터 단순 반복작업이나 루비로 할 수 있는 건 죄다 루비로 했다. 게임 클베의 DB내용을 가공할 일이 있었는데, 내가 SQL에 능통하지 않은 관계로 루비로 작업을 했다. 퇴사 후에 회사에서 전화가 와서 그때 그 통계를 어떻게 뽑았는지 물었다. 아마 그건 SQL로 작업하기 힘들거나 불가능 했던 것 같다.

더불어 RoR(Ruby On Rails)에도 손을 대기 시작했는데, 이 관심은 이내 사그라지다가 최근에서야 다시 타올랐다. 그리고 다시 사그라지는 중이다. – -;

세상은 멀티코어의 시대가 되었고, 함수형 프로그래밍언어가 새롭게 각광을 받기 시작하면서 이런 시류에 휩쓸려 Erlang에 손을 댄다. 절차 형 언어와는 전혀 다른 개념에 도무지 이해가 쉽지 않다. CouchDB같은 게 나오는걸 보면 분명히 확산추세인 것 같긴 한데, 다음 책을 기다리는 중이다.

‘실용주의 프로그래머’에서 매년 하나의 언어를 배울 것을 권장하는 바람에 못이기는 척 따라고 있는 중이다. 대학교 때 코볼수업 – 나 때는 이런 것도 있었다! – 을 담당하시던 교수님이 ‘가능한 많은 언어를 접해보는 것이 좋다’라고 했던 말이 기억난다. 마스터할 필요는 없다. 새로운 언어는 새로운 사고방식을 키워준다. 내 경험이 그렇게 말해주고 있다. C/C++만이 전부였을 때는 포인터와 템플릿이 당연했다. 당연히 컴파일 해야 했고 약간의 속도와 메모리에도 신경이 쓰였다. 스크립트언어로는 왠지 그런데 좀 덜 신경 쓰고 코딩을 해도 괜찮을 것 같다. 게다가 많은 스크립트 언어들이 OOP를 느슨하게 적용한다. C++에서는 당연히 안 되는 것도 Ruby나 Python에선 가능했다. C/C++도 Java도 또 다른 언어도 어느 정도 비슷한 면이 있었기에 배우는데 걸리는 시간이 길지는 않았다. 그렇지만 Erlang는 완전히 다른 세상이었다. 학교에서 배우고 별로 생각해보지 않았던 ‘재귀’라는 개념에 대해서 다시 생각해봐야 했고, 재할당이 불가능하다는 황당한 원칙도 있었다. PHP나 RoR을 들여다 보면, 웹이라는 분야가 얼마나 방대한지 알게 된다. 나 같은 사람이나 다루는 줄 알았던 C/S개념은 웹에서는 너무 당연하게 사용하고 있다. 게다가 훨씬 더 복잡하다.

앞으로도 계속 새로운 언어에 도전해볼 생각이다. 이것은 마치 새로운 외국어를 배우는 느낌인데, 차이점이라면 프로그래밍 언어가 훨씬 더 쉽고 더 빨리 배울 수 있다는 것이다. 그리고 확실하게 자리잡은 생각이 있다. 프로그래밍 언어에 좋고 나쁨은 없다. 할 수 있는 언어로 빨리 일을 하기만 하면 그만이다. 바로 이것.

C/C++ 주 언어
Ruby GUI가 필요 없는 작업 및 각종 단순작업
PHP 첫사랑 웹 스크립트
Java 왠지 별로 정이 가지 않음
C# 모든 툴은 C#으로!
Python Ruby를 대체하기엔 특별히 잘난 게 없어 보임
Erlang 첫 번째 함수형 언어

파이썬으로 소스코드(.h, .cpp) 줄(line) 수 세기

파이썬 배우는 기념으로 만든 소스(.h, .cpp)의 줄 수 세는 프로그램.
현재 디렉토리를 포함한 모든 하위디렉토리에 속한 소스의 줄 수를 보여준다.

# -*-coding:utf-8-*-
import os

def count_line(filename):
	file	= open(filename)
	line_num	= 0
	while (file.readline()):
		line_num	+= 1
	return line_num

def count_code_lines(dirname):
	file_line_list	= []
	filenames	= os.listdir(dirname)
	for filename in filenames:
		filename	= dirname + '\\' + filename
		if (os.path.isdir(filename)):
			file_line_list	+= count_code_lines(filename)
		else:
			if ((len(filename) > len('.h') and filename[-2:] == '.h') or 
				(len(filename) > len('.cpp') and filename[-4:] == '.cpp')):
				file_line_list.append((filename, count_line(filename)))
	return file_line_list

def get_dir_list(path):
	dir_list	= []
	if (os.path.isdir(path)):
		dir_list.append(path)

	header	= os.path.split(path)[0]
	if (header == ''):
		return dir_list
	else:
		dir_list	+= get_dir_list(header)

	return dir_list

file_line_list	= count_code_lines('.')

dir_line_dict	= {}

for filename, line_num in file_line_list:
	dir_list	= get_dir_list(filename)
	for dir in dir_list:
		if (not dir in dir_line_dict):
			dir_line_dict[dir]	= 0
		dir_line_dict[dir]	= dir_line_dict[dir] + line_num

dirnames	= dir_line_dict.keys()
dirnames.sort()

for dirname in dirnames:
	print "%10d %s"%(dir_line_dict[dirname], dirname)

출력예 : 뭐, 대략 이런식

      8388 .
       409 .\MemoryPool
       136 .\MemoryPool\profiler
       862 .\PicTest
       687 .\SimpleMFC
       403 .\SimpleMFC2
      1627 .\SimpleTest
       142 .\SimpleTest2
        59 .\UDPClient
       155 .\UDPServer
       963 .\WebViewer
       112 .\cliWrap
        19 .\cppLib
      2950 .\rvo_test
       136 .\rvo_test\profiler
       472 .\rvo_test\srv_cntr
      2114 .\rvo_test\sti

‘못해요~’

단언컨대, 프로그래밍이란 분야에서 할 수 없는 것이라곤 없다.

아이디어에 문제가 있을 수는 있을지언정, 분명, 그것을 구현할 수는 있다.

‘이런걸 만들 수 있을까요?’라고 물었을 때, 무턱대고 ‘그런 건 만들 수 없어요.’라고 대답하는 프로그래머는 그것을 구현할 능력이 없는 것이다.

그래서 난, 함부로 못하겠다고 대답하지 못한다.

C++로 만든 라이브러리를 C#에서 사용하기

내가 만든 라이브러리가 제대로 동작하는지, 그리고, 이 라이브러리는 사용하는데 있어서 문제가 없는지를 확인하기 위해서, 이를 사용한 테스트 클라이언트를 만들기로 했다. 단, 여기에 C#을 사용하고 싶었다. C#에서 간단히 처리할 수 있는 문제를 가지고 MFC와 씨름하면서 시간을 허비하기는 싫었기 때문에.

몇 가지 방법 중에 내가 선택한 방법은 C++/CLI로 C++라이브러리를 감싼 다음 이를 C#에서 사용하는 것이다. 이 방법을 선택한 이유는 순전히, 시도해본 다른 방법이 모두 실패했기 때문이다. 방법이 없다 라기보다는 내가 잘 모르고 익숙하지 않아서 그렇다. 그렇다고 C++/CLI를 사용하는데 익숙한가 하면, 그것도 아니다. 난 C++/CLI는 정말인지 필요 없다고 생각한다. 딱 한가지만 빼고. 바로 C++라이브러리를 감싸는 것. 하여튼, 난 C++/CLI를 하나도 몰랐다. 지금도 잘 모르는 상태이기 때문에, 아래에 내가 설명하는 내용에는 다소의 오류가 있을 수도 있음을 알아주기 바란다.

C++/CLI는 C++의 문법을 이해한다. 이 말은 C++/CLI에서 Unmanaged Code를 사용할 수 있다는 의미이다. 따라서 C#이 C++/CLI의 문법을 100% 이해할 수는 없다. 기본적으로 C#은 Managed Code이기 때문이다. 따라서 C++/CLI로 C++라이브러리를 잘만 감싸면, C#에서 아무런 수고 없이 이를 사용할 수 있다. 참고로 내가 사용한 Visual Studio의 버전은 2005이다.

Visual C++의 CLR타입 Class Library 프로젝트를 생성하고, C++로 만든 라이브러리를 포함시킨다. 사실, 이것은 Unmanaged C++을 사용할 때의 라이브러리 사용과정과 전혀 다르지 않다. 이제부터 할 일은 C++라이브러리 중에서 노출할 필요가 있는 인터페이스들을 Managed C++로 작성해주기만 하면 된다. 이 글의 주요 주제 되겠다.

C++의 데이터타입은 C++/CLI에서 아래의 표와 같이 바꾼다.

Unmanaged Data Type

Managed Data Type

Ref.

class

ref class

struct

value struct

enum

enum class

std::string

String^

PtrToStringAnsi()

std::map

Dictionary^

std::vector

List^

std::list

List^

function pointer

delegate

반드시 이와 같이 할 필요는 없다. std::vector를 Array로 바꾸어도 전혀 상관없다. 목표는 C++에서 데이터를 다루듯이 C#에서 이를 다룰 수 있도록 하는 것이다.

C++/CLI의 struct는 C++과는 달리, value-type으로만 사용된다. reference-type으로 사용하기위해서는 class를 사용해야 한다.

ref class로 선언되지 않은 클래스는 GC(Garbage Collection)의 관리를 받지 않으며, Unmanaged Code이다.

C++/CLI에서의 ^는 C++의 *에 해당한다. 따라서 ^형으로 선언된 변수는 gcnew키워드로 생성해야 한다. gcnew로 할당된 메모리는 GC가 자동으로 해제하므로, 그에 대해 신경 쓸 필요 없다.

Unmanaged String은 Managed String에 직접 대입될 수 없으므로, PtrToStringAnsi()함수로 사전에 변환되어야 한다. 다음은 Managed String과 Unmanaged String사이에 사용되는 매크로이다.

C++라이브러리에서 사용되는 함수 포인터는 C++/CLI에서 적절한 델리게이트로 바뀌어야한다. GetFunctionPointerForDelegate()함수를 사용할 수도 있지만, 나의 경우는 좀 더 간단하게, Unmanaged Code로 작성한 콜백함수에서 Managed Code로 작성한 콜백함수(델리게이트)를 호출했다. 가장 까다롭게 생각했고, 실제로 시간도 많이 잡아먹은 부분이 콜백함수의 처리였지만, 의외로 싱겁게 끝나버렸다.

이렇게 만들어진 라이브러리는 C#에서 바로 사용할 수 있다. 모든 인터페이스를 Managed Code로 재 작성 해야 한다는 번거로움이 있긴 하지만, 적어도 내 생각에는 이것이 가장 무난하고 또, 만만한 방법이라고 생각된다.


2012.01.31 추가.

위의 매크로는 VS2008에서는 동작하지 않는다. 참조


2012.12.04 추가.

예제

Critical Section Block

다음은 멀티쓰레드 프로그래밍에서 부지런한 프로그래머가 흔히 사용하는 코드의 일부이다. 

알다시피 이와 같은 방법은 코드의 수정을 복잡하게 만들고, 데드락을 피하기 위해서 락의 잠금과 해제 쌍을 완벽히 유지해야 하는 부담도 가지고 있다. Exception이나 갑작스런 흐름의 변화는 이러한 부담을 가중시킨다. 결정적으로…, 귀찮다.

그래서 조금 더 게으른 프로그래머는 auto_ptr을 흉내 낸 클래스를 만들어 사용한다.

크리티컬섹션의 범위가 좁은 경우에는 – 그렇다! 보호해야 하는 것은 데이터이지 함수가 아니다 – AutoCriticalSection타입의 변수의 범위를 제한해 주어야 한다.

위 코드는, 그것을 아름답지 못하게 만드는 두 가지 문제점 있다. 첫 번째는, AutoCriticalSection의 변수 명을 사용자가 선택해야 한다는 것이고, 두 번째는 블럭이 의미하는 바를 직관적으로 알아차리기 어렵다는 것이다.

아래는 이를 해결하기위한, 좀 더 많이 게으른 프로그래머의 코드이다.

두 가지 문제점을 개선한 이 코드에는 두 가지 아이디어가 녹아있다.

첫 번째는, 가독성있는 블록을 사용하기 위해서는 기존의 문법에서 방법을 빌린 것이다. 처음에는 이를 위해서 for문을 사용했다. 그러나 loop를 한번만 돌게 하기 위해서 CriticalSectionContainer클래스에 추가적인 변수가 필요했고, 블록 내에서 break와 continue를 사용할 수 있는 어색함이 남게 된다. 사소한 문제지만, 이는 변수 하나에 해당하는 양의 메모리와 한번의 점프 오퍼레이션이 소모된다. 그래서 if문을 사용했고, if문에서 참, 거짓을 판단하기 위해서 bool 연산자 오버로딩을 사용한 것이 두 번째 아이디어다.

다음은 이를 어떻게 사용하는지 보여준다.

블록이 의미하는 바가 무엇인지 분명히 나타나며, 사용자는 새로운 변수에 대해서 고민하지 않아도 되며, 이를 위해서 희생해야 하는 성능상의 손실은 if문 내에서 발생하는 한 번의 비교뿐이다.

부라보~

Google Chrome

모자익으로 영화 배트맨의 웹사이트를 열 때, 그 희열을 아직 잊지 못한다. 당시에는 모뎀을 통해서 그렇게 화려한 이미지가 화면으로 바로(지금 생각하면 무척 느린 속도지만) 보여질 수 있다는 것 자체가 놀라움이었다. 모자익 이후에 웹브라우저 시장을 장악해 버렸던 넷스케이프의 제작자는 제 2의 빌게이츠가 확실한 것 처럼 떠들어댔지만, 빌게이츠의 익스플로어에 의해서 더 이상 넷스케이프를 보기 힘들어진 요즘에는 뭘 하는지 모르겠다.

그렇게, 오페라가 가끔 노래 부르고 사파리도 자기가 재미있다며 불렀지만, 인터넷을 하기 위해선 당연히 익스플로어가 필요한 줄 알고 지냈다. 영원할 줄 알았던 익스플로어의 점유율은 파이어폭스가 공개되면서 흔들리기 시작했다. 파이어폭스의 탭브라우징을 처음 사용해본 나는 너무 감동해서, 티셔츠와 스티커, 포스터를 주문해버렸다. 액티브액스때문에 가끔은 익스플로어가 필요할 때도 있긴 했지만, 그 잠깐의 결제순간을 빼고는 언제나 파이어폭스를 사용하게 됐다. 익스플로어에도 탭브라우징이 기본으로 추가됐지만, 이미 늦었다.

파이어폭스3가 나왔다. 다운로드회수 신기록을 세웠지만, 어찌된 영문인지 나의 컴퓨터에서는 멈추는 현상이 꽤 자주 생겼다. 메모리 누수현상도 고쳐졌다는데, 왜 유독 나에게만큼은 많은 메모리를 요구하는지도 모르겠다. 확실히 이에 관련한 문제가 보고되고 있는 듯 했지만, 확실한 해결책을 찾지는 못했다. 그래도 익스플로어보단 좋으니 계속 사용했다.

Google Chrome 크롬? 구글에서도 웹브라우저를 만들었다. 그냥 한 번 다운받아서 실행했다. 지금에서 생각해보면, 만약, 그러지 않았으면 정말 후회했을 뻔했다. 체감속도가 파이어폭스보다 빠르다. 그리고 구글답게 정말 필요한 기능만 눈에 띈다. 기존의 웹브라우저 인터페이스에 익숙해져 있으니, 이게 웹브라우저가 맞는가 싶기도 하다. 구글의 웹사이트를 열어보면 데스크톱 어플리케이션의 실행되고 있는 것처럼 보인다. 그만큼 인터페이스가 단순하고 색감이 통일되어있다.

통계의 의하면 (http://marketshare.hitslink.com) 2008년 9월의 웹브라우저 시장점유율은 익스플로어가 70%를 간신히(?) 넘는 수준이고 파이어폭스가 20%정도이다. 얼마나 빠르게 크롬이 그 틈을 비집고 들어갈 수 있는지의 가장 중요한 요소는, 얼마나 빨리 베타딱지를 떼어내는가에 달려있다고 본다. 그 후에는 꽤 빠른 속도로 점유율을 늘려갈 수 있을 듯 하다. 유럽에 비해 높았던 북미의 익스플로어 점유율이 떨어질 날도 많이 남은 것 같지 않아 보인다.

빨리 정식버전을 내놔라!

Secure CRT Functions

Visual C++ 2005에서는 CRT함수들이 ‘_s’ 꼬리를 달고 새로 작성됐다. 대표적인 특징이라면, 버퍼의 크기를 파라미터로 넘겨준다는 것인데, 예를 들어 memcpy함수의 경우 destination buffer의 크기를 명시하는 값이 파라 미터로 추가되는 식이다. 따라서 memcpy_s함수의 프로토타입은 다음과 같이 선언된다.

감히, MSDN을 무시하고 이런 함수를 사용한다면…, 적어도 나의 경우에는, 당연히 Buffer Overflow를 방지할 수 있도록 수정된 것이라고 기대했다. 나라면 분명히 그렇게 했을 것이다. 그러나 Microsoft는 그렇게 하지 않았다.

It should also be noted that the secure functions do not prevent or correct security errors; rather, they catch errors when they occur. They perform additional checks for error conditions, and in the case of an error, they invoke an error handler. ((Security Enhancements in the CRT , MSDN))

즉, 에러를 보안오류를 해결해주진 않고, 그 에러에 대한 처리를 할 수 있도록 해준다는 것이다. MSDN을 좀 더 살펴보면, _set_invalid_parameter_handler함수를 사용한 예제가 나오긴 한다. 근데, 그렇게 하는 게 정말 좋은 거야?

결론…,
감히 MSDN을 무시해? 넌 당해도 싸!