일본에서 일하는 행복한남자
by 필라르
rss

skin by 이글루스
2004년 03월 30일
프로그램, 프로그래밍, 프로그래머
우리는 프로그래밍을 통해 프로그램을 만드는 프로그래머들이다. 하지만 이런 기본적인 것들을 무시한 채 지내는 것에 익숙해진지 이미 오래다. '프로그래머' 자의식의 종말과 왜곡을 목전에 두고, 다시금 출발점으로 돌아가 우리의 존재론적 가치와 지향점 등에 대한 화두를 회복해야 할 것이다. 인간이란 유일하게, 자기 자신과 자신이 하는 일을 관찰하고 반성할 수 있는 동물이기 때문이다.

김창준 (마이크로소프트웨어 2001년 4월호) 2001/04/17

이 글은 프로그램과 프로그래밍, 프로그래머에 대한 매우 '일반적'인 글이다. 즉, 특정 언어의 최적화 기술이라든가, 특정 도구의 활용법 같은 특수하고 한정된 대상에 국한된 것이라기보다는 일반적인 프로그래밍과 그 수련에 대한 것이고, 이것은 좀더 보편적으로 모든 지식에 일부 적용될 수 있다. 따라서, 이 글은 '일반적 지식론 적용의 한 가지'라고 불러도 무방할 것이다. 즉, 여기에 나오는 '프로그래머론'은 철저하게 '일반 지식론'의 성립하에서 자연스레 도출된 것이며, 어느 한 부분도 '일반 지식론'을 조금도 부정하지 않는다.
또 이 글은 어떤 것이 '좋은' 프로그램인지, 누가 '훌륭한' 프로그래머인지에 대한 근본적인 판단근거와 기준을 제공할 것이며, 이러한 기본적인 것들에 대한 여러분 스스로의 관심을 촉구하는 데 목적이 있다. 따라서 글에서는 주로 '뼈대'에 해당하는 것을 다룰 것이며, 그 설명을 위한 방편으로서의 '살'이 들어올 수는 있으나 결코 이 글 자체가 그런 '살'의 구체적 설명을 위한 것이 아님을 미리 밝힌다. 다시 말해 화면에 라디오 버튼을 출력하는 방법이라든가, 패킷을 보내는 방법, 혹은 멀티쓰레딩을 할 때 커널에서 어떤 변화가 일어나는지 등에 관한 내용은 기대할 수 없을 것이다.
서두가 조금 위압적이고 단언적인 선언문의 꼴이 돼버렸는데, 독자들에게 고자세를 취하거나 겁을 주려는 의도는 전혀 들어 있지 않다. '뿌리'가 확실해야만 그 '가지'가 바로 자랄 수 있다는 생각에 다소 엄격한 언어를 사용한 것 뿐이다. 사실 이 바닥에서는 '가지'를 다루는 글이 잘 팔린다. 물론 실상 지면에 쏟아져 나오는 대다수가 가지나 이파리류의 글이다(이런 것도 분명 중요한 작업이긴 하지만). 이로 인해 이리저리 유행에 휩쓸리는 것도 많이 보게 된다.
조금 동떨어진 얘기일지 모르겠으나, 유행(fashion)이란 말이 나온 김에 패션 이야기를 잠시 해야겠다. 필자가 가장 존경하는 패션 디자이너로 가브리엘 본헤어 샤넬(Gabrielle Bonheur Chanel)이 있다. 그는 21세기를 사는 우리가 입는 옷의 기본 구조를 결정한 사람이자 패션의 교과서다. 한마디로 삶의 양식과 문명을 변화시킨 사람이다. 세상에 끼친 그의 영향이 이렇게 클 수 있었던 것은 오히려 일시적 유행에서 동떨어져 있었기 때문이 아닐까 한다. 강호에서 유행에 맞춰 나가는 디자이너는 부지기수다. 하지만 자신의 모드를 고수하며 유행에 물들지 않고 나름의 지속적 변화를 꾀하는 디자이너는 소수다. 그들이 세상을 바꾼다. 그들은 근본적으로 '옷'과 '패션'에 대한 화두를 늘 놓치지 않는 사람들이다. 아직까지도 서점에서 자신의 위용을 뽐내고 있는, 70∼80 년대 이전에 초판으로 출간된 컴퓨터 서적들을 알고 있는가. 불과 일이 년만 지나도 고서 신세가 되고, 하루에도 수십 권의 책들이 명멸하는 컴퓨터 서적의 전국시대에 무엇이 이토록 오랜 가치를 지니도록 했을까. 필자는 이것을 근본과 뿌리에 대한 지속적인 반성에서 비롯됐다고 본다.

@어원학적 고찰

세계에서 가장 많이 팔리는 예술 서적은 곰브리치(E. H. Gombrich)의 「예술 이야기(The Story of Art)」다. 예술 전반에 걸쳐 역사적인 흐름을 따라가며 그림과 함께 독자들이 예술을 직접 느끼고 체험할 수 있도록 도와주는, 그야말로 예술 개론서로는 '탁월한' 책이다. 그런데 이 책의 서두부터가 심상치 않다.

"사실 예술이라고 하는 것은 없다. 오로지 예술가들이 있을 뿐이다."

웃기지 않은가. 예술 이야기라는 책의 첫 문장이 '예술은 없다'는 것이니 마치 종교 경전에서 첫 문장이 '신은 죽었다'로 시작하는 것과 별반 차이가 없어 보인다. 곰브리치는 여기서 대명사로서의 예술, 즉 첫 글자가 대문자인 예술(Art)을 지칭한 것이다. 이것은 어떤 고정적이고 단일한, 천상 어딘가에 그 완벽한 원형이 고이 간직되어 있을 존재로서의 예술은 없음을 의미한다. 어떤 그림을 보고 좋아하는 아이에게 "네가 지금 좋아하는 그건 예술이 아냐!"라고 핀잔을 주는 것만큼 잔인한 행위도 없다. 물론 더 잔인한 것은 예술가가 고통 속에 출산한 예술품을 두고 "이건 예술이 아냐!"라고 외치는 대중일지도 모르겠다. 결국, 곰브리치의 말은 한마디로 예술이 그것을 행하는 사람 이전에 어떤 고정된 실체로 존재하는 것은 아니라는 것이다. 예술을 먼저 실체화하여 설정하는 것은, 손가락 개수가 다섯 개인 이유가 장갑에 뚫린 구멍이 다섯 개라는 궤변일 뿐이다.
그렇다면 이 분야에서는 어떨까. 누군가가 몇 시간을 공들여 만들어 놓은 것을 보고 "이건 프로그램이 아냐!"라고 말할 수 있을까. 이 질문 이전에 '과정'으로서의 '프로그래밍'이란 무엇이고, 거기서 나오는 '결과'로서의 '프로그램'은 무엇이며, 이 작업을 행하는 '주체'로서 '프로그래머'란 누구인가.
이 세 단어의 가장 원형이라고 생각되는 '프로그램(program, programme)'이라는 단어가 역사적 문헌에서 최초로 등장한 것은 17세기(1633년)까지 거슬러 올라간다. 인류가 이 단어를 사용한 역사는 불과 400년도 되지 않는다. 원래 이 단어는 희랍어에서 '이전'을 의미하는 접두어 pro-와 '글을 쓴다'는 의미의 어근 graphein이 합쳐져 생긴 것이다. 초기에는 '미리 쓴다', 즉 뭔가를 미리 써서 알리는 '사전 고지'를 의미했다. 이것은 미리 계획을 세워서 알리는 개념으로 발전했고 나중에는 그 계획 자체를 뜻하게 되었고, 1920년대 들어 기술의 발전으로 라디오가 탄생하면서 라디오 진행표를 일컫는데 사용되기에 이르렀다.
우리가 말하는 컴퓨터 프로그램으로서의 '프로그램'이 최초 등장한 것은 1946년도 네이처(Nature)의 에니악(ENIAC) 컴퓨터 관련 기사였다.
한편 프로그래머라는 단어가 문헌에 등장한 것은 1890년 경마 클럽의 '프로그래머'가 시초였고, 컴퓨터 프로그래머는 그보다 한참 후인 1948년도였으며, 이것이 사람들 앞에서 밝힐 수 있을 만큼 '떳떳한' 직업이 되기까지는 수십 년이 더 흘렀다. 튜링상을 받은 다익스트라는 1957년 결혼 당시 자신의 직업란에 프로그래머라고 적었다가 "이런 직업은 존재하지 않는다"는 반론에 이론 물리학자라고 고쳐썼다고 한다.
프로그래밍이라는 작업은 비교적 이른 시기에 찾아볼 수 있는데, 1949년 Mathematical Tables & Other Aids to Computation이라는 저널에 재미있는 용례가 있다.

"ENIAC 사용에서 발생하는 가장 시간 소모적인 요소는 프로그래밍(특정 문제를 위해 기계를 준비하는 것)이다."

아마 소프트웨어 위기(Software Crisis)는 컴퓨터가 출현한 초기 시대부터 예견됐는지도 모르겠다. 반세기가 지난 지금도 우린 그 시간 소모적인 '프로그래밍'의 문제를 해결하지 못하고 있다.
어원 연구에서부터 어휘 사용의 역사까지 살펴봤으니 현재적 의미에서 합당한, 새로운 정의를 이끌어 내야 할 것 같다. 이것이 온고지신 아니겠는가. 하지만 필자는 앞서 곰브리치가 지적한 것처럼 '완벽한 프로그래밍의 정의'를 닫힌 괄호 속에 채워 넣는 식의 어리석음을 범하고 싶지는 않다.
프로그래머란 프로그램을 만드는 사람을 말한다. 프로그래밍이란 프로그램을 만드는 작업을 말한다. 이런 식으로 두 개의 단어는 제대로 정의가 된 것처럼 보인다(조금 약삭빠른 것 같기도 하다). 프로그램이란 '문제 해결의 단계를 코드화해 표현한 것'이라고 하면 어떨까. 현존하는 대다수의 컴퓨터가 폰 노이만식이니 단계 이야기를 꺼내도 될 것이고, 프로그램이라는 말 자체는 본질적으로 인간의 관점에서 본 것이니(논쟁의 여지가 있긴 하다) "문제 해결" 따위의 말을 써도 될 듯 하다. 또 정해진 표현 양식과 유한 집합의 명령어가 있으므로(이게 아니면 알고리즘이라고 해야할 것이다) '코드화'라는 표현을 사용하는 것은 적절하다. 어쨌든 컴퓨터 프로그램도 '미리 써둔 계획'의 일종이니 몇 백년도 넘은 단어가 처음 의미를 크게 벗어나진 않은 것 같다.

그렇다면 이런 말장난같은 것들로부터 도대체 어떤 쓸모를 얻을 수 있을까. 위의 정의를 고려해 볼 때, 일반적인 의미에서 프로그래머는 '문제 해결자'라고 말할 수 있다. 흔히들 프로그래머간에 자조적으로 자기를 폄하하는, 동시에 책임회피에 아주 유용하게 사용하는 문장이 있다. "전 단지 프로그래머여요(I'm just a programmer)"라는 문구인데, 이 글을 읽는 순간 당장 생각을 바꿔야 한다. "(놀라지 마세요) 저는 프로그래머랍니다"로 말이다. 자신이 설령 시스템 분석가나 아키텍트가 던져주는 문서를 보고 단순 노동으로 프로그래밍을 하는 사람일지라도 자존심을 가져라. 이미 그들은 '일반적 문제 해결자(general problem solver)'의 배경과 가능성을 갖고 있는 것이나 마찬가지이기 때문이다.

@같은 뜻, 다른 표현

문제를 해결한다는 것은 무엇인가. 수학 문제를 푸는 것은 무엇인가로 생각의 범위를 좁혀 보자. 모든 수학 문제는 기본적으로 경험적이 아니라 분석적이다. 세종대왕이 한글을 창제한 해와 같이 어떤 직간접 경험을 통해 알 수 있는 것이 아니고, 그 문제 자체와 몇 가지의 수학적 공리를 분석하면 선험적으로 알 수 있다는 말이다. 한마디로 문제를 완벽하게 이해하고, 기본이 되는 공리를 알고 있다면 답을 알 수밖에 없다는 것과 같다.
예컨대, f(x)=x^2 - 3x + 2일 때, {{{{f(x) = 0 이 되는 실수 x를 묻는 경우, 문제의 f(x)=x^2 - 3x + 2를 f(x) = (x-1)(x-2)로 변형하면 답은 거의 자명해진다. 결국 모든 수학문제의 답은 문제의 조건을 변형한 것으로 귀착된다. 이 변형은 어디를 지향점으로 할까. 당연히 인간에게 명백하고 직관적인 수준(혹은 수학적 공리의 수준)으로의 변형을 목표로 한다.
1978년에 노벨 경제학상을 수상하고 심리학 및 컴퓨터의 인공지능 분야에 지대한 공헌을 한 허버트 사이먼(Herbert A. Simon)은 그의 대표적 저서 '인공 과학(The Sciences of the Artificial)'에서 "문제를 푼다는 것은, 그것을 해답이 드러나도록 표현하는 것"이라고 언급했다. 그가 예로 드는 '표현 양식(representation)의 변형에서 답이 자명해지는' 대표적인 경우를 하나 보도록 하자.

카드 한 벌에서 하트 문양의 1부터 9까지의 카드를 준비한다. 이 카드를 두 사람 사이에 숫자가 보이도록 일렬로 벌여놓고 두 사람이 번갈아 가며 한 장씩 카드를 고른다. 이렇게 해서 자신이 모은 카드의 숫자 합계가 먼저 15가 되는 사람이 승자가 된다.

이 게임에서 이기거나 최소한 비기기 위해서는 어떤 전략을 써야할까. 그다지 쉬운 문제는 아닌 것 같다. 그런데 좀 전에 f(x)를 인수분해해 변형했듯이 현재 문제의 표현 방식을 다르게 생각해 보자.

<그림 1> 마방진
4 9 2
3 5 7
8 1 6

<그림 1>은 어느 쪽으로 더해도 합계가 15로 일정한, 소위 마방진의 하나다. 문제를 이렇게 표현한 경우, 카드를 뽑는 게임은 자신의 말을 일렬로 먼저 늘어놓는 사람이 이기는 틱택토(Tic-Tac-Toe) 게임(서양에서 매우 흔한 게임으로, 가로 세로 세 칸씩 총 아홉 칸의 상자에 두 사람이 한 번씩 번갈아 가며 자신의 표시(○ 또는 ×)를 그려 넣는다. 한번 채워진 곳에는 다시 그려 넣을 수 없고, 먼저 자신의 표시를 일렬로 채운 사람이 이기게 된다. 종종 'Hello! world' 프로그램과 함께 표준 테스트 중 하나로 인정받는다)과 완전히 동일해진다.

<그림 2> 틱택토 게임
x 9 2
o o x
8 1 6

따라서, 같은 문제라도 그 표현 방식에 따라 쉽고 간단한 문제가 되기도 하고 그 반대가 되기도 한다. 우리는 문제를 적절한 표현 방식으로 바꿈으로써 문제를 즉각적으로 풀어낼 수도, 혹은 문제 풀이에 큰 도움을 받을 수도 있는 것이다.
예컨대 로마 숫자와 아라비아 숫자를 비교해 보면 전자의 경우 덧셈에서는 후자보다 더 직관적일 수 있다(덧셈의 계산이 바로 물리적으로 문자를 더하는 데에서 행해지기 때문이다). 하지만 곱셈이나 나눗셈의 경우 로마 숫자는 비효율적이고 어렵다(로마인들은 이것을 해결하기 위해 산술 연산의 경우, 문자간의 계산을 돌멩이간의 계산, 즉 주판이라는 새로운 표현 방식으로 바꿨다). 수학적으로는 문제를 어떻게 변형하든지 그 의미론은 동일하다. 또 그래야만 한다. 다만 표현 방식이 바뀔 뿐이다. 이러한 것들이 프로그래밍에서는 어떤 의미를 가질까.
by 필라르 | 2004/03/30 17:55 | About Programming | 트랙백(136) | 덧글(2)
2004년 03월 30일
프로그램, 프로그래밍, 프로그래머

@컴퓨터의 이론적 배경

이야기를 진행하기에 앞서 독자의 이해를 돕기 위해 몇 가지 기본적 사항을 짚고 넘어가도록 하자.
기본적으로 문제를 푼다, 계산한다(compute)고 하는 것은 수학적인 의미에서의 함수를 말한다. 어떤 값 x를 f(x)라는 함수에 입력했을 때 그 결과값이 무엇인지를 알아내는 것이다. 여기서 x는 단순히 숫자만이 아니라 훨씬 다양한 대상(글자, 문장, 그림 등)이 될 수 있다. 물론 컴퓨터는 이를 단지 기호(symbol)의 일종으로만 여길 뿐이다. 우리가 '컴퓨터'라고 하는 것의 이론적 모델은 튜링 기계(Turing Machine)다. 앨런 튜링(Alan Turing)이 1936년 발표한 이 기계는 실재하지 않는 이론상의 가상적 존재로, 현존하는 모든 컴퓨터와 앞으로 올 모든 컴퓨터(현재 컴퓨터의 패러다임을 유지하는 한)의 이론적 한계를 긋는 '가장 강력한' 컴퓨터다.
여기서 가장 강력하다는 것은 계산 가능성(computability)을 지칭하는 것으로, '얼마나 빨리' 혹은 '얼마나 효율적으로'와 전혀 상관없이 유한한 시간 안에 이 문제를 풀 수 있느냐는 가불가의 판단이다. 즉, 튜링 기계가 풀어낼 수 없는 문제는 어떤 컴퓨터도 풀 수 없고, 역으로 슈퍼 컴퓨터가 풀 수 있는 문제라면 튜링 기계도 풀어낼 수 있다.
튜링 기계는 정해진 길이의 기호(예컨대, 0이나 1)를 적어 넣을 수 있는 칸(cell)이 있는 무한한 길이의 테이프와, 그 테이프에 기호를 쓰고 읽을 수 있는 헤더, 그리고 처리 장치로 이뤄진다. 처리 장치에는 유한한 개수의 상태 중 하나를 저장할 수 있는데, 이 상태와 테이프 위에서 현재 헤더가 위치한 곳의 기호에 따라 다음의 행동이 결정된다. 가능한 행동은 헤더를 좌우로 한 칸 움직이는 것, 현재 칸을 읽고 다시 기호를 써넣는 것, 실행을 종료하는 것이 있다. 이렇게 한 단계가 끝나면 현 상태를 새로운 상태로 바꾸고, 다시 다음 단계를 실행한다. 아주 단순한 기계 같지만 무한한 길이의 테이프와 가장 기본적인 몇 가지의 동작으로 알고리즘이 존재하는 문제는 모두 풀 수 있다.
오늘날 컴퓨터의 실질적 모델은 폰 노이만 구조(Von Neuman Architecture)를 따른다. 폰 노이만 구조는 기억 장치(메모리)에 자료(데이터)와 명령어를 함께 저장하고, 중앙 처리 장치가 그 저장된 프로그램의 명령어를 하나씩 읽어와서 자료에 대해 연산하는 구조를 말한다.
컴퓨터는 근본적으로 오직 한 가지 언어만을 이해한다(하지만 어떤 한 종류의 기계어가 모든 컴퓨터에 두루 쓰이는 공통어는 아니다). 우리는 이것을 기계어라고 부른다. 이 언어는 2진수로 표현되고, 명령어(연산자)와 목적어(피연산자)가 짝을 이룬다. 예를 들어, 기억 장소의 세 번째 칸에 있는 값을 하나 증가시키라는 식이다.
인간은 이런 2진수로 표현된 명령어와 자료를 이해하기 힘들고 이 언어로 표현하기도 어렵다. 따라서 좀 더 인간의 자연 언어에 가까운 언어를 개발해 사용하게 된다. 이를 고수준 언어라고 부른다. 하지만 컴퓨터는 이것을 이해하지 못하기 때문에 번역의 과정이 필요하다. 고수준 언어로 된 프로그램 전체를 한번에 기계어로 번역해(이 번역 행위 역시 기계어로 작성된 프로그램이 한다) 이를 차후에 다시 사용할 수 있게 저장하는 것을 컴파일(compile)이라고 하고, 한 문장씩 번역해 순서대로 실행시키는 것을 인터프리트(interpret)라고 한다. 고수준 언어에서 명령어 하나는 저수준 언어(기계어)의 명령어 수십 개에서 수천 개 이상으로 구성된 것이다.

@컴퓨터 세계의 어족

이 세상에 존재하는 프로그래밍 언어는 줄잡아서 2000개가 넘는다. 하지만 기본적으로 범용 언어인 경우, 대부분 그 표현 능력이 동등하다[주: 쳐치-튜링 논제(Church-Turing Thesis)라고 한다. 순서대로 진행하는 과정(알고리즘)으로 정의되는 함수에 튜링 기계로도 계산할 수 없는 것은 있을 수 없다는 논제다. 따라서 튜링 기계를 흉내낼 수 있는 언어라면 (대부분의 범용언어는 튜링 기계의 단순한 동작을 흉내낼 수 있다) 어떤 알고리즘이든지 표현할 수 있다. 물론 기억장치의 한계를 고려하지 않았을 때의 얘기다]. 갑이라는 언어가 계산할 수 있는 것(혹은 풀 수 있는 문제)이라면 을이라는 언어도 할 수 있다는 말이다. 차이점이 있다면 어떤 표현 방식을 사용하느냐이며, 이는 곧 어떤 문제의 답을 구하는 방법(알고리즘)을 표현할 때 효율적이냐 비효율적이냐의 차이로 나타난다.
눈이 많이 내리는 지방에는 눈과 관련된 표현이 발달하고 추상화(경제적 의미에서)가 많이 진행되는 반면, 사막 지방에는 낙타와 관련된 단어가 많다. 자연언어의 이러한 차이는 인공언어인 컴퓨터 프로그래밍 언어간에서도 관찰할 수 있다.
몇 가지 특징에 의해 프로그래밍 언어를 묶을 수 있는데, 소수의 한정된 디자이너가 존재하는 이유로 각각이 독특한 '언어관'을 내포하는 경우도 흔하다. 이런 이유로 프로그래밍 언어의 어족개념을 '프로그래밍 패러다임[주: 이에 관해서는 1978년에 튜링상을 수상한 로버트 플로이드 교수의 「The Paradigms of Programming」을 참고하라]'이라고 부르기도 한다. 각각은 해당 언어로 생각하는 사람들을 특정 표현 방식으로 생각하도록 유도한다. 언어와 사고에 대해서는 조금 후에 다시 논의하도록 하자.
이 프로그래밍 패러다임은 크게 네 가지의 범주를 벗어나지 않는다. 명령형(imperative), 함수형(functional), 논리형(logic), 객체지향형(object-oriented) 언어가 그것이다. 각각 나름의 특징과 장단이 있기 때문에 다른 것과는 확연히 구별된다. 하지만 이들 언어가 실행되기 위해서는 컴퓨터가 이해할 수 있는 유일한 언어인 기계어로 번역이 되야 하며, 튜링 기계에서도 언급했듯이 각 언어의 표현능력(expressivity)은 기본적으로 동등하다.
결국 기계어로 번역될 것임에도 불구하고 기계어 대신 고수준 언어(3세대 언어라고도 한다)를 사용하는 것은 이것이 인간에게 더욱 가깝고, 추상화가 잘 돼있어 자잘한 것들에 신경 쓸 필요가 없기 때문이다. "밥을 먹어" 대신에 "수저에 밥알 220알을 퍼올려서 상방 30도 각도로 올린 다음 입안에 넣고 씹는 운동을 하는 것을 밥그릇이 빌 때까지 반복하라"는 명령을 해야 한다는 것은 악몽이다.
훌륭한 표기법은 우리 뇌의 모든 불필요한 작업을 덜어주고 우리가 더 고차원적인 문제에 집중할 수 있도록 해주며 결과적으로는 인류의 정신력을 증가시켜주는 것이라고 한 철학자 화이트헤드(A. N. Whitehead)의 명언은 고스란히 프로그래밍 언어의 세계에도 적용된다. 이미 말했듯이 각 언어의 표현능력이 동등함에도 불구하고 여러 언어가 존재하는 것은 각 문제와 상황에 더욱 적당한 언어가 있기 때문이다. 물론 여러 패러다임을 모두 갖춘 언어 하나를 사용하는 것이 최선일 것 같지만 컴퓨터는 그렇게 유연한 기계가 되지 못한다(여러 패러다임을 갖춘 언어를 멀티 패러다임 언어라고 하며, 극히 소수가 존재한다). 따라서 여러 가지 도구를 다룰 줄 알면서 상황에 맞게 적절한 것을 골라 쓰는 장인의 지혜가 필요하다.
우리가 이렇게까지 많은 프로그래밍 언어를 만든 것은 궁극적으로는 자연언어를 모방해 보려는 다각적 시도였는지도 모른다. 프로그래밍 언어에서 자연언어를 제5세대 언어라고 부르며, 오르지 못할 바벨탑에 도전하는 어리석음으로 매달리고 있는 것도 결국은 컴퓨터에서 인간성을 찾기 위한 노력이지 않을까.

@프로그래밍 언어와 사고

"우리가 만약 다른 언어로 말한다면, 우리는 다소 다른 세상을 인지할 것이다.- 비트겐슈타인"

언어가 우리의 사고를 형성하는 것일까, 아니면 우리의 사고가 언어를 형성해 나가는 것일까. 닭과 달걀의 논쟁처럼 끝이 보이지 않는 우문같이 들리지만, 굳이 답을 찾는다면 어떻게 말해야 할까. 우리의 언어와 사고는 상호 작용을 하는 양방향의 관계에 있다. 마주보는 거울을 생각하면 된다. 한쪽 거울에 비친 상이 다시 반대쪽 거울에 비치고, 그 (거듭) 비친 상은 또 다시 원래의 거울에 비치는 식으로 무한히 연속된다.
언어는 틀이고 툴(tool)이다. 인식의 도구이자 인간을 종속시킨다(우리는 사용하면서 동시에 지배받는다). 우리는 언어로 세계를 형성하고 이해한다. 다른 언어를 사용하는 이상, 같은 상황을 보면서도 다르게 인식할 수밖에 없다[주: 언어가 우리의 사고 방식을 결정한다고 하는 것을 언어 결정론이라고 한다. 사피어 훠프(Sapir-Whorf) 가설이 이 이론을 주장했고, 20세기 언어학에 많은 영향을 끼쳤지만 현재는 학계에서 그 자체로 받아들여지지 못하고 있다. 사피어와 훠프는 어떤 개념이 특정 언어에만 존재하는 것에서 출발해 해당 언어 사용자의 사고의 고유함을 말했지만, 그러한 경우에도 충분히 성공적인 번역이 가능하다는 점이 이 가설에 대한 가장 큰 반격이다. 필자 역시 이 가설에서 한 걸음 물러선 입장이며, 우리의 삶과 그 양식이라는 보다 큰 그림을 봐야 한다고 생각한다]. 마샬 맥루한의 말에 빗대어 "언어는 메시지다"라고 말하고 싶다. 즉 어떤 언어를 사용하느냐에 따라 그 메시지가 달라질 수 있다는 말이다.
하나의 인간 개체가 태어나면서부터 겪게 되는 언어 발달 과정을 유심히 관찰하면 우리 인류가 겪어온 언어 발달의 역사를 유추해 볼 수 있다(부분적 마이크로 모델에서 전체의 매크로 모델이 유추되는 것이다). 처음 글자가 없을 때의 사고 구조(구술 문화)와 글자가 생기고 나서의 사고 구조(문자 문화)의 차이는, 글자는 모르지만 말은 하는 아이와 나중에 글과 말을 모두 터득한 아이의 비교를 통해 대강 짐작할 수 있다. 한 가지만 예를 들면, 구술 문화의 사람들은 말의 호흡이 짧다. 이것은 인간의 한정된 기억 능력에 기인한다. 반면, 글자가 사용되면서부터 자신의 뇌 외부에 말을 기록하는 것이 가능해졌고, 이는 말의 호흡을 길게 하는 효과를 가져왔다(이것은 언어, 나아가 그 사람의 사고 활동이 좀더 복잡해지고 추상화되어지도록 한다). 마찬가지로 글을 모르는 아이와 글을 사용하는 아이의 언어 차이도 이와 유사하다. 결국 어떤 언어를 사용한다는 것은 그 사람에게 사고의 어떤 틀을 제공한다는 말과 같다. 물론 그런 언어도 해당 언어 사용자들의 사고 구조에 가장 적합한 형태로 진화하고 있다. 언어와 사람의 사고는 이처럼 불가분의 관계에 있다.
우리가 한 가지 언어를 배운다는 것은 그 언어를 사용하는 사람들의 사고 구조를 몸에 익힌다는 말과 크게 다르지 않다. 영어를 배운다면 영어를 사용하는 사람들의 사고 구조가 몸에 익도록 해야한다. 결국 프로그래밍 언어를 배우는 것도 쿵후(工夫)와 크게 다르지 않다. 몸의 길을 닦는 것이다. 태권도라는 것은 결국 손과 발이 갈 '길'이면서 동시에 자신의 몸에 그런 '길'을 내주는 공부다. 어떤 산 근처에 촌락이 형성되면 사람들은 그 산을 다니기 시작할 것이고 '적당한 루트'를 따라 길이 자연스럽게 만들어 질 것이다. 사람들이 많이 다니면 자연스럽게 길이 닦이는 것이다. 한번 길이 놓인 이후로는 별 고생 없이 그 길을 따라가면 된다. 이제는 그 산과 길이라는 것이 별개가 아니고, 또한 그 길과 내 몸도 별개가 아니다. 내 몸 역시 그 길에 맞게 '진화'했을 테니까.

@과학자, 장인, 예술가

앞서 설명한 표현 양식과 언어와 사고간의 관계 등을 고려해 볼 때 다양한 패러다임의 언어를 안다는 것(비슷비슷하거나, 자체의 일관된 철학 없이 수많은 기능만 끌어 모은 소위 '강력한' 언어는 별 도움이 안된다)은 문제 해결자들에게 엄청난 무기가 될 수 있다. 이것이 필자가 말하고자 하는 '장인(artisan)으로서의 프로그래머'다. 자신의 몸의 훈련을 통해 도구를 마치 몸의 연장(延長)처럼 만들되, 하나의 도구에만 종속되지 않으며 재료에 알맞게 다양한 도구를 선택할 수 있어야 한다. 또한 자신이 만드는 프로그램 하나 하나에 누가 감시하든 말든 성실하게 최선을 다하고 그것을 내 몸과 같이 아끼고 사랑할 수 있어야 비로소 '장인으로서의 프로그래머'가 될 수 있다.
이와 동시에 프로그래머는 예술가(artist)의 역할도 할 수 있어야 한다. 다익스트라는 "아름다움이 우리가 하는 일이오(Beauty is our business)"라는 명언을 남겼고, 크누쓰 교수의 기념비적 저서 「TAOCP」에도 예술(art)이라는 말이 들어간다[주: 영어에서 art는 기술이라는 의미로 쓰이기도 하지만 크누쓰는 분명히 미적 가치를 추구하는 예술임을 밝히고 있다]. 과학우선주의 사회에서는 이런 예술이나 기술과 같은 것은 저열한 것으로 치부되고, 그것을 과학화해야 비로소 자랑스러워하는 경향이 강하다. 하지만 아인슈타인의 말대로 "수학의 법칙들이 현실을 언급하는 이상, 그것은 확실하지 않고 그것이 확실한 이상, 그것은 현실을 언급하지 않는다"는 사실을 기억해야 할 것이다. 프로그래밍이라는 것은 자연과학이 될 수 없다. 인간이라는 요소가 개입되기 때문이다. 결국 크누쓰가 말하는 것처럼 우리는 '아름다운 프로그램(beautiful program)을 만드는 심미적 목적을 가질 수밖에 없는 것이다.
물론 과학자로서의 프로그래머를 무시할 수도 없다. 비록 이론이 모두 적중하지 못하더라도 탄탄한 이론적 바탕은 우리의 수많은 시행착오를 절약할 수 있게 해준다. 분석적이고 논리적인 냉철한 사고를 갖고, 예술가로서의 감수성과 심미성을 추구하며, 자신의 몸 공부가 경지에 이른 장인이 바로 이 시대가 원하는 프로그래머일 것이요, 이 프로그래머가 역시 진정한 엔지니어의 요구사항을 충분히 만족시킬 수 있을 것이다.

@훌륭한 프로그램과 프로그래머

우리 모두는 훌륭한 프로그래머이기를 꿈꾼다 (어쩌면 우리의 관리자들이 더욱 그러할 수도 있겠다). 훌륭한 프로그래머는 어떤 사람일까. 프로그래머는 프로그램으로 말한다. 이들은 오로지 프로그램(결과)과 프로그래밍(과정)으로 평가받기를 원한다. 그렇다면 훌륭한 프로그래머란 바람직한 프로그래밍을 통해 훌륭한 프로그램을 만들어 내는 사람일 것이다. 오로지 결과물, '프로그램'만 좋으면 된다고 생각하는 사람은 이 사회에 적응하기 힘든 해커기질을 타고났다고 자신해도 좋을 듯 싶다. 프로그램이라는 결과물에는 그 사람이 작업한 과정은 잘 드러나지 않는다. 결과물이 아무리 중요하다고 해도 하루 걸릴 일을 일년 걸리거나, 천원에 할 일을 일억원에 하는 경우를 생각해 보라. 하지만 '좋은 프로그램'이 '좋은 프로그래머'를 결정하는데 가장 큰 요인이라는 것을 무시할 수는 없겠다. 어찌 보면 좋은 프로그래밍을 좋은 프로그램의 필요조건으로 넣을 수도 있겠는데, 그렇다면 결국 '좋은 프로그램'이 지상최대의 궁극적 과제가 될 수도 있을 것이다[주: 사실 이런 논의는 그 자체로 무의미할 수 있다. 좋은 프로그램이라는 것은 맥락 의존적이기 때문이다. 어떤 상황에서 좋은 프로그램이 다른 곳에서는 나쁜 프로그램이 될 수 있다. 하지만 우리는 비교적 일반적인 경우에서 공통분모를 놓고 생각해 보려고 한다]. 좋은 프로그램이 되기 위한 조건들은 다음과 같다.

◆ 스펙(Specification)
◆ 스케쥴
◆ 적응성
◆ 효율성
◆ 경제성

「The Pragmatic Programmer」의 저자 데이비드 토마스와 앤드류 헌트는 프로그래밍이란, 단순히 보면 자신이 혹은 사용자가 원하는 일을 컴퓨터가 할 수 있도록 만드는 것이라고 했다. 무엇이 좋다 나쁘다, 훌륭하다 못하다는 효용가치 판단은 구체적 목적이 있어야 비로소 가능해진다. 분명 프로그래밍의 목적은 '문제 해결'이요, '일을 해 내는 것'이다. 그렇다면 좋은 프로그램의 가장 기본적인 요구사항은 '해야 할 일을 하는 것'이라고 말할 수 있을 것이다. 이것이 첫 번째이자 가장 중요한 '스펙'이라는 사항이다. 즉 프로그램은 모든 요구조건을 만족해야 한다. 이것은 효율성(속도 등)과는 비교할 수도 없을 만큼 중요한 사항이지만 많은 개발자들이 이것을 망각한 채 다른 잔가지에 매진하곤 한다.
두 번째 스케쥴은 '시간 안에' 프로그램을 만들어 내는 것을 말한다. 요즘 같이 소프트웨어 산업에서 비즈니스 측면이 부각되는 때라면 이 요건은 더욱 중요해진다. 물론 이 스케쥴의 요건을 충족하기 위해서는 적절한 개산(槪算, estimation)이 필요하다.
한 사회의 안정성은 그 사회의 가변성에 의존한다. 자기 모순적 명제 같지만, 우리는 이러한 사실을 실생활에서 자주 접한다. 프로그램의 경우를 보자. 가변성이 낮은 프로그램일수록 일찍 폐기 처분되기 쉽다. 이런 프로그램은 다른 환경(유사하지만 조금 다른 문제 혹은 다른 플랫폼 등)에 잘 적응하지 못하고, 그로 인해 비용이 극도로 늘어나게 된다. 고정화, 고형화는 죽음이고, 유연성은 삶이다. 유전학과 자연선택에서 유명한 피셔(R. A. Fisher)는 '피셔의 기초 원리'를 만들었다. 골자는 "특정 환경에 잘 적응된 시스템일수록 그것은 새로운 환경에 잘 적응하지 못한다"는 것이다.
어떤 프로그램이 효율적으로 되기 위해서는 현 문제의 특수성과 그 프로그램이 실행될 컴퓨터의 고유한 특성을 '영리하게' 이용해야 한다. 대부분의 경우 특출한 기술을 사용해 벌은 시간은 그 코드에 새로운 부분이 추가될 때 소모되는 시간에 비해 극히 미미하다. 배보다 배꼽이 큰 셈이다. 현재는 하드웨어의 비약적인 발전으로 과거만큼 빡빡한 한계는 없다(물론 상대적으로 다뤄야할 문제가 커진 것에서 생기는 한계상황도 있다). 컴퓨터가 이해할 수 있는 코드를 만드는 것이 문제가 아니다. 문제는 인간이 쉽게 이해할 수 있는 코드이고, 자신의 변화를 허용하는 코드인 것이다. 효율성은 실행시간만을 의미하는 것은 아니다. 실행시간이라는 것은 실행 이전이나 이후에 소요되는 시간으로 어느 정도 대치 가능하기 때문이다. 또한 효율성의 측정이라는 것을 진지하게 생각해 봐야 한다. 짧은 평균 실행 시간보다 낮은 표준 편차가 더욱 중요할 수도 있다. 입력자료가 100개 미만일 때 1밀리세컨드 걸리지만 그 이상에선 10초 이상 걸리는 경우는 표준 편차가 너무 크다. 그리고 효율성 증진을 위해서는 여러 가지 최적화의 방법이 존재하지만 '포기에 의한 최적화'도 가능하다. 일반적으로 어떤 문제가 풀 수 있는 영역에서 비교적 덜 중요한 10%를 포기하게 되면 전체 실행 효율(속도)을 두 배 이상 올릴 수 있다. 이런 경우에는 '스펙'을 수정해야 한다(이 때 고객 혹은 자신과의 솔직한 커뮤니케이션이 꼭 필요하다). 어찌 됐건, 효율성(efficiency)이라는 가치는 '바른 일을 하는가'라는 효과성(effectiveness)의 고려 없이는 전혀 무의미하다.
마지막으로 경제성은 비용과 수익의 측면이다. 프로그래밍의 목적이 '돈을 버는 것'이라고 할 때 가장 우선적인 요소가 될 지도 모르겠다. 하지만 경제성 역시 다른 요건들이 충족될 때 고려해 볼 수 있다.
이상의 요건들을 '상황에 맞게' 적절히 갖춘 프로그램을 생산해 낼 수 있는 사람, 우리는 그들을 '훌륭한 프로그래머'라고 부른다[주: 여기서 언급되지 않았지만 훌륭한 팀 플레이어의 역할도 빼놓을 수 없다. 뛰어난 지식에 의사소통 능력이 떨어지는 사람이 컴퓨터 도사의 전형이 되던 시대는 갔다]
by 필라르 | 2004/03/30 17:55 | About Programming | 트랙백 | 덧글(0)
2004년 03월 30일
프로그램, 프로그래밍, 프로그래머
프로그래머의 지식 투자

수많은 세계의 석학들은 미래사회는 지식 중심 사회가 될 것이라고 예견했고, 그 예측은 거의 맞아 들어가고 있는 것 같다. 몇몇 특수한 상황을 제외하곤, 지금 당장 가장 수익률이 좋고 안정성이 보장되는 투자는 지식에 대한 투자다. 한번 제대로 획득하면 잃어버릴 일이 거의 전무하기 때문이다. 프로그래머와 같은 지식 산업 종사자들은 ( 자신들은 단순 노무직이라고 부인할 지라도) 자신의 지식 투자를 효과적, 효율적으로 관리할 수 있어야 한다. 이것이 미래에 대비하는 길이다.

앞서 소개한 헌트와 토마스는 이것을 지식 포트폴리오(Knowledge Portfolio)로 설명하고 있다. 지식 투자 관리는 어떤 면에서 재무 투자 관리와 상당히 유사하다.

- 정기적으로 투자하는 것을 습관화한다
- 분산 투자가 장기 성공의 열쇠다
- 자신의 포트폴리오를 안전한 것과 위험성이 큰 것을 고루 갖추도록 균형을 잡는다
- 싸게 사서 비싸게 판다.
- 주기적으로 포트폴리오를 재평가한다

첫 번째, 정기적 투자는 자신의 지식을 위해 '정기적'으로 '조금씩' 새로운 지식을 습득하는 것을 말한다. 예를 들어 매년 새로운 프로그래밍 언어(가능하면 다른 패러다임의 언어)의 습득을 목표로 세운다든지, 매 분기마다 새로운 기술 서적을 한 권 씩 읽기로 약속한다든지, 비기술 서적(컴퓨터와 관련 없어 보이는 것일수록 좋다)을 정기적으로 읽고 통신 동호회에 가입해 스터디를 한다든지, 새로운 플랫폼을 시도해 보거나, 매달 잡지와 저널을 구독하는 노력을 모두 꾸준히 조금씩 해주는 것이 중요하다.지금 당장 필요하지 않은 혹은 향후 수십 년간 사용할 것 같지도 않은 언어를 배우면서 자꾸 의혹 속에 괴로워하지 마라. 설령 그 언어를 사용하진 않더라도 다른 문제 해결에 분명 도움이 될 것이다. 또 경계를 넘어선 '가로지르기'도 필요하다. 갑이라는 기술을 배웠고 전혀 다른 분야에서 을이라는 지식을 얻었을 경우 둘 사이에 존재하는 상관관계, 응용 방법 등을 깊이 생각해 보는 것은 지식을 체화시키면서 실질적인 소득도 얻을 수 있는 기회다.
두 번째, 분산 투자는 한마디로 서로 다른 것을 더 알게 될수록 자신은 더욱 가치 있어질 것이라는 얘기다. 하지만 기본적으로 어떤 것이 저무는 태양이고, 어떤 것이 떠오르는 것인지에 대한 정보를 갖춰야 할 것이다. 그렇다고 자신을 너무 내몰지는 마라. 어제 떠오른 것이 오늘 지고, 어제 졌던 것이 오늘 뜨는 현상이 이 분야에 한 두 번 있는 일이던가.
세 번째, 위험 관리다. 아마도 '계란을 한 곳에 담지 마라'는 말을 들어봤을 것이다. 안정성이 보장되는 지식만 좇는 것이나, 위험성이 너무 큰 (실효가 입증되지 않은) 지식만 추구하는 것은 모두 문제가 있다. 균형을 유지해야 한다.
네 번째, 싸게 사서 비싸게 팔아 차익을 크게 만들어라. 자바가 처음 등장했을 때 그것을 배우는 일은 상당히 위험성이 높았을 것이다. 하지만 초기 개발자들이 결국은 얼마나 비싸게 자신의 지식을 팔아 이득을 얻었는가. 서점에 널린 기술은 이미 비싸게 사서 싸게 팔 확률이 높은 것들이다.
다섯 번째, 이 분야는 매우 동적이다. 지난달에 인기가 치솟았던 것이 이번 달엔 곤두박질 칠 수도 있다. 너무 유행에 민감한 것도 문제겠지만, 그렇다고 자신의 포트폴리오를 몇 달 간 다시 들여다보지 않는 것처럼 위험한 것도 없다. 먼지가 쌓이고 녹슬어 가는 지식이라면 기름칠을 해야 할 것이고, 새로운 지식이 필요하다고 판단되면 과감이 뛰어들어야 한다.

이 다섯 가지 중에서 뭐니뭐니 해도 가장 중요한 것은 첫 번째 항목인 '자신의 포트폴리오에 정기적인 투자'가 될 것이다.

@프로그래머의 자기 수련

:: 서적

다음의 서적들은 프레드 브룩스, 팀 버너스리, 앨런 쿠퍼, 제임스 고슬링, 브라이언 커니건, 스티브 맥코넬, 앤드류 타넨바움, 윌리엄 스톨링, 제럴드 웨인버그 등과 같은 컴퓨터 역사에 이름이 남을 만한 유명인으로부터 실전에서 이십 년 이상을 구르고 베테랑으로 알려진 프로그래밍의 노장과 달인들이 공통적으로 '자신에게 가장 많은 영향을 준 컴퓨터 관련 책'으로 꼽는 것을 필자가 몇 년에 걸쳐 수집하고 추려낸 것이다. 재밌게도 컴퓨터와는 별 관련 없어 보이는 책들도 몇 권 있다. 역시 유행과 동떨어졌기에 유행에서 살아남을 수 있었던 것이리라. 여기 나열된 책들은 대부분 처음 출판된 지 10년이 넘은 것이고 어떤 것은 30년이 넘은 것도 있다. 이런 고생대의 화석이 아직까지도 우리 시대에 유효할 수 있다는 것 자체가 경이로울 뿐이다. 정말 좋은 책이란 읽을 때마다 새로운 맛이 소록소록 나오고, 자신이 가진 문제에 늘 다양한 해답을 제공해 줄 것이다. 수천 년을 면면히 이어 내려온 노자 도덕경이 인류 곁을 아직 떠나지 않는 이유일지도 모르겠다. 전문 프로그래머라면 항상 기술 중심적이고 구체적인 책을 한 손에 들고 공부하면서도, 이런 일반적이고 유행과 상관없는 책을 다른 손에서 놓치지 않아야 할 것이다.

◆ The Art Of Computer Programming (TAOCP), Knuth, Donald
알고리즘과 자료구조에 관한 최고의 책이다. 프로그래머로서 정말 충실하게 공부해 둬야만 나중에 좌절을 맛보는 경험을 피할 수 있다. 현재 세 권까지 출판돼 있고, 1997년에 세 번째 판이 나왔다.

읽을 자신이 없다면 최소한 이 책들의 목차만이라도 봐두자. 상대적으로 좀 가벼운 책으로는 로버트 세드게윅(Robert Sedgewick)이나 토마스 코멘 외 2인 공저의 'Introduction to Algorithms'를 참고하라.

◆ Programming Pearls, Bentley, Jon Louis
실질적인 코드(C, C++)와 함께 알고리즘 개선, 코드 최적화 등을 다룬다. CACM에 연재됐던 것을 모으고 좀 더 덧붙인 것이다. 현재 프로젝트에서 알고리즘이나 자료구조에서 문제가 생기면 일단 마음을 차분히 가라앉히고 조용한 곳에서 이 책을 읽어보라.

◆ Structure and Interpretation of Computer Programs, Abelson, Harold, et al.
미국 MIT 대학에서 십 년이 넘도록 입문 코스용 교과서로 사용되고 있는 유명한 고전이다. 비록 수년이 흘렀고, Scheme이라는 그다지 대중적이지 못한 언어를 사용했지만, 이 책은 여전히 고전으로서의 가치가 빛나고 있다. 세월이 가도 변치 않을 프로그래밍의 근본 원리 전달을 목적으로 집필됐기 때문일 것이다. 이 책은 겉 표지에 마법사 그림이 있어서 마법사 책이라고 불리며, 에릭 레이먼드의 해커 사전에도 등재돼 있다.

◆ Design Patterns, Gamma, Erich, et al.
하나의 디자인 패턴은 특정한 종류의 문제를 해결하는, 프로그래밍 언어보다는 좀 더 추상적인 차원에서 일반적인 방법을 서술한다. 저자들은 '네 명의 동지들(Gang of Four)'로 더 알려져 있다. 국내 서점에서도 바닥이 날 정도로 잘 팔리는 베스트 셀러다.

◆ A Pattern Language: Towns, Buildings, Construction, Alexander, Christopher
패턴 언어는 원래 건축학에서 온 개념이다. 건물을 짓는 것과 소프트웨어를 만드는 것(영어로는 모두 build라고 한다) 간에는 상당한 유사점이 있다. 디자인 패턴을 본 사람이라면 이 개념의 원류를 공부해 보는 것이 매우 유익할 것이다.
이 책과 함께 많이 읽히는 'Timeless Way of Building'은 좀 더 철학적(노장사상과 관계가 깊다)이고 사변적이다. 이것을 읽는다면 세상을 보는 관점이 바뀔 것이다.
흔히 알렉산더의 이론에 대한 반대로 실증적인 결과와 예가 없다는 것인데, 그의 'The Production of Houses'를 꼭 읽어보길 권한다. 필자는 이 책에서 프로젝트 관리와 적응적 개발(adaptive development) 등의 가능성을 발견했다.

◆ How Buildings Learn: What Happens After They're Built, Brand, Stewart
비교적 최근에 출간된 책으로 건축학적인 개념에서 어떻게 건물이 '진화'하고 스스로 변화시켜 나가는지를 보여주며, 진화하기 좋은 건축물은 어떤 것인가에 대한 진지한 고찰이 들어있다. 우리 프로그래머들이 고민하는 문제와 동일하다. 따라서 프로그래밍을 새로운 관점에서 볼 수 있을 것이다.

◆ The Mythical Man-Month: Essays on Software Engineering, Brooks, Frederick
더 이상 설명할 필요가 없는 책이다. 진행중인 프로젝트 팀에 더 많은 인원을 쏟아 부으면 오히려 제품 출시가 더욱 늦어진다는 점을 밝힌 것으로 유명하다. 소프트웨어 공학에 관심이 없거나 기반 지식이 전무한 사람도 읽어볼 만한 책이다.

◆ Code Complete, McConnell, Steve
소프트웨어 구축 과정에 관한 한 거의 모든 사항을 '코드 중심으로' 모아둔 집적체다. 필자는 아직까지 이 주제를 다루면서 이 정도로 포괄적이면서 동시에 가치있는 책을 보지 못했다. 특히 33장의 참고자료는 더 많은 자료를 원하는 사람에게 매우 유용하다.

◆ How to Solve It, Polya, George
문제 해결에 관한 한 최고의 베스트 셀러다. 한글 번역판이 있는데, 국내에서 이 책의 가치가 제대로 평가되지 못하고 수학 시험 준비 서적으로 분류되고 있는 점이 아쉽다. 비단 수학뿐만 아니라 거의 모든 '문제 해결'이라고 할 만한 것(프로그래밍을 포함)에 대해 건강한 경험적 가이드라인(휴리스틱스, heuristics)을 제시하는 책으로 교육적 가치도 높다. 이 책을 공부하고('읽고'가 아니라) 나면 한층 똑똑해진 자신을 발견할 수 있다.

◆ Godel, Escher, Bach: An Eternal Golden Braid, Hofstadter, Douglas R.
GEB라고도 불리는 이 책은, 저자 호프슈테더 교수에게 풀리처상을 안겨줬다. 아마 컴퓨터 관련 직종뿐만 아니라 자연과학, 철학 쪽에서까지 널리 읽히는 인기 서적이 아닐까 한다. 수학의 괴델과, 회화의 에셔, 음악의 바흐 작품을 비교하며 공통점을 찾는다. 전산학의 시원이라 할 수 있는 튜링 컴퓨터에 대한 설명이 있다.

◆ Computer Architecture: A Quantitative Approach, Patterson, David A., et al.
전문 프로그래머라면 하드웨어적인 지식도 절대 놓쳐서는 안된다. 이러한 지식을 아는 사람과 그렇지 못한 사람의 프로그래밍 능력과 몸값은 엄청난 차이가 있다. 컴퓨터 아키텍처에 관한 한 최고의 양서로 평가받는 이 책은 학부생이나 평범한 프로그래머들이 보기엔 다소 난해할 수 있다. 그럴 경우에 같은 저자의 'Computer Organization and Design'을 보는 것이 좋다.

◆ Elements of Style, Strunk, William and E.B. White
영미권에서 작문 관련 서적으로 가장 많이 팔린 책이다. 브라이언 커니건과 플로거가 쓴 'The Elements of Programming Style'은 이 책의 제목을 흉내낸 것이다.
영미인과 문법이나 철자법 등에 대한 논쟁을 하다가도 "스트렁크와 화이트의 책에 따르면"이라는 한마디면 종지부를 맺을 수 있을 정도로 권위적인 책이다. 특히 5장 스타일에 대한 가이드는 기술적 문서를 작성할 때는 물론이고 프로그래밍을 할 때에도 참고가 될 것이다.

◆ The Psychology of Computer Programming, Weinberg, Gerald M.
이 책은 에릭 레이먼드가 썼던 '성당과 시장'에서 비자아적 프로그래머(egoless programmer)에 관한 언급으로 국내에 많이 알려졌지만, 사실 영미권에서는 이미 베스트 셀러의 반열에 오른 지 몇 십 년이 됐다.
프로그래밍을 인간 활동의 하나로 인식하고 심리학적인 접근을 통해 새로운 분야를 세운 기념비적인 책이다. 아직까지도 ACM이나 IEEE 회원들이 가장 많이 구입하는 책 중 하나이며, 최근 실버 기념판이 출판됐다.

◆ ACM Turing Award Lectures : The First Twenty Years : 1966 to 1985
튜링상은 컴퓨터 분야의 노벨상이다. 우리가 실제로 사용하고 있는 거의 모든 기술의 원천은 튜링상 수상자들의 작품이다. 이 책은 튜링상 수상시 함께 하도록 돼있는 강의 내용을 20년간 모은 것이다. 한눈에 컴퓨터계의 발전 역사를 조망할 수 있으며, 선지자들이 조심스럽게 말하는 앞으로의 발전 방향도 엿볼 수 있다.
특별히 엣져 다익스트라(Edsgar Dijkstra)의 'The Humble Programmer'와 도널드 크누쓰의 'Computer Programming as an Art'는 꼭 읽어볼 만하다. 각각 72년, 74년에 한 강의이지만, 많은 부분이 오늘날에도 유효하다는 사실이 그 페이퍼의 질을 보장해 준다.

소개한 책들은 이미 십년 이상을 살아 남았고 앞으로도 최소 오년 이상 가치를 유지할(혹은 더 높아질) 책이 대부분이다. 그런데 모아 놓고 보니 모두가 원서다. 참 슬픈 일이다. 아직까지 우리나라에 그 가치가 최소 오년 이상 되는 책이 쓰여지고 있지 않다는 것은 짧은 역사와 기술 도입만으로는 설명하기 힘들다. 게다가 필자가 아는 한 그나마 두 권(GEB, How to Solve It)을 빼놓고는 모조리 번역 작업조차 되지 않았다.

멀리 보지 못하고, 멀리 볼 겨를도 없는 우리 신세가 안타깝지만, 조만간 이런 작업들이 진행되리라는 일말의 희망을 걸어본다.

@정기 간행물

필자는 과거를 보려면 서점에 나가보고, 현재를 보려면 정기 간행물이나 논문을 살펴보고, 미래를 보려면 현장 (아카데미아와 기업계)을 뛰어다녀 봐야 한다고 생각한다.
이미 서점에 판을 치고 있는 기술들은 그 정보가치가 많이 하락한 것들이고 소위 '끝물'일 확률이 높다. 주식의 "소문에 사고 뉴스에 팔아라"는 말이 적용되는 것이다. 잡지 같은 것은 비교적 출간 사이클이 짧고, 이에 따라 현실 세계를 조금 더 빨리 반영한다. 국내에도 물론 좋은 잡지와 저널이 많이 있지만 여기서는 언급을 피하도록 하겠다.

◆ Software Development(www.sdmagazine.com)
이 잡지는 특정 기술이나 팁보다는 전문 프로그래머가 접하는 일반적인 프로그래밍 관련 이슈를 다룬다. 소프트웨어 공학, 개발 방법론, 프로그래머란 직업에 대한 기사들 혹은 프로젝트 관리자에게 도움이 될만한 것들이 많고, 개발 툴 리뷰도 유익하다. 특히 일년에 한번씩 있는 졸트상 수상은 꼭 놓치지 말아야할 좋은 정보다

◆ Dr. Dobb's Journal(www.ddj.com)
제목에는 저널이라고 되어 있지만 그다지 아카데믹한 내용은 아니다. 비교적 이론적이고 코드 지향적인 성격의 잡지라고 보면 된다. 알고리즘 분야에 상당히 강하다. 도구나 기술 사용법의 연마도 중요하지만 도구/기술의 이면에 있는 이론으로 중무장하는 것은 '전문 프로그래머'가 되기 위해선 반드시 해야할 일이다.

◆ Information Week(www.informationweek.com)
아무리 개발자라고 해도 비즈니스적인 변화는 늘 감지하고 있는 것이 좋다. 어떤 기술이 잘 팔리고 향후 어떤 기술이 주목을 받을지, 지금 내가 의지하고 있는 배가 침몰 중이지는 않은지 등을 말이다.

◆ Communications of ACM(www.acm.org)
가장 오래되고, 또 가장 인정(?)받는 컴퓨터 관련 저널 중 하나. IEEE Computer처럼 다루는 분야가 매우 넓기 때문에 대부분의 기사가 자신의 관심사 밖의 것일 수도 있는데, 컴퓨터 관련 이론/기술의 원류가 되는 만큼 자신의 분야를 막론하고 꼭 구독해 볼 가치가 있는 잡지이다. 이곳에 기사가 실리고 몇 년 지나야 비로소 관련 내용을 여타 잡지에서 확인하는 경우도 종종 있다.

◆ IEEE Software(www.computer.org)
격월 잡지로 소프트웨어 개발 방법론이나 여타 소프트웨어 관련 주제를 다룬다. 전문 프로그래머들에게 도움이 될만한 실질적인 기사가 많이 있다. IEEE Computer는 앞서 소개한 CACM과 비슷한 성격인데, IEEE Software보다는 다루는 주제의 범위가 훨씬 넓다.

@모임

컴퓨터 분야에는 현재 두 개의 '세계 수준의' 전문가 모임이 존재한다. ACM(Association for Computing Machinery)과 IEEE 컴퓨터 소사이어티가 그것이다. 전문 프로그래머(세계 수준의)라면 최소한 둘 중 하나에는 가입되어 있는 것이 일반적이다. 국내에도 다양한 전문가 단체가 있는데, 자신의 관심 분야 한 곳과 일반적인 한 곳은 꼭 가입을 해두는 것이 좋다.
또한 통신 동호회나 스터디 그룹과 같은 비격식적인 모임에도 참여를 하고, 자신과 다른 분야에서 일을 하는 전문가들과 지속적인 접촉을 유지하는 것이 세상에 뒤쳐지지 않는 방법이다. 항상 다른 사람들이 '현재 고민하는 것'이 무엇이고, '성취하고자 하는 것'이 무엇이며, '과거에 어떤 교훈을 얻었는지'의 세 가지를 탐지할 일이다.

@효과적인 공부법

심리학에서 스키너 박스는 행동주의(Behaviorism)의 대표적인 실험인데, 상자 안에 생쥐를 가둬두고 그 놈이 버튼 혹은 레버를 누를 때마다 구멍으로 먹이를 보내준다. 처음에는 그 버튼이, 레버가 무슨 의미인지를 알지 못하다가 우연히 그것을 누르고는 먹이를 먹는다. 물론 당시에는 그 두 가지 사건을 연관지어 생각하지 못한다. 하지만 시간이 갈수록 학습을 하게 되고, 배가 고플 때면 버튼을 알아서 누른다. 인간의 학습에 대한 이런 스키너 박스식 접근은 이미 폐기 처분된 지 오래지만, 여전히 유효한 것들이 몇 가지 있다. 이 실험에서 버튼이 눌려진 때와 먹이를 보내주는 때의 시간 차이를 늘려주면 학습이 느려지거나 혹은 아예 학습이 일어나지 않는다. 우리가 학습을 할 때 피드백이라는 것은 아주 중요한 역할을 한다. 내가 무엇을 잘못했는지, 제대로 했는지를 즉각적으로 알 수 있으면 바로 자신의 이전 행동에 대한 수정이 가능하고 이는 새로운 학습으로 이어질 수 있다. 이런 면에서 파이썬이나 스몰토크 같은 대화형 인터프리터 언어는 중요한 위치를 차지한다. 난생 처음 파이썬을 대하는 사람이 단박에 문자열을 출력해 본다든지, 사칙연산을 해본다든지 하는 경험은 다른 컴파일러 언어에서 쉽게 체험할 수 없는 '놀라운 학습'의 경험인 것이다.
주변에서 보면 처음부터 모든 완벽을 기하려는 사람보다 조금씩 시도해 보고 또 수정하고, 다시 시도하는 소위 점진적 접근법을 행하는 사람들이 더 빨리 학습하는 경우가 많이 있다. 예컨대, HTML을 공부할 때 처음부터 태그를 외우고 프로토콜의 정의를 이해하고, 문법을 외우는 등 '정규 코스'를 밟은 후에 각종 HTML 에디터를 공부하는 경우와, 나모 같은 소프트웨어를 통해 손쉽게 만들어 본 것을 바로 확인해 보고 또 수정하고 하는 식으로 일단 감을 잡은 사람이 차후에 태그나 문법을 공부하는 경우를 비교해 볼 수 있다. 규칙 중심적 학습은 경험 중심적 학습에 비해 훨씬 더 어렵고 비효율적일 수밖에 없다. 규칙은 '데이터'가, 실제 경험이 이미 내 안에 있는 이후에나 의미가 있다. 아담이 말을 보고 '말'이라고 이름 지은 것은 말을 보기 전이 아니라 그 후였음을 생각해 봐야 할 것이다.
자신이 사고하는 것에 대해 사고하는 것, 이 이차적 사고를 메타인지(meta-cognition)라고 한다. 자신의 잘못을 스스로 인식하고 그것에 대해 생각해 보는 것도 훌륭한 학습의 경험이 된다. 예컨대, 25-16을 19라고 대답한 학생과 41이라고 대답한 학생을 생각해 보자. 만약 학생들이 독학하는 것이 아니고 '보통' 선생님의 가르침을 받고 있다고 치면, 그 둘은 똑같이 틀렸다는 말을 듣고 자신의 실수를 잊어버릴 것이다. 하지만 두 번째 학생의 경우 명백히 뺄셈 대신 더하기를 했다는 것을 알 수 있고, 첫 번째 학생의 경우도 뺄셈을 하되 십의 자리에서 뭔가 문제가 있었다는 것을 알 수 있다. 이런 정보를 기반으로 개개인에게 좀 더 훌륭한 학습의 기회를 제공할 수 있다. 혼자 프로그래밍을 공부하는 사람이라면 자신의 프로그램이 제대로 돌지 않는 경우, 자신의 잘못을 분석하고 어떤 '사고의 틀'이 문제를 일으켰는지 생각해 봐야 한다. 한마디로 '자기 자신을 볼 줄 알아야 한다'는 것이다. 이것이 남보다 빨리 학습하는 비결이다.
by 필라르 | 2004/03/30 17:54 | About Programming | 트랙백 | 덧글(0)
2004년 03월 30일
프로그래밍은 예술이다
프로그래밍은 예술이다

저 자 : 임백준 출판일 : 2004년 1월호


필자는 프로그래밍을 비교적 늦은 나이인 이십대 중반에 시작했다. 따라서 독학을 통해서 익힌 ‘초식’이 많았는데 그래서인지 10년이 지나도록 잘 고쳐지지 않는 습관이 하나 있다. 머리 속에 알고리즘의 윤곽이 떠오르면 일단 키보드를 붙잡고 코드를 두드려야만 직성이 풀리는 것이다. 그렇게 하지 않으면 다음 내용이 잘 떠오르지 않는다. 프로그래밍 방법론이나 소프트웨어 공학의 충고에 의하면 이것은 ‘코딩’이 ‘설계’에 앞서는 대단히 잘못된 방법에 속한다. 교과서에 적힌 기본을 무시하는 철저한 아마추어리즘의 소산인 것이다.

@프로그래밍의 맛
여러 명의 개발자가 함께 코딩을 하는 경우에는 물론 얘기가 다르다. 그런 경우에는 레쇼날 로즈(Rational Rose) 같은 소프트웨어나 객체 설계용 언어인 UML(Universal Modeling Language)을 이용해서 어느 정도 설계를 마친 다음에 코딩을 시작할 수밖에 없다. 하지만 프로그래밍을 혼자서 할 때는 언제나 ‘코딩’이 ‘설계’를 앞선다. “진정한 ‘프로’는 설계를 마친 다음에 비로소 키보드를 잡는 거야”라고 아무리 말해도 소용이 없다. 커피를 마실 때 크림을 넣지 않으면 맛이 느껴지지 않는 것처럼 손끝에 전달되는 키보드의 감촉이 없으면 프로그래밍의 ‘맛’이 느껴지지 않는다.
이런 습관은 회사에서 수행하는 공식적인 프로그래밍에도 종종 연결된다. 외부의 API가 모두 결정된 상태에서 독립적인 컴포넌트의 내부를 구현하는 경우에는 예외 없이 코딩을 통해서 설계가 시작된다. 화면에 뜬 편집기(필자의 경우에는 주로 vi)라는 캔버스 위에 키보드 커서라는 연필을 조금씩 움직여 나가면 머리 속에 감추어져 있던 알고리즘이 서서히 눈앞에 모습을 드러낸다. 때로는 종이 위에 동그라미, 네모, 선 등을 그리면서 설계를 하는 경우도 있지만 그것은 어디까지나 키보드를 통해서 하는 붓질을 돕는 보조적인 조치일 뿐이다.
프로그래밍에 ‘조예’가 있는 독자라면 이런 습관은 그다지 자랑할 바가 아니라고 생각할 것이다. 당연하다. 필자도 아주 최근까지 그렇게 생각했다. 그렇지만 프로그래머 중에서 이와 같은 습관을 가지고 있는 사람이 적지 않으리라는 점은 분명하다. 손끝에 키보드의 감촉이 전달될 때 비로소 프로그래밍의 맛을 느끼는 사람은 결코 필자에 국한되는 얘기가 아닐 것이다. 하지만 그런 사람들조차 대부분 ‘설계’에 앞서는 ‘코딩’은 자랑할 바가 아니라고 생각한다. 특히 프로그래밍 실력이 뛰어난 고수일수록 설계를 마치기 전에는 키보드를 넘실거리지 않을 것이라고 믿는다. 뒤집어 말하면 설계를 끝내기 전에 키보드를 만지작거리는 사람은 일종의 ‘하수’로 간주되는 셈이다.

@프로그래밍 예술론
필자가 이와 같은 ‘설계’와 ‘코딩’의 관계를 포함하여 흔히 알려진 프로그래밍의 방법론이나 소프트웨어 공학의 ‘교리’를 의심하기 시작한 것은 (지난 해에 두 권의 책을 쓰면서) 프로그래밍의 본질이 ‘공학’에 있는가 아니면, ‘예술’에 있는가 하는 문제를 고민하면서부터였다. 프로그래밍이 도대체 예술일 수 있는가에 대한 답을 구하려면 우선 예술이 무엇을 의미하는지 이해해야 하는데 그것은 간단하지 않은 주제이므로 여기서 다루기 어렵다. 하지만 한 가지 분명한 것은 필자의 관점에서 볼 때 프로그래밍은 공학적 요소를 포함하고 있긴 하지만 분명히 예술에 더 가깝다는 점이다.
프로그래밍을 예술로 파악하는 것은 물론 새로운 관점이 아니다. 「프로그래밍의 예술(The Art of Computer Programming」로 유명한 스탠포드 대학의 도날드 카누스(Donald Knuth) 교수는 일찍이 「문학적 프로그래밍(Literate Programming, CSLI, 1992)」이라는 책에서 ‘프로그래밍은 예술’이라고 선언한 바 있다. 그는 이러한 선언을 한 걸음 더 밀고 나아가서 프로그램 소스 코드도 다른 예술 작품들과 마찬가지로 미학적 요소와 독창성을 고려해서 ‘값’이 매겨지는 시대가 도래할 것이라고 예언하기까지 했다.

@문학적 프로그래밍이란
카누스 교수가 말한 ‘문학적 프로그래밍’이란 사실 단순한 비유에서 그치는 것이 아니라 코드의 예술성을 담보하기 위한 일종의 구체적인 프로그래밍 방법론이었다. 우리나라에서는 「생각하는 프로그래밍」이라는 책으로 번역된 ‘프로그래밍 펄(Programming Pearl)’이라는 컬럼으로 널리 알려진 존 벤틀리(John Bentley)는 카누스 교수가 ‘문학적 프로그래밍’을 설명한 글을 읽고 감명을 받은 나머지 자신의 컬럼 몇 개를 카누스 교수의 새로운 방법론을 소개하는데 바치기도 했다.
‘프로그래밍은 예술’이라는 명제는 사실 수학 명제처럼 명쾌하게 증명될 수 있는 것이 아니다. 그러나 프로그래밍을 하는 사람이라면, 그 ‘맛’을 조금이라도 아는 사람이라면, 이 명제를 간단하게 거부하지 못할 것이다. 오픈소스 프로젝트에 참여하여 자신의 여가시간마저 프로그래밍에 바치는 해커든, 아니면 회사에 출퇴근하면서 정해진 틀에 따라 코딩을 하는 ‘월급쟁이’이든 상관이 없다. 프로그래밍이 단순히 기술이나 공학의 수준에 머무르지 않는다는 사실은 누구에게나 분명하다. 프로그래밍이라는 행위 안에는 꼭 집어서 설명할 수 없지만 가슴이 떨리고 흥분이 밀려오는 ‘창조적 긴장’의 순간이 담겨 있기 때문이다.
카누스 교수는 스스로 수학적 논리와 알고리즘에 대해서 실로 심오한 내공을 갖추고 있었다. 그런 맥락에서 그는 프로그래밍이 가지고 있는 ‘과학적 미학’의 측면을 강조했다. 이에 비해서 폴 그래이엄(Paul Graham)은 프로그래밍에 담겨 있는 ‘창조적 미학’의 측면을 날카롭게 부각시켰다. 그래이엄은 하버드에서 컴퓨터 과학(Computer Science) 박사 학위를 받고 인공지능 언어인 리스프(LISP)에 대한 교과서를 쓸 정도로 내공이 중후한 프로그래머였다. 뿐만 아니라 인터넷 붐이 한창이던 1998년에 ViaWeb이라는 회사를 야후에 팔아서 ‘비즈니스맨’으로서도 이름을 얻었다.
그래이엄은 프로그래밍에 담긴 예술의 측면을 설명하기 위해서 프로그래밍을 그림 그리는 행위에 비유했다. 앞에서 그를 소개하면서 내공이 중후한 ‘프로그래머였다고’ 말한 이유는 그가 지금은 그림(painting)을 공부하여 화가의 길을 걷고 있기 때문이다. 그가 보기에 프로그래밍은 순수한 논리나 학문의 대상이라기보다는 ‘실천적 행위’를 통해서 몸에 익혀 가는 구체적인 ‘행동’에 가까웠다. 그것은 마치 텅빈 백지 위에 붓을 한 번 크게 긋는 행위와 다를 바 없었다. 그래서 그는 컴퓨터 과학이라는 표현이 프로그래밍의 진정한 속성을 정확하게 담지 못한다고 비판했다.
프로그래밍이 ‘컴퓨터 과학’ 혹은 ‘컴퓨터 공학’과 같지 않은 이유는 그림을 그리는 예술적 실천이 물감의 화학적 배합을 연구하는 ‘학문’과 같지 않은 이유와 동일하다. 다시 말해서 그림을 그리는 화가는 물감의 화학적 성분이나 여러 화학 이론에 대해서 굳이 알 필요가 없다. 이와 마찬가지로 프로그래밍이라는 창조적 활동을 하는 사람(즉, 프로그래머)들은 컴퓨터 과학과 공학의 수많은 이론을 굳이 자세하게 알 필요가 없다. 예를 들어서 튜링 기계(turing mach ine)나 오토마타(automata)의 개념 정도는 알 필요가 있을지 몰라도 복잡성 이론(complexity theory)에 등장하는 명제를 모두 읽어야만 좋은 프로그램을 만들 수 있는 것은 아니다.

@코딩이 설계에 앞선다?
그래이엄을 알기 전까지 필자는 ‘코딩’이 ‘설계’를 앞서는 습관을 ‘아마추어리즘’의 표현이라고 생각해 왔다. 진정한 프로라면 교과서에서 가르치는 대로 정확하게 설계를 마친 다음 비로소 코딩을 시작해야 하는 것이라고 생각했다. 이런 강박관념은 일종의 열등감마저 수반했는데 그래이엄의 통찰은 필자를 ‘예술’이라는 아름다운 이름과 함께 구원해 주었다. 프로그래밍을 예술로 바라보는 관점에서 생각해 보면 ‘판에 박힌 듯한’ 소프트웨어 개발 방법론은 프로그래머 개개인의 감성을 존중하기보다는 정해진 틀에 맞는 상품을 생산하기 원하는 기업의 욕망을 반영하고 있다. ‘획일적인 틀’은 상품 생산을 위해서 필요할 뿐 진정한 창조와 아무런 상관이 없기 때문이다.
뛰어난 프로그래머였던 그래이엄은 자기 자신도 프로그래밍을 할 때 키보드를 붙잡고 코딩부터 시작한다고 고백했다. 그가 밝힌 방법은 우선 가볍게 키보드를 두드리면서 코드의 전체 윤곽을 잡고, 다시 처음으로 돌아가서 조금씩 각 부분의 디테일을 살려 나가는 방식으로 프로그램을 작성하는 것이었다. 그는 코딩이 설계에 앞서는 이와 같은 방식을 조금도 이상하게 여기지 않았다. 오히려 그는 모든 예술적 창조가 대개 이와 비슷한 과정을 거치면서 이루어지며 그림을 그리는 과정도 이와 다르지 않다고 말했다. 그리고 미술에서는 그것을 ‘스케치’라는 자연스러운 이름으로 부른다고 지적했다.
혹시 필자가 이 글을 통해서 ‘코딩은 설계에 앞서야 한다’는 명제를 주장하고 있다고 잘못 이해하지 않기 바란다. 그것은 손으로 달을 가리켰더니 손가락만 바라보더라는 이야기와 다를 바 없는 오해가 될 것이다. 여러 명이 함께 복잡한 소프트웨어를 만들 때 ‘설계’의 과정이 결정적으로 중요하다는 사실에는 이견이 있을 수 없다. 다만 필자는 소프트웨어의 ‘생산성’을 높이기 위한 방법론이 반드시 프로그래밍의 ‘예술성’을 강화시키는 쪽으로 작용하지 않는다는, 아니 정확하게 말하자면 그 반대의 방향으로 작용한다는 사실을 지적하고 싶었을 뿐이다.
그럼 프로그래밍의 ‘예술성’을 강조하는 프로그래머는 그렇지 않은 프로그래머에 비해서 소프트웨어 ‘생산성’이 떨어지는 것일까? 놀랍게도 전혀 그렇지 않다. 오히려 그 반대의 경우가 더 많다. 창조의 기쁨을 아는 사람과 그렇지 않은 사람이 발휘하는 능력에는 본질적인 차이가 존재하기 때문이다. 필자가 이 글을 통해서 말하고 싶은 것이 바로 그 차이이다. ‘기쁨’이 있는 사람과 없는 사람 사이에 존재하는 차이는 프로그래밍의 예술적 속성을 이해하는데 있어서 핵심적인 열쇠가 된다.
컬럼의 첫 번째 시간이다 보니 두서없이 시작한 감이 없지 않지만, 앞으로 이 컬럼에서는 ‘행복한 프로그래밍’이란 대 전제 하에 프로그래밍을 어떻게 받아들이고 해석해야 하는 지에 대해 소개하는 자리를 마소 독자들과 함께 만들어 보도록 하겠다.
by 필라르 | 2004/03/30 15:21 | About Programming | 트랙백 | 덧글(0)
2004년 03월 30일
프로그래머, 논쟁의 법칙
저 자 : 임백준 출판일 : 2004년 2월호

썬마이크로시스템즈(Sun Microsystems)의 제임스 고슬링(James Gosling)은 자바 언어를 개발한 것으로 널리 알려진 프로그래머이다. 장난기 넘치는 웃음을 머금고 있는 그의 모습은 밝아서 얼굴만 봐서는 나이를 가늠하기가 쉽지 않다. 하지만 금발이 찰랑거리던 젊은 시절의 모습과 달리 세월의 무게에 밀려 뒤로 벗겨진 머리는 C++ 언어를 개발한 뱐 스트라우스트럽(Bjarne Stroustrup)을 닮았고 턱 밑에 수북한 수염은 C 언어를 개발한 데니스 리치(Dennis Ritchie)를 닮았다.
캐나다의 캘거리(Calgary) 대학에서 컴퓨터공학을 공부하고 미국의 카네기 멜론(Carnegie-Mellon) 대학에서 컴퓨터공학 박사를 획득한 고슬링은 말하자면 ‘엘리트 코스’를 제대로 밟은 프로그래머였다. 야전(野戰)을 통해서 실력을 쌓은 해커들과 달리 탄탄한 제도권 안에서 내공을 쌓은 그가 훗날(처음에 비해서 의미가 모호해지긴 했지만) 해커라는 이름으로 불릴 수 있게 된 까닭은 대부분 자바 언어 덕분이었다. 개인용 PC 운영체제 시장을 독점한 마이크로소프트(이하 MS)의 전횡에 지친 프로그래머들에게 특정한 운영체제에 구애받지 않는 자바 언어는 ‘해방군’처럼 느껴졌기 때문이다.

@소프트웨어 발명가
여담이지만 1991년에 썬 마이크로시스템즈의 프로그래머 13명이 모여서 차세대 셋탑(Set-Top) TV를 위한 기술을 개발하는 ‘그린 프로젝트’가 자바 언어의 탄생 배경이었다는 사실은 유명하다. ‘그린 팀’의 목적은 새로운 언어를 개발하는 것과 거리가 멀었으며 자바는 다만 프로젝트의 진행을 돕기 위해서 고안된 프로그래밍 도구에 불과했다. 그런 자바가 90년대에 C와 C++의 아성에 도전하는 새로운 프로그래밍 언어로서 성공을 거두게 된 데에는 인터넷이라는 환경이 작용한 바가 크지만, 당시 프로그래머들 사이에서 더 명료한 객체지향 언어에 대한 요구가 존재했기 때문이기도 하다.
자바의 성공에 자극받은 MS는 C++의 뒤를 잇는 객체지향 언어인 C#을 발표했지만 이미 자바대 비(非)자바의 양강 구도로 정착된 대세를 바꾸기에는 역부족이었다. 제임스 고슬링은 MS가 C# 언어를 준비하고 있다는 소식을 처음 접했을 때 몹시 긴장할 수밖에 없었다고 고백했다. 하지만 C# 언어가 모습을 드러낸 이후인 2002년 1월에 씨넷(CNET)과의 인터뷰를 할 때에는 C#을 일컬어서 “안정성(reliability), 생산성(productivity), 그리고 보안성(security)을 제거한 자바 언어에 불과하다”고 일축했다. 뿐만 아니라 자바를 폄하하던 MS가 뒤늦게나마 자바와 비슷한 언어를 설계했다는 것은 결국 “자바에 대해서 최대의 찬사를 보낸 것”이라고 말하여 익살을 부리기도 했다.
고슬링은 자바의 초기 문법 구조를 설계하고 컴파일러와 자바 가상기계를 구현한 핵심 프로그래머였기 때문에 흔히 ‘자바의 발명가(Inventor of Java)’라고 불린다. 자바를 발명한 것은 분명히 제임스 고슬링 한 사람이 아니었지만 C의 데니스 리치와 C++의 뱐 스트라우스트럽처럼 고슬링의 이름 앞에는 항상 자바가 따라다니게 되었다. 프로그래밍 언어가 아니더라도 유닉스의 켄 톰슨(Ken Thompson), 리눅스의 리누스 토발즈(Linus Torvalds), 넷스케이프의 마크 엔드리슨(Marc Andreesen), GNU의 리차드 스톨만(Richard Stallman)처럼 한 시대를 풍미한 소프트웨어의 ‘발명가’로 불리는 것은 프로그래머에게 있어서 무엇과도 바꿀 수 없는 최고의 영광임에 틀림없다(GNU는 물론 한 개의 소프트웨어가 아니다).

@프로그래머들의 논쟁
그래서 프로그래머들은 종종 특정한 소프트웨어나 알고리즘의 구현을 둘러싼 ‘크레딧(credit)’을 놓고 격렬한 논쟁을 벌이기도 한다(철학자 헤겔이 말했던 ‘인정 투쟁’을 벌이는 셈이다). 리누스 토발즈의 자서전인 『리눅스 그냥 재미로(Just For Fun)』에서 소개된 리누스 본인과 앤드류 타넨바움 사이의 논쟁은 건설적인 논쟁의 예가 된다. 운영체제 학습을 위한 소형 운영체제였던 미닉스의 저자 타넨바움과 새롭게 부상하는 차세대 운영체제인 리눅스를 설계한 토발즈가 ‘마이크로 커널’과 ‘모놀리틱 시스템’의 장단점을 놓고 한판 논쟁을 벌이는 과정은 논쟁의 내용을 떠나서 그 자체로 많은 사람들에게 흥분과 관심의 대상이 되었다(그리고 이 논쟁은 서로에 대한 예의를 잃지 않은 적정한 선에서 정리가 되었다).
그러나 프로그래머 사이의 논쟁은 때때로 감정을 자극하는 파괴적인 다툼으로 발전하여 서로에게 상처만 입히는 싸움으로 끝나는 경우도 많다(크레딧을 둘러싼 이러한 다툼은 유명한 프로그래머 사이에서만 일어나는 일이 아니다. 필자와 같은 평범한 프로그래머, 특히 회사에서 월급을 받으며 생활하는 프로그래머에게 있어서 크레딧을 잘 관리하고 논쟁의 수위와 방향을 조절하는 능력은 프로그램을 잘 짜는 일 못지않게 중요하다). 유닉스 환경에서 vi와 함께 널리 사용되는 문서 편집기인 이맥스(Emacs)를 둘러싸고 제임스 고슬링과 자유 소프트웨어 운동의 대부(代父) 리차드 스톨만 사이에 있었던 크레딧 논쟁은 수위가 잘못 조절되어 파국으로 끝난 잘못된 논쟁의 예에 속한다.
스톨만이 지난 1986년에 스웨덴에 있는 대학에서 강연할 때 이맥스와 관련해서 다음과 같은 일화를 밝힌 적이 있다. 다음은 GNU의 웹 사이트에 있는 원고(http://www.gnu. org/philosophy/stallman-kth.html)에서 강연 내용의 일부를 발췌하여 내용을 일부 번역한 것이다.

“두 해 전에 한 친구가 자신은 고슬링 이맥스(Gosling Emacs)의 초기 개발에 관여했기 때문에 고슬링이 자기에게 이맥스를 배포할 수 있는 권리를 허락했다고 말했다. 고슬링은 내가 원래 이맥스를 가지고 시작했던 철학을 따르겠다는 입장을 취했기 때문에 많은 사람들의 협력을 구할 수 있었다. 그렇지만 그는 자신의 소프트웨어에 카피라이트를 적용함으로써 모든 사람들의 등에 칼을 꽂았다. 아무도 그것을 재배포할 수 없도록 만든 다음 자신은 그것을 한 소프트웨어 회사에 팔아넘겼다. 내가 고슬링과의 개인적인 교류를 통해서 확인한 것은 바로 이와 같은 사실로부터 알 수 있듯이 그가 비열하고 천박한 종류의 인간이라는 점이었다.”

프로그래머 중에서 리차드 스톨만을 모르는 사람은 거의 없을 것이다. 또한 유닉스 환경에서 프로그래밍을 하는 사람이라면 GNU에서 개발하여 무료로 배포하는 소프트웨어 도구를 한 번쯤 사용하지 않았을 가능성이 거의 없다. 오픈소스 운동보다 먼저 시작된 자유 소프트웨어 운동의 지도자에 해당하는 스톨만은 ‘자유’와 ‘저항’이라는 해커 정신의 핵심을 포기하지 않았기 때문에 프로그래머들보다 오히려 인터넷이나 사이버스페이스 같은 열쇠 말을 연구하는 사회학자나 철학자에게 더 많이 알려져 있을 정도이다.
많은 사람들에게 크레딧을 받고 있는 스톨만은 이렇게 강력한 어조로 또 다른 일군의 프로그래머들에게 ‘리더’로서의 존경을 받는 제임스 고슬링을 비판했다. 이러한 스톨만의 비판에 대해서 고슬링의 입장을 변호하는 사람들은 스톨만이 그래픽 사용자 인터페이스(Graphic User Interface)는 물론 마우스의 사용까지 혐오하는 고지식한 ‘텍스트 모드’ 마니아이며, 고슬링은 따라서 스톨만이 제작했던 조야한 초기 버전을 사용자들에게 더 친숙한 소프트웨어로 개선할 수밖에 없었다고 항변했다. 그리고 그에 덧붙여서 스톨만은 (GNU/Linux의 예에서 볼 수 있듯이) 자기가 조금도 관여하지 않은 소프트웨어를 통해서 크레딧을 얻으려고 애를 쓰며, 다른 사람이 자기보다 성공하거나 주목받는 것을 견디지 못하는 속 좁은 인간이라는 인신공격에 가까운 비판을 퍼부었다.
이런 식의 주장은 이미 기술적인 측면에 초점을 두는 건설적인 논쟁의 궤도를 벗어나서 서로의 철학과 정치적 입장 혹은 인간성에 대한 비판으로 나아가는 위험천만한 다툼에 해당한다. 양쪽의 주장이(구체적으로 입증할 수 없는 근거를 기초로 해서) 팽팽하게 맞서고 있기 때문에 사람들은 누구의 말을 들어야 할지 쉽게 판단하기 어렵다. 따라서 사람들 중에는 이맥스의 ‘발명가’를 스톨만으로 알고 있는 사람도 있고 고슬링으로 알고 있는 사람도 있다. 하지만 이와 같은 경우에는 크레딧을 누가 가져가든 당자를 제외한 3자에게는 아무 의미가 없다(스톨만의 비판은 고슬링이 자유 소프트웨어 정신을 배신했다는 점에 핵심이 놓여 있다. 반면 고슬링 쪽에서는 스톨만이 크레딧에 집착한 나머지 다른 사람의 정당한 공헌을 왜곡한다는 점, 그리고 절실히 요구되는 기술적 개선을 외면한다는 점을 지적하고 있다. 하지만 이런 것은 차원이 다른 문제이다. 이맥스의 주인공이 스톨만이든 고슬링이든 사용자들은 개의치 않는다!).

@논쟁의 수위 조절
프로그래밍은 속성상 다른 분야의 일에 비해서 ‘공(功)’과 ‘과(過)’가 비교적 뚜렷하게 구분된다. 예를 들어서 고객이 사용하고 있는 소프트웨어에 중대한 결함이 생겨서 일정한 기간 내에 결함을 반드시 수정해야 하는 경우가 발생했다고 하자. 이 경우 문제가 간단하게 해결될 수 있는 성질의 것이 아니라면 실력이 뛰어난 프로그래머 몇 사람이 달라붙어서 밤을 새우며 디버깅을 해야 할 지도 모른다. 이 때 문제를 해결한 사람은 영웅이 되고 그 문제를 야기한 코드의 주인공은 졸지에 역적이 된다. 약간 과장된 표현이긴 하지만 프로그래밍을 하는 사람이라면 영웅이 되는 우쭐한 기분도, 역적으로 내몰리는 서글픈 기분도 맛본 적이 있을 것이다.
필자가 일하는 프로젝트의 구성원들은 미국에 있는 직원들과 영국에 있는 직원들이 반씩 섞여 있기 때문에 대개 5~6 시간의 시차를 두고 일을 한다. 아무래도 얼굴을 맞대고 있는 사람들끼리 나누는 의사소통이 편하기 때문에 소프트웨어를 몇 개의 큼직한 컴포넌트로 나눈 다음, 몇 개는 미국 부서에서 구현하고 나머지 몇 개는 영국 부서에서 구현한다. 이렇다 보니 사용자 필드에서 치명적인 문제가 보고 되었을 때 문제의 원인이 어느 컴포넌트에 존재하는지를 규명하는 일은 항상 (두 지역의 프로그래머 사이에서) 심각한 수준의 논쟁을 수반한다. 이 때 필자가 늘 마음속으로 긴장하면서 노력하는 것은 논쟁의 ‘수위’를 알맞게 조절하여 합리적인 결론을 도출하는 일이다.
필자와 함께 일하는 미국 친구 중 한명은 매우 뛰어난 프로그래밍 실력을 갖추고 있음에도 불구하고 이와 같은 논쟁의 상황이 전개되면 쉽게 이성을 잃고 흥분하여 크레딧을 스스로 까먹는 경우가 많다. 유심히 살펴보면 프로그래밍 실력이 뛰어나고 자아가 강한 사람일수록 자기의 의견에 맞서는 논쟁을 견디지 못하는 경우가 더 흔하다. 이런 사람들은 쉽게 흥분하여 합리적인 근거에 입각한 주장보다 인신공격에 가까운 표현을 구사하여 논쟁의 발전적 가능성을 차단시킨다. 필자는 스톨만을 매우 존경했고 지금도 존경하고 있지만, 그가 자바에 대해서 비교적 냉담한 자세를 취하는 이유의 상당 부분이 고슬링과의 개인적인 악연에 기인한다는 주장을 (어느 곳에선가) 읽고 크게 실망한 적이 있었다. 논쟁을 논쟁 자체로 끝내지 못하고 그 이후의 개인 감정으로 끌고 들어오는 것은 상당히 잘못된 일이기 때문이다.

@논쟁도 즐겨라
결론을 내려 보자. 지난 컬럼에서 필자는 ‘기쁨’이 있는 프로그래머와 그렇지 않은 프로그래머 사이에는 큰 차이가 있을 수밖에 없다고 말했다. 예술적 창의력이 있는 사람과 없는 사람의 차이에 대해서도 언급했다(참고로 지난 글의 말미에서 분명히 밝혔음에도 불구하고 필자가 ‘설계에 앞서는 코딩이 예술이다’ 혹은 ‘코딩이 설계에 앞서야 한다’고 주장한다고 잘못 이해한 사람도 있었다. 상대방의 이야기를 이렇게 엉뚱하게 이해하는 것도 잘못된 논쟁 방식의 예가 된다!).
이번에 이야기하고자 하는 내용은 ‘논쟁’을 건설적으로 이끌어 가며 즐길 수 있는 프로그래머와 그렇지 않은 프로그래머 사이에는 시간이 흐르면 큰 차이가 생길 수밖에 없다는 점이다. 자신의 의견에 맞서는 ‘논쟁’을 고맙게 생각하여 힘껏 즐기고 또한 (지위 고하를 막론하고) 자신의 생각과 다른 의견에 대해서 끊임없이 의심하여 논쟁을 제기하기를 두려워하지 말 일이다. 예의를 잃지 않는 논쟁은 프로그래밍 실력을 키우는 가장 큰 지름길이기 때문이다.
by 필라르 | 2004/03/30 15:18 | About Programming | 트랙백 | 덧글(0)
2004년 03월 30일
SW 개발자가 되는 것은「무거운 책임이자 특권」 - UML과 래쇼날 로즈 개발자 그래디 부치 인터뷰
SW 개발자가 되는 것은「무거운 책임이자 특권」 - UML과 래쇼날 로즈 개발자 그래디 부치 인터뷰

그래디 부치(Grady Booch)는 래쇼날(Rational)의 수석 과학자로 UML과 래쇼날 로즈(Rose)를 개발한 주도적 인물 중 한 명이자 소프트웨어 공학에서는 몇 손가락 안에 꼽히는 유명인이다(www.rational.com/university/rubios.jsp 참고). 이 인터뷰는 본지 자문위원인 김창준 씨가 전자메일을 통해 진행한 것이다.

김창준 (마이크로소프트웨어) 2002/11/14

Q:좋은 소프트웨어를 빨리 만들기 위해서는 오늘날 무엇이 필요한가요?
A:사실 그 질문보다도 문제는 더욱 복잡합니다. 품질과 시간에 대한 압력을 조율하는 것은 프로젝트에 주어지는 여러 가지 공학적인 영향(engineering forces) 중 두 가지를 조절하는 것에 불과합니다. 비용, 일정, 기능, 호환성, 성능, 확장성(scalability), 효율(throughput), 신뢰성, 실패 안전/결함 허용(fail safe/fault tolerance), 복원력(resilience) 등이 모두 프로젝트의 비즈니스적이고 경제적인 맥락 전반에서 균형을 맞추어야 할 것들입니다.
이 모두를 고려해 반복 가능하고 예상할 수 있는 방식으로 조율하는 것은 본질적으로 어렵습니다. 이런 것들을 극복하기 위해서는 무엇이 필요할까요? 배리 보엠(Barry Boehm)은 소프트웨어 경제학에 대한 자신의 작업에서, 프로젝트를 위한 리소스 요구에 영향을 미치는 네 가지 주요 요소가 복잡성, 프로세스, 팀, 도구라고 말합니다. 그렇기 때문에 무엇이든지 간에 복잡성을 관리할 수 있게 하고, 계획된 프로세스를 제공하며, 팀에게 자신감과 힘을 주고, 도구를 통해 작업을 자동화하는 것들이 큰 도움이 될 것입니다.

Q:왜 여전히 ‘소프트웨어 위기(crisis)’가 있을까요? 최근의 통계(예컨대 스탠디쉬 그룹 보고서 같은)에 따르자면, IT 프로젝트의 상당수가 실패하거나 혹은 그럴 위험이 있다고 합니다. 실질적인 문제가 무엇이라고 보십니까?
A:내재적인 문제는 아마도 품질이 좋은 소프트웨어를 만들어 내는 것은 투자자와 개발자로 이루어진 한 팀의 집합적인 노력을 필요로 하는, 매우 어려운 지적 작업이라는 것이지 않을까요. 복잡도는 점점 증가하고 있고 거기서 문제는 더욱 악화됩니다.
궁극적으로 소프트웨어 개발은 인간 활동(human activity)입니다. 이 말은 근본 문제는 결국 인간에 관련된 것이지 기술에 관한 것이 아니라는 말이 됩니다. 하지만 기술적 요소들이 우리 문제 속 깊이 포함되어 있다는 사실 때문에 작업이 복잡해집니다. 프레드 브룩스(Fred Brooks)가 말했듯이 소프트웨어에는 본질적으로 도무지 피할 수 없는 복잡성이 있습니다.

Q:컴포넌트 기반 개발, UML, AOP(Aspect-Oriented Programming), 애자일, 웹서비스, 닷넷 혹은 최근 시장의 주목을 받고 있는 그 무엇이 이런 문제를 해결하는 데 도움이 될 것이라고 생각하십니까? 그렇다면 어떤 면에서 그렇게 생각을 하시나요?
A:그것들은 모두 어떤 해법의 요소가 될 수 있는 것들입니다. 제가 보기에는 우리가 소프트웨어를 개발하는 방식에 어떠한 혁명이 있었다고 생각지 않으며, 장래에 그러한 혁명이 있을 것이라 기대하지도 않습니다. 진보는 다른 의미있는 공학적 활동과 마찬가지로 과거의 기반 위에서 진화의 방식으로 이루어집니다. 말씀하신 것의 대부분은 본질적으로 추상화나 프로세스와 상관이 있습니다.
인간은 복잡성을 추상화를 통해 다스립니다. 실제로 소프트웨어 공학의 전체 역사는 우리의 언어나 메쏘드, 프로세스 등에서 보듯이 추상화 레벨을 증가시키는 것이었습니다. CBD (Component Based Development), UML, AOP, 웹 서비스, 닷넷, J2EE 모두가 추상화 레벨을 올려주는 예입니다. 애자일 메쏘드들과 RUP(Rational Unified Process)는 모두 프로세스를 관리하는 요소입니다. 거듭 말하지만 개발은 인간 활동이며 우리가 효과적인 베스트 프랙티스(예컨대, ‘테스트 우선’과 아키텍처를 성장시켜 나가는 것 등)를 발견할 수 있는 한 소프트웨어 개발을 어렵게 만드는 마찰점 몇 군데를 공격할 수 있지 않을까 합니다.

Q:향후 몇 년 동안 소프트웨어 개발에 있어 어떤 경향이 있으리라 예측하십니까? 당신이 보기에 유망한 기술이 있는가요?
A:래쇼날의 수석 과학자로서 제 포커스는 다음 3년에서 5년간입니다. 앨런 케이(Alan Kay)가 말했듯이 미래를 예견하는 최고의 방법은 직접 미래를 만드는 것입니다. 그래서 저는 실제로 그렇게 되게끔 세계 전역의 다양한 동료와 함께 일합니다. 제 레이다 망에 있는 것들은 플랫폼들의 부상(浮上), 컴포넌트 기반 개발, 모델 주도적 개발, AOP, 에이전트, 협동 개발 환경입니다.
애자일 메쏘드들은 최근 업계에서 엄청난 주목을 받고 있습니다. 래쇼날 역시 XP를 받아들이는(혹은 보완하는) 데 많은 관심이 있는 듯 합니다. 예를 들면 최근 발표된 XP 플러그인 같은 것 말이죠.

Q:XP가 RUP에 어떤 도움을 줄까요? 혹은 반대로 RUP가 XP에 어떤 도움을 줄 수 있을까요?
A:성공적인 프로젝트는 여러 레벨에서 이루어집니다. XP는 적은 수의 개발자 집단 내의 리듬을 언급하고, RUP는 비즈니스적이고 경제적 환경의 맥락에서 좀더 긴 리듬의 프로젝트를 언급하고 있습니다. 그렇기 때문에 애자일 메쏘드와 RUP는 무척이나 상보적이라 할 수 있습니다. 사실 저는 애자일 얼라이언스(Agile Alliance) 위원회의 한 사람이며 애자일 메쏘드를 믿고 있습니다.
그렇지만 동시에 애자일 메쏘드는 RUP에서 고려하는 이슈의 상당 부분에 대해서까지 신경을 쓰기에는 불충분하다는 것을 인식하고 있습니다. 철학적으로 말하자면, 그 둘은 양립할 수 있습니다(비록 켄트 벡과 제가 아키텍처의 역할에 대해서는 반의(反意)하자는 것에 동의(同意)하기는 했습니다만).

Q:중량 방법론자로 분류되는 것에 만족하십니까? 하지만 당신의 이전 저작을 읽어보면 많은 사람이 생각하는 것과는 달리 당신이 프로세스에 대해 했던 이야기는 상당 부분 애자일 메쏘드와 가까워 보이기도 합니다. 당신은 애자일 얼라이언스 위원회의 한 명이고, 또 XP 메일링 리스트에도 매우 적극적으로 활동하고 있습니다. 어떻게 애자일 메쏘드에 발을 들여놓게 되었으며, 당신이 받은 인상은 어땠습니까?
A:저는 켄트 벡은 물론 많은 애질리스트(agilist)와 수년 동안 친분을 쌓아왔고, 때로는 그들의 세계관을 접하고 거기에 익숙해졌습니다. 게다가 저는 제 시간의 30~40%를 고객들과 함께 보냅니다. 그렇기 때문에 저는 세계의 수만 가지 개발 스타일에 노출되어 있는 셈입니다.
래쇼날과 저는, 간단히 말하자면 조직이 더 나은 소프트웨어를 더 빨리 만들어내도록 도와주는 것에 관심이 있습니다. 애자일 메쏘드는 RUP가 침묵해 왔던 어떤 요소들에 대해 매우 유용한 아이디어들을 제공합니다. 그렇기 때문에 이 아이디어들을 흡수하는 것이죠.
더 나아가서 RUP는 프로세스가 아니라 프로세스 프레임워크이고 그런 이유로 해당 조직과 프로젝트의 목적에 맞게 구성되어야 한다(tailored)는 점을 인식해야 합니다. 어떤 환경에서는 많은 의식을 수반하는(high ceremony) 프로세스가 필요합니다. 또 반대로 다른 경우에는 적은 의식을 수반하는(low ceremony) 프로세스가 최선입니다. 경량 웹 중심 클라이언트(light-weight Web-centric clients)들의 부상 하에서, 적은 의식 메쏘드가 최근 증가하는 애플리케이션 군에 아주 효과적이라는 것이 증명됐습니다. 하지만 존재하는 모든 종류의 문제와 개발 환경들을 다루기에는 XP로는 불충분할 수밖에 없습니다.
UML에서와 마찬가지로 저는 뭔가 잘 합치는 사람이고, 제 강점 중 하나는 외면상 분리된 것처럼 보이는 것에서 공통분모를 찾아내고 그것들을 합치는 것이죠. 그래서 애자일 메쏘드와 RUP에 대해서도 마찬가지이겠죠?
by 필라르 | 2004/03/30 15:04 | About Programming | 트랙백 | 덧글(2)
2004년 03월 30일
프로그래머가 알아야 할 기본 지식
프로그래머가 알아야 할 기본 지식

컴퓨터 세계에 빠져들면 언젠가는 컴퓨터나 운영체제, 새로운 프로그래밍 언어를 만들고 싶다는 욕심을 갖게 된다. 하지만 이른바 전체적이고 종합적인 '기본기'가 충실히 쌓여 있지 않다면 그 꿈은 꿈으로 그칠 수밖에 없다. 이 글은 전산학이라는 화두를 갖고, 아무리 강조해도 지나치지 않는 개발자가 알아야 할 '기본 지식'을 살펴보는 데 그 목적이 있다.

이승준 (마이크로소프트웨어 2001년 4월호) 2001/04/18

"컴퓨터를 전공하지 않은 사람인데, 컴퓨터를 잘할 수 있을까요?" 예전에 어떤 사람이 이런 질문을 해왔다. 이 질문으로 얘기를 시작해 보자(사실 필자도 컴퓨터를 학문으로 전공한 사람은 아니다).
모든 분야의 일이 마찬가지지만, 컴퓨터 관련 엔지니어링 분야만큼 이론과 실제의 차이가 항상 민감하게 교차되는 분야가 그리 흔하지는 않다. 우선 우리는 컴퓨터를 '과학'으로 볼 것인지, '공학'으로 볼 것인지를 결정해야 한다.
과학이란 무엇인가. 간단하게 과학은 '가설과 검증'이라고 정의할 수 있다. 과학은 가설을 세우고, 이를 검증해 이론을 만드는 것을 말한다. 그러나 공학은 좀 다르다. 공학은 실제로 유용한 구현물을 만들기 위한 방법을 만드는 것이다. 따라서 공학의 목적은 무언가 구체적인 '구현' 혹은 '공정'이 된다.

◆ 과학 : 가설과 검증 이론
◆ 공학 : 방법과 효율 구현

우리나라 전산학의 영문 명칭은 대부분 'Computer Science'로 표기된다. 하지만, 앞서 언급했듯이 컴퓨터 과학과 컴퓨터 공학은 조금 명확히 구분할 필요가 있다. 이 글을 읽는 독자의 대부분이 소프트웨어 개발 혹은 프로그래밍의 관점에서 컴퓨터를 바라보고 있을 것이다('공학'의 입장에서 컴퓨터를 바라보는 것이다). 이론을 만드는 게 목적이 아니라는 점을 명확히 하자.
필자는 이 글을 통해 전산학 이론에 대한 말하고자 하는 것이 아니다. 그보다 전산학에서는 무엇을 공부하는지 살펴보고, 전산학의 여러 분야 중에서 우리가 실제 소프트웨어를 개발하는 일에 구체적인 도움이 되는 부분에는 어떤 것이 있는지 '상식'선에서 짚어보고자 한다.
언제나 '기본'이 중요하다는 사실을 다시 돌이켜 보자. 이론에서 실질적인 도움을 얻을 수 있는 부분들, 이론 중에서 기본적으로 알아둬야 할 상식들, 잘못 이해되고 있는 부분들(이론과 실제의 차이)을 살펴보자.

@전산학의 기초 '빅 5'

컴퓨터를 접하고 이를 공부하기 시작하면 누구나 언젠가는 컴퓨터를 직접 만들거나, 운영체제를 만들어 본다거나 새로운 프로그래밍 언어를 만들겠다는 생각을 한 적이 있을 것이다. 전산학의 분야를 보면 실제로 이런 분야가 들어 있다. 전산학의 여러 분야 가운데 기본이 되는 다섯 분야를 꼽는다면 다음과 같다.

1. 컴퓨터 구조론
2. 운영체제
3. 자료구조와 알고리즘
4. 프로그래밍 언어론, 컴파일러
5. 데이터베이스론

이 다섯 개의 분야는 기초분야로 꼽히며, 실제로 거의 모든 전산학과에서 강의가 이뤄지고 있다. 이 밖에 소프트웨어 공학, 네트워크, 인공지능 등의 분야가 있으며, 학교에 따라 조금씩 다른 특성을 갖고 커리큘럼이 운영된다.
독자 여러분도 이미 알겠지만, 이 분야를 모두 공부해야 프로그래밍을 할 수 있는 것은 아니다. 다시 말해 '프로그래밍'하는 것과 이 분야를 공부하는 것은 전혀 별개의 문제일 수 있다. 프로그래밍은 누구나 할 수 있다.
실제 컴퓨터에 대한 이해가 전혀 없는 사람도 대략 4∼6개월 정도의 학습을 거치면 실전에서 애플리케이션을 개발할 정도의 능력이 배양된다. 하지만 여기서 모든 것이 해결되는 것은 아니다. 1년이나 2년이 지나면, '프로그램 짤 수 있다'는 정도의 내공(?)에 부족함을 느끼게 되는 것은 어쩌면 당연한 일인지도 모른다. 소프트웨어 개발에 따른 다양한 이슈를 소화하고, 실제 기술의 장단점을 논의하기 위해서는 조금은 다른 지식이 필요하다. 예컨대 개발된 애플리케이션의 수행 효율을 향상하기 위한 성능 튜닝, 이식, 프로그램 설치와 배포, 팀 개발을 이끌어 가는 프로젝트 관리 등의 프로그래밍 이외의 이슈를 만나면, '프로그램을 짤 수 있다'만으로는 해결되지 않는 구석이 많다는 사실을 깨닫게 된다. 즉, 기본기의 중요성을 절감하게 되는 것이다.
이 글의 목적은 전산학이라는 화두를 갖고, '기본기'라는 것을 살펴보기 위함이다. 이제부터 각 분야별로 살펴보자(이 글은 전산학의 전체를 얘기하는 것이 아니라, 전산학과 학부과정에서 배우는 내용과 교재에 한정한 얘기라는 점을 전제한다).

1.컴퓨터 구조론
강좌내용 : 컴퓨터 구조론은 글자 그대로 컴퓨터의 기본적인 하드웨어의 작동 원리와 구성에 대한 내용을 다루는 분야. 부울 대수(Boolean Algebra)와 논리 표현을 익히고, 이를 하드웨어로 어떻게 구현하는지 공부하고 집적회로(IC)의 동작원리를 배운다. CPU, 메모리, 입출력의 구성이나 주변 장치와의 통신방법 등도 포함된다.

소프트웨어를 하는 사람의 입장에서 컴퓨터 구조론은 '어셈블리어'를 익히고, 동작원리를 아는 데 의의가 있다. 컴퓨터 구조론은 컴퓨터를 만드는 데 필요한 내용을 공부하는 것이지만, 컴퓨터 구조론을 공부하는 것과 컴퓨터를 만드는 일에는 아주 큰 격차가 있다는 사실을 알아야 한다. 만일, 여러분이 컴퓨터를 만들고 싶다면 납땜질을 배우거나 원칩 마이크로 컴퓨터를 공부하는 것이 훨씬 빠를 것이다.

2.운영체제
강좌내용 : 컴퓨터와 운영체제의 구조, 가상 기억 장치, 멀티 태스킹, 프로세스 스케쥴링 등의 기본 개념 및 이들과 관련된 이슈를 공부한다.

대부분의 강좌에서 유닉스 운영체제의 구조와 작동원리를 실사례로 많이 사용한다. 유닉스는 C로 소스가 쓰여 있어 구체적으로 설명하기에 좋기 때문이다.
운영체제는 프로그램이 운영되는 환경을 제공하기 때문에 운영체제론은 소프트웨어를 개발하는 사람들에게 중요한 내용을 많이 담고 있다. 물론 메모리 관리, CPU 스케쥴링 알고리즘, 주변장치 관리 등에 대한 학습이 실제 코딩에 직접 사용되지 않더라도, 조금 규모가 있는 소프트웨어를 제작하는 경우 운영체제가 갖고 있는 여러 가지 정책에 대한 구현은 여러분이 소프트웨어 아키텍처를 설계하는 데 적지 않은 도움을 준다. 특히 '무슨 무슨 서버'라는 이름이 붙는 소프트웨어를 만든다면, 운영체제 전반에 대한 이해는 아주 필수적이다.

3.자료구조와 알고리즘
강좌내용 : 컴퓨터 프로그램 설계에 널리 사용되는 자료구조와 알고리즘, 알고리즘에 대한 복잡도를 분석하는 방법 등을 제공하며 각종 검색, 정렬 프로그래밍을 통해 실제로 구현해 보고 복잡도를 분석한다.

일반적인 애플리케이션에서 자료구조를 직접 설계하고 구현할 필요성은 점차 줄어들고 있다. 자료구조의 많은 내용이 클래스 라이브러리로 구축돼 이를 잘 활용하거나 데이터베이스에 자료를 저장하는 것이 일반화적인 현상으로 자리잡았기 때문이다. 비정형화된 자료는 복잡한 자료구조를 쓰는 것보다 XML로 저장하거나 전송하는 것이 상당히 보편화됐다.
예를 들어 C++ 프로그래머가 직접 자료구조를 만들지 않아도 되도록 CArray, CList, CMap 같은 세 개의 클래스는 각각 가변 길이 배열, 양방향 리스트, 해시를 구현하고 있다. 이 정도면 웬만한 비즈니스 애플리케이션을 작성하기에 충분하다. 마찬가지로 자바도 이런 기능을 가진 벡터나 해시 테이블 등을 클래스 라이브러리로 제공하고 있다. 더 고급 기능이 필요하면 직접 작성하는 것보다는 표준화한 자료구조와 알고리즘을 제공하는 C++의 STL을 이용해도 된다. 하지만, 자료구조나 알고리즘에 대한 이해 없이 이런 내용을 사용하는 것은 불가능하다.
자료구조는 적어도 양방향 리스트를 자신이 사용하는 언어로 직접 구현하는 수준까지 해봐야 한다. 대부분 프로그래머가 메모리 기반의 정렬/탐색 알고리즘은 기본으로 공부하지만, 실제는 파일 기반의 탐색과 정렬이 오히려 더 중요할 수 있다. 따라서 정렬의 경우 파일 기반의 병합 정렬 정도까지 마스터하는 것이 좋다.

4.프로그래밍 언어와 컴파일러
강좌내용 : 각종 언어의 특성을 서로 비교하며 프로그래밍 언어의 문법 및 데이터 타입 등을 다룬다. 논리 언어, 함수 언어, 그리고 객체 지향 언어의 특성 및 응용 분야 등이 여기에 해당한다. 컴파일러는 오토머터(Automata) 구성, 어휘 분석(lexical analysis) 등을 학습하고, 컴파일러 제작도구인 Lex나 Yacc를 이용해 간단한 언어를 만들어 본다.

컴파일러는 무척 복잡하고 까다로운 분야 중 하나다. HTML, XML과 같은 마크업 언어가 널리 사용되면서 컴파일러의 한 부분인 파서에 대한 관심이 높아졌으며, 이에 따라 공개된 파서도 많이 등장했다. 여러분의 애플리케이션에서 파서가 필요하고 이를 직접 구현해야 한다면 컴파일러 이론이 필요하겠지만, 흔하지 않은 일이다.

5.데이터베이스
강좌내용 : 주로 관계형 데이터베이스 구조와 동작 등에 대한 이슈를 공부하며, 정규화 방법과 데이터베이스 설계, 튜닝 등에 필요한 여러 가지 이론을 공부한다.

대부분의 애플리케이션에서 데이터베이스 사용은 필수적인 사항으로 SQL, ERD 작성, 정규화, 설계, 구축, 데이터베이스 애플리케이션 작성 등은 대부분의 개발자에게 요구되는 기술이 됐다. 특히 SQL에 대한 이해와 사용이 가장 중요하며, 데이터베이스 설계에 대한 이해가 필수적이다.

@중요하지 않은 것은 하나도 없다

전산학의 기초를 이루고 있는 다섯 분야 중 실제 프로그래밍이나 소프트웨어 개발에 가장 크게 도움이 되는 분야를 꼽으라면, 주저 없이 '운영체제론'을 꼽을 것이다. 만일, 여러분의 팀에서 시간적 여유가 좀 있고, BOOK GROUP(특정한 책을 함께 공부하는 한시적인 학습 조직)을 운영한다면 운영체제론에 대한 학습을 가장 추천하고 싶다.
특히 (여러분이 윈도우를 쓴다고 해도) 유닉스에 대한 학습은 아주 필수적인 코스 중 하나다(여기서 말하는 학습은 유닉스 명령어나 사용법을 말하는 것이 아니다). 윈도우 2000의 내부적인 구성이 이전 버전과 비교해 유닉스를 많이 닮았다는 점과 맥 OS X이 완전히 유닉스 기반이라는 점은 시사하는 바가 크다. 보안과 관련해 네트워킹을 공부하는 사람이라면 유닉스는 더욱 중요하다. TCP/IP 등 대부분의 인터넷 관련 프로토콜이나 기반기술이 유닉스를 기반으로 하고 있기 때문이다.
자바 VM(Java Virtual Machine, 이하 JVM)은 운영체제와 그 역사가 전혀 다르지만, 자바 애플리케이션 입장에서 보면 JVM도 하나의 운영체제다. 시스템 프로그래밍을 하는 프로그래머가 운영체제에 대한 전반적인 지식을 필요로 하는 것과 마찬가지로, 자바 프로그래머들은 자신이 사용하고 있는 JVM의 특성에 대해 학습할 필요가 있다. 자바를 깊이 있게 다루는 프로그래머는 거의 한결 같이 자바가 100% 플랫폼 독립적이지는 않다고 말한다(아마도 정도의 문제일 것이다). 자바 기술은 대부분 썬이 스펙을 제공하고, 이를 여러 회사들이 구현하고 있다. JVM만 봐도 그렇다. 썬, 마이크로소프트, IBM 등 유수의 업체들이 나름대로 구현한 JVM을 내놓고 있으며 안정성, API 구현상의 특이점, 확장 기능 제공면에서 차이를 보이고 있다. 가끔은 이런 차이가 특정 JVM을 선택하는 기준이 되기도 한다. 또한 JVM 자체가 운영체제 위에서 운영되는 애플리케이션이기 때문에 JVM의 구현 특성과 운영체제의 환경을 무시할 수 없다.
그 다음으로 중요한 분야를 꼽는다면 '데이터베이스', '자료구조와 알고리즘'이다. 객체지향 데이터베이스(Object-Oriented DBMS)가 주목을 받아 많은 연구가 수행되고 있지만, 관계형 데이터베이스(Relational DBMS)를 완전히 대체하지는 못하고 있다(현재는 RDB에 ODB의 특성을 가미한 ORDB가 사실상의 표준이다). 이제 데이터베이스 프로그래밍은 더 이상 특수한 분야가 아니다. 대부분의 애플리케이션이 인터넷을 기반으로 하고 있고, 기본적으로 데이터베이스를 사용하고 있기 때문이다.

<표 1>은 이 다섯 분야의 교재로, 가장 널리 사용되는 책을 나열한 것이다(분야별로 다른 좋은 책이 많이 있으나 개인적 체험에 입각해 한 개씩 선정한 것이다). 이 책들은 모두 번역서도 있다.

<표 1> 분야별 대표적인 교재
컴퓨터 구조론 Computer System Architecture 2/e, M. Morris Mano, Prentice-Hall, 1982
운영체제론 Operating System Concepts 4/e, Avi Silberschatz, Peter Galvin, Addision Wesley Longman, Inc., 1998.
자료구조와 알고리즘 Fundamentals of DATA STRUCTURES in C++, Horowitz & Sahni, Computer Sci. Press, 1995.
컴파일러 Compilers: Principles, Techniques, and Tools, Alfred Aho, Ravi Sethi,Jeffrey Ullman, Addison-Wesley, 1986.
데이터베이스론 An introduction to Database Systems 6/e, C.J.Date, Addison-Wesley, 1995.
by 필라르 | 2004/03/30 14:57 | About Programming | 트랙백(5) | 덧글(0)
2004년 03월 30일
프로그래머가 알아야 할 기본 지식
@그 밖의 분야들

앞서 말한 분야 외에 소프트웨어 공학, 네트워크, 인공지능 같은 분야도 이에 못지 않게 기반이 되는 분야이다.
소프트웨어 공학은 분석 설계 구현을 큰 축으로 하는 소프트웨어 개발의 생명 주기를 바탕으로 개발시 여러 단계와 각 단계에서 발생하는 이슈를 주로 다룬다. 요즘은 객체지향 방법론과 분석/설계에 대한 내용이 많이 보강되고 있다. 네트워크는 주로 네트워킹의 기본 이론이 되는 OSI 7 계층에 대한 내용과 프로토콜 관련 이슈가 주류를 이룬다. 인공지능에선 문제 해결, 자연어 처리, 지식 처리, 추론 머신, 로보틱스, 에이전트 등의 연구가 진행되고 있다.
이 세 가지의 분야에 대한 지식은 간접적으로 소프트웨어 개발에 많은 '꺼리'를 던져준다. 실무에서 일하는 개발자들은 이들 분야에 대해선 지나치게 원론적인 이론서보다는 한 단계 쉽고 구체적인 안내서를 읽는 것이 훨씬 좋다.

@프로세스의 메모리 구조
프로세스에 대한 이해는 프로그래밍의 핵심이라고 할 수 있다. 프로세스는 간단하게 '수행중인 프로그램'이라고 정의할 수 있다(참고로 프로그램은 수행 가능한 디스크상의 이미지라고 정의할 수 있다). 다시 말해, 프로세스는 디스크에 저장돼 있던 실행 가능한 프로그램이 메모리에 적재돼 운영체제의 제어를 받는 상태를 말한다.
프로그램을 작성해 컴파일하고 링크하면 실행 가능한 파일이 생성된다(윈도우라면 *.exe라는 파일이, 유닉스라면 기본적으로 a.out이라는 파일이 생성된다). 쉘을 통해 사용자가 프로그램을 수행시키면, 커널은 이 프로그램을 제어에 적합한 자료구조로 만들어 메모리로 읽어낸 후, 커널의 프로세스 테이블에 등록하고, 메모리, 파일, 입출력 장치 같은 자원을 할당하는데, 이때부터 프로그램은 커널의 한 프로세스로서 실행 상태가 된다.
프로세스는 Win32의 경우에 CreateProcess(), 유닉스의 경우에는 fork() 시스템 콜을 사용해 새로운 프로세스를 생성하고, 프로세스간에는 다양한 IPC(Inter-Process Communication) 방법을 통해 데이터를 교환하거나 프로세스간의 동기화를 수행한다.

<그림 1>은 프로그램이 메모리에 적재된 모습을 나타낸다. 이 구조는 유닉스와 윈도우가 크게 다르지 않다 (JVM에서 돌아가는 자바 프로그램도 비슷한 구조를 갖는다). 그림에서 위쪽이 낮은 주소번지가 된다. 그림에서 보이는 네 개의 범위(텍스트, 데이터, 힙, 스택)를 각각 세그먼트라고 한다.

각 세그먼트에 대해 좀더 자세하게 알아보자(여기서는 유닉스와 C를 기준으로 서술하지만, 윈도우에서도 공통적인 특성을 갖는다).

◆ 텍스트 : 프로그램의 실행 코드인 기계어 코드와 읽기 전용 데이터 등을 가진다(CPU가 읽어들여 수행한다고 해서 텍스트라고 부르며, 코드 영역이라고도 한다).
◆ 데이터 : C언어에서 전역 변수, 정적 변수 등으로 선언된 변수 영역(읽기/쓰기 가능)
◆ 힙 : 프로그램 수행 중 malloc(), free() 등의 시스템 콜로 할당되고, 해지되는 메모리 영역
◆ 스택 : C언어의 함수 호출시 지역 변수와 인수, 함수의 수행이 끝났을 때 리턴할 주소(return address)를 푸시한다(함수가 끝나면 이 값을 팝하고 리턴하게 된다).

운영체제는 프로그램의 텍스트 부분에 메모리를 읽기 전용으로만 사용하고, 프로세스간에는 메모리 영역을 침범하지 못하도록 한다. 따라서, 프로그램의 텍스트로 되어 있는 메모리 영역을 침범해 기록하면 버스 에러나 세그먼트 결함이 일어나서 프로그램이 종료된다. 여러분은 윈도우에서 '잘못된 연산을 수행해 프로그램을 종료합니다'란 메시지를 본적이 있을 것이다. 이 에러(잘못된 연산)의 95% 이상이 바로 앞서 이런 연유에서 발생한다.
C/C++와 같이 포인터(주소를 갖는 변수)를 사용해 메모리를 직접 액세스하는 언어로 개발할 때도 흔히 이와 같은 에러가 발생한다. 따라서 프로그램을 개발할 때 가장 중요한 점이 바로 메모리 관리다. 프로그램 오류의 80% 이상을 차지하는 이유를 살펴보면 다음과 같다.

◆ 초기화
◆ 해지

자바는 가비지 컬렉션을 통해 사용하지 않는 메모리를 자동으로 해지하지만, 필요에 따라 명시해 주는 것이 좋다. C/C++에서는 쓰지 않는 메모리에 대해 반드시 명시적으로 delete를 써줘야 한다. C/C++는 할당된 메모리에 대한 포인터를 잃어버리는 경우가 생기는데, 이를 메모리 누수라고 한다. 메모리 누수는 프로그래머를 괴롭히는 가장 큰 골칫거리 중 하나다. 꼼꼼히 확인하는 습관을 들이는 것이 좋다.

@멀티로 시작하는 단어의 사용
멀티 프로그래밍, 멀티 프로세싱, 멀티 태스킹, 멀티 쓰레드, 멀티 유저는 비슷비슷한 용어이기 때문에 혼돈해 사용하지만 의미가 모두 다르다.

◆ 멀티 프로그래밍 : 여러 프로그램이 메모리에 적재돼 수행되는 것. 하나의 프로그램이 수행되다가 입출력을 하면 CPU는 다른 프로그램으로 제어권을 넘긴다. 즉, 프로그램의 입출력을 기준으로 프로그램 수행의 스위칭이 일어난다(요즘은 좀처럼 쓰이지 않는 말이다).
◆ 멀티 프로세싱 : 다수의 프로세서가 작업을 처리하는 것. 운영체제가 멀티 프로세싱을 지원한다는 것은 다수의 CPU를 지원할 수 있다는 뜻이다. 여러 CPU가 운영체제와 메모리를 공유해 프로그램을 수행하는 방식을 SMP(대칭형 멀티 프로세싱)라고 한다(윈도우 NT가 이런 방식이다).
◆ 멀티 태스킹(시분할 시스템) : 태스크(Task, 운영체제가 수행하는 기본 단위)가 여럿인 것. 운영체제가 강제로 CPU 시간을 프로세스에 할당한다.
◆ 멀티 유저 : 멀티 유저는 기본적으로 멀티 태스킹이 되는 시스템에 다중 사용자 파일 시스템 등 다중 사용자를 지원하기 위한 기능을 추가한 것이다.
◆ 멀티 쓰레드 : 하나의 프로세스 내에 여러 개의 수행경로가 존재하고, 이를 동시에 수행하는 것. 하나의 프로세스가 동시에 두 가지 이상의 작업을 수행하는데 활용된다(쉽게 말해 프로세스 내에서 멀티 태스킹을 하는 것이라고 볼 수 있다).

여기서 멀티 쓰레드에 대해 좀더 구체적으로 알아보자. 쓰레드는 '수행 경로'라고 정의할 수 있다. CPU가 텍스트(코드)를 읽어 수행할 때 수행되는 절차를 하나의 수행 경로라고 한다. 멀티 쓰레드란 결국 이런 수행 경로가 여러 개 있다는 뜻이다. 멀티 쓰레드도 멀티 태스킹과 마찬가지로 기본적으로 여러 쓰레드를 번갈아 수행한다. 텍스트, 데이터, 힙, 스택의 각 세그먼트에 대한 주소를 CPU 레지스터에 담고 있는데, 이 레지스터의 내용을 바꿔(컨텍스트 스위칭) 다른 쓰레드를 수행하도록 한다. 쓰레드 간에 프로세스가 갖고 있는 메모리와 코드 영역을 공유하므로, 컨텍스트 스위칭할 때 레지스터의 내용을 조금만 바꿔도 멀티 태스킹에 비해 컨텍스트 스위칭 하는 속도가 빠르다.
멀티 태스킹이나 멀티 쓰레드는 두 개 이상의 작업이 동시에 수행되므로, 동시에 수행되는 작업에 대해 동기화가 필연적으로 필요하다.
자바는 언어 차원에서 동기화를 지원한다. synchronized 키워드를 이용해 손쉽게 동기화를 구현할 수 있지만, 꼭 필요할 때만 사용하는 것이 좋다. synchronized를 사용한 것이 사용하지 않은 코드에 비해 약 3∼4배정도 느려지기 때문이다. 대부분의 유닉스와 윈도우는 운영체제 차원에서 Event, Critical Section, Mutex, Semaphore 등의 동기화 메커니즘을 제공한다.

@객체지향 방법론과 UML

요즘 소프트웨어 전반에 '객체지향'이란 말이 붙지 않은 분야가 없다. 객체지향 데이터베이스, 객체지향 프로그래밍 언어뿐만 아니라 소프트웨어 공학에도 객체지향 분석/설계, 방법론이 널리 사용되고 있다. 이제 UML(Unified Modeling Language)은 정착 단계에 들어섰다. 어느 글을 보든지, 표기법은 기본적으로 모두 UML을 사용하고 있다. 하지만 많은 사람들이 UML을 오해하고 있는데, 그 중 가장 대표적인 두 가지만 살펴보겠다.

1. UML은 객체지향 방법론이다.
2. UML은 프로젝트를 진행하는 데 생기는 많은 기술적인 문제를 푸는 데 도움이 된다.

UML은 방법론(methodology)이 아니다. UML은 표기법(notation)이다. 많은 사람들이 UML을 일종의 방법론처럼 생각하고 있는데, UML은 객체지향 분석/설계의 결과를 표시하는 표준적인 표기법을 제공할 뿐이지 UML 자체가 무엇인가를 해주는 것은 아니다. 방법론이라고 얘기하려면 표기법과 함께 공정을 갖고 있어야 한다.

방법론 = 표기법 + 공정

하지만 UML은 공정을 포함하고 있지 않다. 따라서 RUP(Rational Unified Process)를 쓰거나 자체의 고유한 공정을 써도 좋다는 얘기가 된다. 또 한 가지 사실은 UML을 쓰더라도 여전히 기술적인 문제들은 그대로 남아 있다는 점이다. 기술적인 문제는 어떤 방법론을 쓰건 방법론과는 별개로 풀어야 할 과제로 남게 된다.
그렇다면 왜 UML을 사용하는가. 그 답은 '남들이 모두 쓰니까'다. 우스개 소리 같지만 사실이자 곧 현실이다. 좀더 고상하게 말해 표준이기 때문이다. UML은 개발자간 혹은 개발자와 고객간의 의사소통에 있어 표준적인 형태를 제공한다는 데 가장 큰 의의가 있다. 사실 시스템을 분석/설계하는 것은 표기법이나 공정보다 '경험'이 훨씬 중요하다. 필자는 '경험'을 앞서는 것은 아무 것도 없다고 본다.

<그림 2> UML의 클래스 다이어그램

많은 사람이 재사용을 부르짖고 객체지향의 가장 큰 장점을 재사용에서 찾고 있지만, 실제 여러분의 프로젝트에서 얼마나 많은 코드가 재사용되고 있는지 돌이켜 보라.
재사용이 가장 잘 적용되는 분야가 바로 컴포넌트 기반의 개발(CBD; Component Based Development)이다. 그렇지만 실제 프로젝트에서 컴포넌트를 만들고 조립하는 역할과 배분이 그리 쉽게 이뤄지지는 않는다. 결국 객체지향론이나 재사용, CBD 등은 프로젝트를 진행하는 데 좀더 도움이 되도록 하는 독려의 대상이지 그 자체가 목적이 될 수는 없다. 소프트웨어 분야에서는 아무리 좋은 개념에 아무리 좋은 제품이라도 실제 활용되지 않으면 아무 소용이 없다.

@컴퓨터와 수학

컴퓨터의 구조 자체가 수학이라는 것을 아는 사람은 생각보다 그리 많지 않은 것 같다. 사실 컴퓨터의 아키텍처는 부울 대수이고, 관계형 데이터베이스는 수학의 집합론을 그대로 옮겨 놓은 것이다. 관계형 데이터베이스가 계층형 데이터베이스나 네트워크 데이터베이스를 제치고 70년대부터 지금까지 널리 쓰이는 까닭은 수학적 이론을 바탕으로 했기 때문에 가능했다는 말도 있다. 물론 수학에 대한 이해와 지식이 있는 경우 프로그래밍을 하는 데 많은 도움을 받는 것은 사실이지만 절대 필수적인 것은 아니다. 어쩌면 중학교 3학년 정도의 수학이면 충분하다고 볼 수도 있다. 고등학교 이상의 수학 실력이 필요한 분야는 컴퓨터 그래픽스다(컴퓨터 그래픽스를 프로그래밍으로 접근하는 경우). 만일 보다 심도 깊은 연구가 필요하다면, 이산 수학(Discrete Mathematics)이라는 수학분야를 공부할 것을 권한다. 이산 수학은 전산학의 기초 이론을 수학적인 입장에서 다룬다. 수학이라는 학문에서 가장 중요하다는 무한(Infinity)와 연속(Continuity)을 뺀 수학이라고 보면 틀리지 않는다.

@미래를 좌우하는 것

인터넷의 확산은 엔터프라이즈 애플리케이션과 데스크톱 애플리케이션의 경계를 허물었고, 소프트웨어 산업전체를 뒤집어 놓았다. 대부분의 애플리케이션 개발은 웹 기반으로 전환됐으며, 인터넷을 빼놓고선 소프트웨어를 말하기가 힘들어졌다.
그 다음은 무엇인가. 그것은 바로 '모바일'일 것이라는 점에 많은 사람이 공감을 표시하고 있다. 모바일 시장의 활성화에 따라 특수 목적의 운영체제나 하드웨어가 각광받을 것이고 더욱 더 많은 기술이 발표될 것이다. 현재도 기술은 약어집이 필요할 정도로 쏟아져 나오고 있다. 따라서 점차 코딩은 기술과 기술을 묶어내는 도구로 사용되고 있다.
많은 플랫폼과 언어가 흥망성쇠를 거듭해 가면서 발전하고 있지만, 기본과 기반기술은 크게 변하지 않았다. 하드웨어 구조 자체가 '폰 노이만 구조(stored program)'를 벗어나지 않고 있고, 소프트웨어의 모든 기술이 이전 기술을 바탕에 두고 시작하기 때문이다. UML을 예로 들어보자. UML은 사실 전혀 새로운 것이 아니다. 이전의 여러 기술과 개념을 종합하고 표준화했을 뿐이다. C#도 C++, 스몰토크, 자바와 같은 조상 언어와 COM/DCOM에 기반해 만들어졌다.
필자는 개인적으로 향후 대중적인 프로그래밍 언어의 대표 주자는 자바와 C#이 될 것으로 점치고 있다. C#은 클래스 라이브러리 전체가 COM 객체로 구성돼 있고, 자바는 EJB를 통해 CBD를 지원하고 있다. JVM과 .NET 플랫폼을 보면 재사용 가능한 컴포넌트가 플랫폼에 흡수되는 것을 볼 수 있다.
이런 얘기가 사뭇 다르게 들릴지 몰라도, 조금만 깊게 살펴보면 실은 비슷한 개념의 기반기술을 배경으로 하고 있다는 것을 알 수 있다. 웹뿐만 아니라 다른 서비스에도 XML과 SOAP는 더욱 더 많이 쓰이게 될 것이다(XML과 SOAP는 여러 가지 기능을 묶어내고 연결하는 기본적인 방법이 될 것이다). 이제 개발자들에게는 네트워크를 기반으로 다양한 지식을 자신이 선호하는 언어로 요리해 엮어내고 연결할 수 있는 자질이 요구되고 있다. @

참고 문헌
* Operating System Concepts 3/e, A. Silberschatz, J. Peterson, P. Galvin, Addison-Wesley, 1992
* Digital Logic and Computer Design, M. Morris Mano, Prentice-Hall, 1979
* Computer System Architecture 2/e, M. Morris Mano, Prentice-Hall, 1982
* Computer Organization and Architecture: Principles of Structure and Function, William Stallings, Macmillan Publishing Company, 1987
* Discrete Mathematics with Computer Science Applications, Skvarcius, Robinson, The Benjamin/Cummings Publishing Company, 1986
* Fundamentals of Data Structures in C++, Ellis Horowitz, Sartaj Sahni and Dinesh Mehta, Computer Science Press, 1995
* Introduction to Algorithms: A Creative Approach, Udi Manber, Addison-Wesley Publishing Company, 1989
* Object Lifecycles, Sally Shlaer, Stephen J. Mellor, Prentice-Hall, New Jersey, 1992
* Object-Oriented Modeling and Design, J. Rumbaugh, M. Blaha, W. Premerlani, F. Eddy, W. Lorensen, Prentice-Hall, 1991
by 필라르 | 2004/03/30 14:56 | About Programming | 트랙백 | 덧글(0)
2004년 03월 26일
*어떻게 공부할까? 프로그래머를 위한「공부론」Part I
우리 프로그래머들은 항상 공부해야 합니다. 우리는 지식을 중요하게 여깁니다. 하지만 지식에 대한 지식, 즉 내가 그 지식을 얻은 과정이나 방법 같은 것은 소홀히 여기기 쉽습니다. 따라서 지식의 축적과 공유는 있어도 방법론의 축적과 공유는 매우 드문 편입니다. 저는 평소에 이런 생각에서 학교 후배들을 위해 제 자신의 공부 경험을 짬짬이 글로 옮겨놓았고, 이번 기회에 그 글들을 취합, 정리하게 되었습니다. 그 결실이 바로 이 글입니다.

김창준 (마이크로소프트웨어)  2002/06/02

이 글은 공부하는 방법과 과정에 관한 글입니다. 이 글은 제가 공부한 성공/실패 경험을 기본 토대로 했고, 지난 몇 년간 주변에서 저보다 먼저 공부한 사람들의 경험을 관찰, 분석한 것에 제가 다시 직접 실험한 것과 그밖에 오랫동안 꾸준히 모아온 자료들을 더했습니다. '만약 다시 공부한다면' 저는 이렇게 공부할 것입니다.부디 독자 제현께서 이 글을 씨앗으로 삼아 자신만의 나무를 키우고 거기서 열매를 얻고, 또 그 열매의 씨앗이 다시 누군가에게 전해질 수 있다면 더 이상 바랄 것이 없겠습니다.
이 글은 특정 주제들의 학습/교수법에 대한 문제점과 제가 경험한 좋은 공부법을 소개하는 식으로 구성됐습니다. 여기에 선택된 과목은 리팩토링, 알고리즘?자료구조, 디자인패턴, 익스트림 프로그래밍(ExtremeProgramming 혹은 XP) 네 가지입니다. 이 네 가지가 선택된 이유는 필자가 관심있게 공부했던 것이기 때문만은 아니고, 모든 프로그래머에게 어떻게든 널리 도움이 될만한 교양과목이라 생각하여 선택한 것입니다. 그런데 이 네 가지의 순서가 겉보기와는 달리 어떤 단계적 발전을 함의하는 것은 아닙니다. 수신(修身)이 끝나면 더 이상 수신은 하지 않고 제가(齊家)를 한다는 것이 어불성설인 것과 같습니다.
원래는 글 후미에 일반론으로서의 공부 패턴들을 쓰려고 했습니다. 하지만 지면의 제약도 있고, 독자 스스로 이글에서 그런 패턴을 추출하는 것도 의미가 있을 것이기에 생략했습니다. 그런 일반론이 여기 저기 숨어있기 때문에 알고리즘 공부에 나온 방법 대부분이 리팩토링 공부에도 적용할 수 있고, 적용되어야 한다는 점을 꼭 기억해 주셨으면 합니다. 다음에 기회가 닿는다면 제가 평소 사용하는 (컴퓨터) 공부패턴들을 소개하겠습니다.

@알고리즘?자료구조 학습에서의 문제

우리는 알고리즘 카탈로그를 배웁니다. 이미 그러한 해법이 존재하고, 그것이 최고이며, 따라서 그것을 달달 외우고 이해해야 합니다. 좀 똑똑한 친구들은 종종 "이야 이거 정말 기가 막힌 해법이군!"하고 감탄할지도 모릅니다. 대부분의 나머지 학생들은 그 해법을 이해하려고 머리를 쥐어짜고 한참을 씨름한 후에야 어렴풋이 왜 이 해법이 그 문제를 해결하는지 납득하게 됩니다. 그리고는 그 '증명'은 책 속에 덮어두고 까맣게 사라져버립니다. 앞으로는 그냥 '사용'하면 되는 것입니다. 더 많은 대다수의 학생은 이 과정이 무의미하다는 것을 알기 때문에 왜 이 해법이 이 문제를 문제없이 해결하는지의 증명은 간단히 건너뜁니다.
이런 학생들은 이미 주어진 알고리즘을 사용하는 일종의 객관식 혹은 문제 출제자가 존재하는 시험장 상황에서는 뛰어난 성적을 보일 것임은 자명합니다. 하지만 스스로가 문제와 해답을 모두 만들어내야 하는 상황이라면, 또는 해답이 존재하지 않을 가능성이 있는 상황이라면, 혹은 최적해를 구하는 것이 불가능에 가깝다면, 혹은 알고리즘을 완전히 새로 고안해내야 하거나 기존 알고리즘을 변형해야 하는 상황이라면 어떨까요?
교육은 물고기를 잡는 방법을 가르쳐야 합니다. 어떤 알고리즘을 배운다면 그 알고리즘을 고안해낸 사람이 어떤사고 과정을 거쳐 그 해법에 도달했는지를 구경할 수 있어야 하고, 학생은 각자 스스로만의 해법을 차근차근 '구성'(construct)할 수 있어야 합니다(이를 교육철학에서 구성주의라고 합니다. 교육철학자 삐아제(Jean Piaget)의 제자이자, 마빈 민스키와 함께 MIT 미디어랩의 선구자인 세이머 페퍼트 박사가 주창했습니다). 전문가가 하는 것을 배우지 말고, 그들이 어떻게 전문가가 되었는지를 배우고 흉내 내야 합니다.
결국은 소크라테스적인 대화법입니다. 해답을 가르쳐 주지 않으면서도 초등학교 학생이 자신이 가진 지식만으로 스스로 퀵소트를 유도할 수 있도록 옆에서 도와줄 수 있습니까? 이것이 우리 스스로와 교사들에게 물어야 할질문입니다. 왜 우리는 학교에서 '프로그래밍을 하는 과정'이나 '디자인 과정'(소프트웨어 공학에서 말하는 개발 프로세스가 아니라 몇 시간이나 몇 십 분 단위의, 개인적인 차원의 사고 과정 등을 일컫습니다)을 명시적으로 배운 적이 없을까요? 왜 해답에 이르는 과정을 가르쳐주는 사람이 없나요? 우리가 보는 것은 모조리 이미 훌륭히 완성된, 종적 상태의 결과물로서의 프로그램뿐입니다. 어느 날 문득 하늘에서 완성된 프로그램이 뚝 떨어지는 경우는 없는데 말입니다.
교수가 어떤 알고리즘 문제의 해답을 가르칠 때, "교수님, 교수님께서는 어떤 사고 과정을 거쳐, 그리고 어떤 디자인 과정과 프로그래밍 과정을 거쳐서 그 프로그램을 만드셨습니까?"하고 물어봅시다. 만약 여기에 어떤 체계적인 답변도 할 수 없는 분이라면 그 분은 자신의 사고에 대해 '사고'해 본 적이 없거나 문제 해결에 어떤 효율적체계를 갖추지 못한 분이며, 따라서 아직 남을 가르칠 준비가 되어있지 않은 분일 것입니다. 만약 정말 그렇다면 우리는 어떻게 해야 할까요?
by 필라르 | 2004/03/26 20:31 | About Programming | 트랙백 | 덧글(0)
2004년 03월 26일
*어떻게 공부할까? 프로그래머를 위한「공부론」Part II
@자료구조와 알고리즘 공부

제가 생각건대, 교육적인 목적에서는 자료구조나 알고리즘을 처음 공부할 때 우선은 특정 언어로 구현된 것을 보지 않는 것이 좋을 때가 많습니다. 대신 말로 된 설명이나 의사코드(pseudo-code) 등으로 그 개념까지만 이해하는 것이죠. 그 아이디어를 절차형(C, 어셈블리어)이나 함수형(LISP, Scheme, Haskell), 객체지향(자바, 스몰토크) 언어 등으로 직접 구현해 보는 겁니다. 그 다음에는 다른 사람이나 다른 책의 코드와 비교합니다. 이 경험을 애초에 박탈당한 사람은 귀중한 배움과 깨달음의 기회를 잃은 셈입니다.
만약 여러 사람이 함께 공부한다면 각자 동일한 아이디어를 같은 언어로 혹은 다른 언어로 어떻게 다르게 표현했는지를 서로 비교해 보면 배우는 것이 무척 많습니다. 우리가 자료구조나 알고리즘을 공부하는 이유는, 특정 '실세계의 문제'를 어떠한 '수학적 아이디어'로 매핑시켜 해결할 수 있는지, 그것이 효율적인지, 또 이를 컴퓨터에 어떻게 효율적으로 구현할 수 있는지 따지고, 그것을 실제로 구현하기 위해서입니다. 따라서 이 과정에 있어 실세계의 문제를 수학 문제로, 그리고 수학적 개념을 프로그래밍 언어로 효율적으로 표현해내는 것은 아주 중요한 능력이 됩니다.

@알고리즘 공부에서 중요한 것

개별 알고리즘의 목록을 이해, 암기하며 익히는 것도 중요하지만 더 중요한 것은 다음 네 가지입니다.
①알고리즘을 스스로 생각해낼 수 있는 능력
②다른 알고리즘과 효율을 비교할 수 있는 능력
③알고리즘을 컴퓨터와 다른 사람이 이해할 수 있는 언어로 표현해낼 수 있는 능력
④이것의 정상작동(correctness) 여부를 검증해 내는 능력
첫 번째가 제대로 훈련되지 못한 사람은 알고리즘 목록의 스테레오 타입에만 길들여져 있어서 모든 문제를 자신이 아는 알고리즘 목록에 끼워 맞추려고 합니다. 디자인패턴을 잘못 공부한 사람과 비슷합니다. 이런 사람들은 마치 과거에 수학 정석만 수십 번 공부해 문제를 하나 던져주기만 하면, 생각해보지도 않고 자신이 풀었던 문제들의 패턴 중 가장 비슷한 것 하나를 기계적?무의식적으로 풀어제끼는 문제풀이기계와 비슷합니다. 그들에게 도중에 물어보십시오. "너 지금 무슨 문제 풀고 있는 거니?" 열심히 연습장에 뭔가 풀어나가고는 있지만 그들은 자신이 뭘 풀고 있는지도 제대로 인식하지 못 하는 경우가 많습니다. 머리가 푸는 게 아니고 손이 푸는 것이죠. 이렇게 되면 도구에 종속되는 '망치의 오류'에 빠지기 쉽습니다. 새로운 알고리즘을 고안해야 하는 상황에서도 기존 알고리즘에 계속 매달릴 뿐입니다. 알고리즘을 새로 고안해 내건 혹은 기존의 것을 조합하건 스스로 생각해 내는 훈련이 필요합니다.
두 번째가 제대로 훈련되지 못한 사람은 일일이 구현해 보고 실험해 봐야만 알고리즘 간의 효율을 비교할 수 있습니다. 특히 자신이 가진 카탈로그를 벗어난 알고리즘을 만나면 이 문제가 생깁니다. 이건 상당한 대가를 치르게 합니다.
세 번째가 제대로 훈련되지 못한 사람은, 문제를 보면 "아, 이건 이렇게 저렇게 해결하면 됩니다"하는 말은 곧잘할 수 있지만 막상 컴퓨터 앞에 앉혀 놓으면 아무 것도 하지 못합니다. 심지어 자신이 생각해낸 그 구체적 알고리즘을 남에게 설명해 줄 수는 있지만, 그걸 '컴퓨터에게' 설명하는 데는 실패합니다. 뭔가 생각해낼 수 있다는 것과 그걸 컴퓨터가 이해할 수 있게 설명할 수 있다는 것은 다른 차원의 능력을 필요로 합니다.
네 번째가 제대로 훈련되지 못한 사람은, 알고리즘을 특정 언어로 구현해도, 그것이 옳다는 확신을 할 수 없습니다. 임시변통(ad hoc)의 아슬아슬한 코드가 되거나 이것저것 덧붙인 누더기 코드가 되기 쉽습니다. 이걸 피하려면 두 가지 훈련이 필요합니다. 하나는 수학적?논리학적 증명의 훈련이고, 다른 하나는 테스트 훈련입니다. 전자가 이론적이라면 후자는 실용적인 면이 강합니다. 양자는 상보적인 관계입니다. 특수한 경우들을 개별적으로 테스트해서는 검증해야 할 것이 너무 많고, 또 모든 경우에 대해 확신할 수 없습니다. 테스트가 버그의 부재를 보장할 수는 없습니다. 하지만 수학적 증명을 통하면 그것이 가능합니다. 또, 어떤 경우에는 수학적 증명을 굳이 할 필요 없이 단순히 테스트 케이스 몇 개만으로도 충분히 안정성이 보장되는 경우가 있습니다. 이럴 때는 그냥 테스트만으로 만족할 수 있습니다.

@실질적이고 구체적인 문제를 함께 다루라

자료구조와 알고리즘 공부를 할 때에는 가능하면 실질적이고 구체적인 실세계의 문제를 함께 다루는 것이 큰 도움이 됩니다. 모든 학습에 있어 이는 똑같이 적용됩니다. 인류의 지성사를 봐도, 구상(concrete) 다음에 추상(abstract)이 옵니다. 인간 개체 하나의 성장을 봐도 그러합니다. 'be-동사 더하기 to-부정사'가 예정으로 해석될 수 있다는 룰만 외우는 것보다 다양한 예문을 실제 문맥 속에서 여러 번 보는 것이 훨씬 나을 것은 자명합니다. 알고리즘과 자료구조를 공부할 때 여러 친구들과 함께 연습문제(특히 우리가 경험하는 실세계의 대상들과관련이 있는 것)를 풀어보기도 하고, ACM의 ICPC(International Collegiate Programming Contest: 세계 대학
생 프로그래밍 경진 대회) 등의 프로그래밍 경진 대회 문제 중 해당 알고리즘?자료구조가 사용될 수 있는 문제를 같이 풀어보는 것도 아주 좋습니다. 이게 가능하려면 "이 알고리즘이 쓰이는 문제는 이거다"하고 가이드를 해줄 사람이 있으면 좋겠죠. 이것은 그 구체적 알고리즘?자료구조를 훈련하는 것이고, 이와 동시에 어떤 알고리즘을 써야할지 선택, 조합하는 것과 새로운 알고리즘을 만들어내는 훈련도 무척 중요합니다.

@알고리즘 디자인 과정의 중요성

알고리즘을 좀더 수월하게, 또 잘 만들려면 알고리즘 디자인 과정에 대해 생각해 봐야 합니다. 그냥 밑도 끝도없이 문제를 쳐다본다고 해서 알고리즘이 튀어나오진 않습니다. 체계적이고 효율적인 접근법을 사용해야 합니다. 대표적인 것으로 다익스트라(E. W. Dijkstra)와 워스(N. Wirth)의 '조금씩 개선하기'(Stepwise Refinement)가 있습니다. 워스의 「Program Development by Stepwise Refinement」(1971, CACM 14.4,http://www.acm.org/classics/dec95)를 꼭 읽어보길 바랍니다. 여기 소개된 조금씩 개선하기는 구조적 프로그래밍에서 핵심적 역할을 했습니다(구조적 프로그래밍을 'goto 문 제거' 정도로 생각하면 안 됩니다). 다익스트라의 「Stepwise Program Construction」(Selected Writings on Computing: A Personal Perspective, Springer-Verlag, 1982, http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD227.PDF)도 추천합니다.
알고리즘 검증은 알고리즘 디자인과 함께 갑니다. 새로운 알고리즘을 고안할 때 검증해 가면서 디자인하기 때문입니다. 물론 가장 큰 역할은 고안이 끝났을 때의 검증입니다. 알고리즘 검증에는 루프 불변식(loop invariant)같은 것이 아주 유용합니다. 아주 막강한 무기입니다. 익혀 두면 두고두고 가치를 발휘할 것입니다. 맨버(UdiManber)의 알고리즘 서적(『Introduction to Algorithms: A Creative Approach』)이 알고리즘 검증과 디자인이 함께 진행해 가는 예로 자주 추천됩니다. 많은 계발을 얻을 것입니다. 고전으로는 다익스트라의 『A Discipline of Programming』과 그라이스(Gries)의 『The Science of Programming』이 있습니다. 특히 전자를 추천합니다. 프로그래밍에 대한 관을 뒤흔들어 놓을 것입니다.

@알고리즘과 패러다임

알고리즘을 공부하면 큰 줄기들을 알아야 합니다. 개별 테크닉도 중요하지만 '패러다임'이라고 할만한 것들을 알아야 합니다. 이것에 대해서는 튜링상을 수상한 로버트 플로이드(Robert Floyd)의 튜링상 수상 강연(The Paradigms of Programming, 1978)을 추천합니다. 패러다임을 알아야 알고리즘을 상황에 맞게 마음대로 변통할 수 있습니다. 그리고 자신만의 분류법을 만들어야 합니다. 구체적인 문제들을 케이스 바이 케이스로 여럿 접하는 동안 그냥 지나쳐 버리면 개별자는 영원히 개별자로 남을 뿐입니다. 비슷한 문제들을 서로 묶어서 일반화해야 합니다.
이런 패러다임을 발견하려면 '다시 하기'가 아주 좋습니다. 다른 것들과 마찬가지로, 이 다시 하기는 알고리즘에서만이 아니고 모든 공부에 적용할 수 있습니다. 같은 것을 다시 해보는 것에서 우리는 얼마나 많은 것을 배울수 있을까요. 대단히 많습니다. 왜 동일한 문제를 여러 번 풀고, 왜 같은 내용의 세미나에 또 다시 참석하고, 같은 프로그램을 거듭 작성할까요? 훨씬 더 많이 배울 수 있기 때문입니다. 화술 교육에서는 같은 주제에 대해 한번 말해본 연사와 두 번 말해본 연사는 천지 차이가 있다고 말합니다. 같은 일에 대해 두 번의 기회가 주어지면두 번째에는 첫 번째보다 잘 할 기회가 있습니다. 게다가 첫 번째 경험했던 것을 '터널을 벗어나서' 다소 객관적으로 볼 수 있게 됩니다. 왜 자신이 저번에 이걸 잘 못 했고, 저걸 잘 했는지 알게 되고, 어떻게 하면 그걸 더 잘할 수 있을는지 깨닫게 됩니다. 저는 똑같은 문제를 여러 번 풀더라도 매번 조금씩 다른 해답을 얻습니다. 그러면서 정말 엄청나게 많은 것을 배웁니다. '비슷한 문제'를 모두 풀 능력이 생깁니다. 제가 개인적으로 존경하는 전산학자 로버트 플로이드(Robert W. Floyd)는 1978년도 튜링상 강연에서 다음과 같은 말을 합니다.

"제가 어려운 알고리즘을 디자인하는 경험을 생각해 볼 때, 제 능력을 넓히는 데 가장 도움이 되는 특정한 테크닉이 있습니다. 어려운 문제를 푼 후에, 저는 그것을 처음부터 완전히 새로 풉니다. 좀 전에 얻은 해법의 통찰(insight)만을 유지하면서 말이죠. 해법이 제가 희망하는 만큼 명료하고 직접적인 것이 될 때까지 반복합니다. 그런 다음, 비슷한 문제들을 공략할 어떤 일반적인 룰을 찾습니다. 아까 주어진 문제를 아예 처음부터 최고로 효율적인 방향에서 접근하도록 이끌어줬을 그런 룰을 찾는 거죠. 많은 경우에 그런 룰은 불변의 가치가 있습니다. … 포트란의 룰은 몇 시간 내에 배울 수 있습니다. 하지만 관련 패러다임은 훨씬 더 많은 시간이 걸립니다. 배우거나(learn) 배운 것을 잊거나(unlearn) 하는 데 모두."

수학자와 프로그래머를 포함한 모든 문제 해결자들의 고전이 된 죠지 폴리야(George Polya)의 『How to Solve it』에는 이런 말이 있습니다: 

“심지어는 꽤나 훌륭한 학생들도, 문제의 해법을 얻고 논증을 깨끗하게 적은 다음에는 책을 덮어버리고 뭔가 다른 것을 찾는다. 그렇게 하는 동안 그들은 그 노력의 중요하고도 교육적인 측면을 잃어버리게 된다. … 훌륭한선생은 어떠한 문제이건 간에 완전히 바닥이 드러나는 경우는 없다는 관점을 스스로 이해하고 또 학생들에게 명심시켜야 한다.”

저는 ACM의 ICPC 문제 중에 어떤 문제를 이제까지 열 번도 넘게 풀었습니다. 대부분 짝 프로그래밍이나 세미나를 통해 프로그래밍 시연을 했던 것인데, 제 세미나에 여러 번 참석한 분이 농담조로 웃으며 물었습니다. "신기해요. 창준 씨는 그 문제를 풀 때마다 다른 프로그램을 짜는 것 같아요. 설마 준비를 안 해 와서 그냥 내키는 대로 하는 건 아니죠?" 저는 카오스 시스템과 비슷하게 초기치 민감도가 프로그래밍에도 작용하는 것 같다고 대답했습니다. 저 스스로 다른 해법을 시도하고 싶은 마음이 있으면 출발이 조금 다르고, 또 거기서 나오는 진행방향도 다르게 됩니다. 그런데 중요한 것은 이렇게 같은 문제를 매번 다르게 풀면서 배우는 것이 엄청나게 많다는 점입니다. 저는 매번, 전보다 개선할 것을 찾아내게 되고, 또 새로운 것을 배웁니다. 마치 마르지 않는 샘물처럼 계속 생각할 거리를 준다는 점이 참 놀랍습니다.
알고리즘 개론 교재로는 CLR(Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, and Ronald L. Rivest)을 추천합니다. 이와 함께 혹은 이 책을 읽기 전에 존 벤틀리(Jon Bentley)의 『Programming Pearls』도 강력 추천합니다. 세계적인 짱짱한 프로그래머와 전산학자들이 함께 꼽은 위대한 책 목록에서 몇 손가락 안에 드는 책입니다. 아직 이 책을 본 적이 없는 사람은 축하합니다. 아마 몇 주간은 감동 속에 하루하루를 보내게 될 겁니다.

@리팩토링 학습에서의 문제

먼저, 본지 2001년 11월호에 제가 썼던 마틴 파울러의 책을 추천하는 글을 인용하겠습니다.

"OOP를 하건 안 하건 프로그래밍이란 업을 하는 사람이라면 이 책은 자신의 공력을 서너 단계 레벨업시켜줄 수 있다. 자질구레한 술기를 익히는 것이 아니고 기감과 내공을 증강하는 것이다. 혹자는 DP 이전에 RF를 봐야 한다고도 한다. 이 말이 어느 정도 일리가 있는 것이, 효과적인 학습은 문제의식이 선행해야 하기 때문이다. DP는 거시적 차원에서 해결안을 모아놓은 것이다. RF를 보고 나쁜 냄새(Bad Smell)를 맡을 수 있는 후각을 발달시켜야 한다. RF의 목록을 모두 외우는 것은 큰 의미가 없다. 그것보다 냄새나는 코드를 느낄 수 있는 감수성을 키우는 것이 더 중요하다. 필자는 일주일에 한 가지씩 나쁜 냄새를 정해놓고 그 기간 동안에는 자신이 접하는 모든 코드에서 그 냄새만이라도 확실히 맡도록 집중하는 방법을 권한다. 일명 일취집중 후각법. 패턴 개념을 만든 건축가 크리스토퍼 알렉산더나 GoF의 랄프 존슨은 좋은 디자인이란 나쁜 것이 없는 상태라고 한다. 무색 무미 무취의 무위(無爲)적 자연(自然) 코드가 되는 그 날을 위해 오늘도 우리는 리팩토링이라는 유위(有爲)를 익힌다."

주변에서 리팩토링을 잘못 공부하는 경우를 종종 접합니다. 어떤 의미에서 잘못 공부한다고 할까요? '실체화'가 문제입니다. 리팩토링은 도구이고 방편일 뿐인데, 그것에 매달리는 것은 달은 보지 않고 손을 보는 것과 같습니다. 저는 리팩토링 책이 또 하나의 (이미 그 병폐가 많이 드러난) GoF 책이 되는 현상이 매우 걱정됩니다.

@리팩토링 공부

사람들이 일반적으로 생각하는 바와는 달리 리팩토링 학습에 있어 어떤 리팩토링이 있는지, 구체적으로 무엇인지 등의 리팩토링 목록에 대한 지식과 각각에 대한 메카닉스(Mechanics: 해당 리팩토링을 해나가는 구체적 단계)는 오히려 덜 중요할 수 있습니다. 더 기본적이고 유용한 것은 코드 냄새(Code Smell)와 짧은 테스트-코드 싸이클입니다. 이것만 제대로 되면 리팩토링 책의 모든 리팩토링을 스스로 구성해낼 수 있으며, 다른 종류의 리팩토링까지 직접 발견해낼 수 있습니다.
그 책에서는 테스트의 중요성이 충분히 강조되지 않았습니다. 하지만 테스트 코드 없는 리팩토링은 안전벨트 없는 자동차 경주와 같습니다. 그리고 테스트 코드가 리팩토링의 방향을 결정하기도 합니다. 양자는 음과 양처럼 서로 엮여 있습니다. 이런 의미에서 리팩토링은 TDD(Test Driven Development)와 함께 수련하는 것이 좋습니다. 훨씬 더 빨리, 훨씬 더 많은 것을 배울 수 있을 겁니다.
리팩토링을 공부할 때는 우선 코드 냄새의 종류를 알고, 왜 그것이 나쁜 냄새가 될 수 있는지 이해하고(그게 불가하다면 리팩토링 공부를 미뤄야 합니다) 거기에 동의할 수 있어야 합니다. 그런 다음, 대충 어떤 종류의 리팩토링이 가능한지 죽 훑어봅니다. 그 중 몇 개는 메카닉스를 따라가면서 실험해 봅니다. 이제는 책을 덮습니다. 그리고 실제 코드를 접하고, 만약 거기에서 냄새를 맡는다면 이 냄새를 없애기 위해 어떻게 해야 할지 스스로 고민합니다. 리팩토링 책의 목록은 일단 무시하십시오. 그 냄새를 없애는 것이 목표이지, 어떤 리팩토링을 여기에'써먹는 것'이 목표가 되어선 안 됩니다. 이 때, 반드시 테스트 코드가 있어야 합니다. 그래야 '좋은' 리팩토링을 할 수 있습니다. 책을 떠나 있으면서도 책에서 떠나지 않는 방법입니다.
리팩토링을 하기 전에 초록색 불(테스트가 모두 통과)이 들어온 시점에서 코드를 일부 고치면 빨간 불(테스트가 하나라도 실패)로 바뀔 겁니다. 이게 다시 초록색 불이 될 때까지 최소한도의 시간이 걸리도록 하십시오. 현 초록색에서 다음 초록색까지 최소한의 시간을 소비하도록 하면서 코드와 테스팅을 오가게 되면 자기도 모르는 사이에 훌륭한 리팩토링이 자발공으로 터져 나옵니다. 여기서 목적지는 우선은 OAOO(Once And Only Once: 모든 것은 오로지 한 번만 말해야 한다)를 지키는 쪽으로 합니다. 그러면 OAOO와 짧은 테스트-코드 싸이클을 지키는 사이 어느새 탁월한 디자인이 튀어나옵니다. 참고로 저는 '모래시계 프로그래밍'이란 걸 가끔 합니다. 모래시계나 알람 프로그램으로 테스트-코드 사이클의 시간을 재는 것입니다. 그래서 가급적이면 한 사이클이 3분이내(대부분의 모래시계는 단위가 3분입니다)에 끝나도록 노력합니다. 여기서 성공을 하건 실패를 하건 많은 걸얻습니다.

@리팩토링 수련법

제가 고안, 사용한 몇 가지 리팩토링 수련법을 알려드립니다.
①일취집중후각법: 앞에 소개한 본지 2001년 11월호에서 인용된 글 참조
②주석 최소화: 주석을 최소화하되 코드의 가독성이 떨어지지 않도록(혹은 오히려 올라가도록) 노력합니다.
이렇게 하면 자동으로 리팩토링이 이뤄지는 경우가 많습니다.
③OAOO 따르기: OAOO 법칙을 가능하면 최대한, 엄격하게 따르려고 합니다. 역시 자동으로 좋은 리팩토링이 이뤄집니다. 여기서 디자인패턴이 창발하기도 합니다. GoF 책을 한번도 보지 못한 사람이 디자인패턴을 자유자재로 부리는 경우를 보게 됩니다.
④디미터 법칙(Law of Demeter) 따르기: 디미터 법칙을 가능하면 지키려고 합니다. 어떤 리팩토링이 저절로 이뤄지거나 혹은 필요 없어지는가요?
⑤짝(Pair) 리팩토링: 함께 리팩토링합니다. 혼자 하는 것보다 더 빨리, 더 많은 걸 배우게 됩니다.
특히, 각자 작성했던 코드를 함께 리팩토링하고, 제3자의 코드를 함께 리팩토링해 봅니다. 사람이 많다면 다른 짝이 리팩토링한 것과 서로 비교하고 토론합니다.
⑥'무엇'과 '어떻게'를 분리: 어떻게에서 무엇을 분리해 내도록 합니다. 어떤 리팩토링이 창발합니까?

여기서 번, 짝 리팩토링은 아주 효과적인 방법입니다. 저는 이것을 협동적 학습(Collaborative Learning)이라고 부릅니다. 상대가 나보다 더 많이 아는 경우만이 아니고, 서로 아는 것이 비슷해도 많은 양의 학습이 발생합니다. 특히, 전문가와 함께 짝 프로그래밍을 하면 무서울 만큼 빠른 학습을 경험할 수 있습니다. 저와 짝 프로그래밍을 한 사람이 학습하는 속도에서 경이감을 느낀 적이 한두 번이 아닙니다. 문화는 사회적으로 학습되는 것입니다. 우리가 지식이라고 하는 것의 상당 부분은 문화처럼 암묵적인 지식(Tacit Knowledge)입니다. 전문가가 문제가 생겼을 때 어떻게 사고하고, 어떤 과정을 거쳐 접근하며, 어떻게 디버깅하고, 키보드를 어떤 식으로 누르는지, 사고 도구로 무엇을 사용하는지, 일 계획과 관리를 어떻게 하는지, 동료와 어떻게 대화하는지 등은 성문화되어 있지 않습니다. 그러나 이런 것들은 아주 중요합니다. 프로페셔널의 하루 일과의 대부분을 이루고 있기 때문입니다. 이런 것들은 전문가 바로 옆에서 조금씩 일을 도와주면서 배워야 합니다. 도제 살이(Apprenticeship)입니다. 진정한 전문가는 모든 동작이 우아합니다. 마치 춤을 추는 것 같습니다. 이 모습을 바로 곁에서 지켜보게 되면, 주니어는 한마디로 엄청난 충격을 받습니다. 그리고 스펀지처럼 빨아들이게 됩니다. 도대체 이 경험을 책이나 공장화한 학교가 어떻게 대신하겠습니까. 이와 관련해서는 레이브와 웽거(Jean Lave, Etienne Wenger)의 『Situated Learning : Legitimate Peripheral Participation』을 강력 추천합니다. 이 글을 보는 모든 교육 종사자들이 꼭 읽어봤으면 합니다. 이 협동적 학습은 두 사람만이 아니고 그룹 단위로도 가능합니다. 스터디에 이용하면 재미와 유익함 일석이조를 얻습니다.
이 외에, 특히(어쩌면 가장) 중요한 것은 일취집중후각법 등을 이용해 자신의 코드 후각의 민감도를 높이는 것입니다. 코드 후각의 메타포 말고도 유사한 메타포가 몇 가지 더 있습니다. 켄트 벡은 코드의 소리를 들으라고 하고, 저는 코드를 향해 대화하라고 합니다. 코드의 소리를 듣는 것은 코드가 원하는 것에 귀를 기울이는 것을 말합니다. 코드는 단순해지려는 욕망이 있습니다. 그걸 이뤄주는 것이 프로그래머입니다. 그리고 짝 프로그래밍을 할 때 두 사람의 대화를 코드에 남기도록 합니다. 주석이 아닙니다. 왜 이것이 중요한가는 본지 2001년 12월호「허실문답 XP 강화」를 참고하기 바랍니다.
기학으로 우리 사상사에 큰 획을 그은 철학자요, '서울서 책만 사다 망한 사람'으로 이름을 날릴 정도로 엄청난 지식욕을 과시하던 조선시대 사상가 혜강 최한기는 그의 저술 『신기통』(神氣通)에서 '눈에 통하는 법(目通),귀에 통하는 법(耳通), 코에 통하는 법(鼻通)' 등을 이야기하고 있습니다. 어떻게 하면 우리는 코드에 도통할 수 있을까요? 리팩토링을 공부하거나 혹은 했던 사람들에게 많은 영감과 메타포를 주는 책으로 일독을 권합니다. 필자가 기회가 닿는다면 프로그래밍을 혜강의 사상적 측면에서 조망한 글을 써보고 싶습니다.
앞서의 것들이 어느 정도 이뤄지고, 리팩토링에 대한 감이 오게 되면 그 때 비로소 리팩토링 책을 하나 하나 파헤치고 또 거기서 제대로 된 비판을 할 수 있게 됩니다.
by 필라르 | 2004/03/26 20:31 | About Programming | 트랙백 | 덧글(0)
2004년 03월 26일
*어떻게 공부할까? 프로그래머를 위한「공부론」Part III
@디자인패턴 학습에서의 문제

잡지에 연재되거나 서적으로 출간된 혹은 세미나에서 진행되었던 디자인패턴 '강의'를 몇 가지 접했습니다. 훌륭한 강의도 많았지만 그렇지 못한 것도 있었습니다. 몇 가지 문제점을 지적하겠습니다.

◆패턴을 지나치게 실체화, 정형화해 설명한다.
◆컨텍스트와 문제 상황에 대한 설명이 없거나 부족하다. 결과적으로 문제를 해결하기 위해 패턴이 도입된 것이 아니라 패턴을 써먹기 위해 패턴이 도입된 느낌을 준다.
◆문제의식을 먼저 형성하게 하지 않고 답을 먼저 보여준 뒤 그걸 어디에 써먹을지 가르친다. 왜 이걸 쓰는 게 좋은지는 일언반구 언급이 없다. 독자는 '어린아이가 망치를 들고 있는 오류'에 빠질 것이다.
◆패턴이 어떻게 생성되었는지 그 과정을 보여주지 못한다. 즉, 스스로 패턴을 만들어내는 데 도움이 전혀 되지 않는다.
◆해당 패턴이 현실적으로 가장 자주 쓰이는 맥락을 보여주지 못한다. 대부분 장난감 문제(Toy Problem)에서 끝난다.

그런 패턴 강의를 하는 분들이 알렉산더(Christopher Alexander, 패턴언어 창시자)의 저작을 충실히 읽어봤다면 이런 병폐는 없을 것이라 생각합니다. 알렉산더의 저작을 접해보지 못 하고서 패턴을 가르치는 사람은 성경을 읽어보지 않은 전도사와 같을 것입니다. 알렉산더가 『The Timeless Way of Building』의 마지막에서 무슨 말을 하는가요?

“이 마지막 단계에는 더 이상 패턴은 중요하지 않다. … 패턴은 당신이 현실적인 것에 대해 수용적이 되는 것을 가르쳐줬다.”

패턴 역시 도구요, 방편일 뿐입니다. 패턴은 현실적인 것에 대해 수용적이 되도록 가르친다는 말은 결국 우리가 궁극적으로 추구하는 것은 패턴이 아니라 현실이어야 한다는 이야기입니다. 물론 처음 단계에는 교육적인 목적에서, 어느 정도 패턴에 얽매여도 괜찮다고는 해도, 나중에 패턴을 잊고 패턴에서 자유로워지려면 처음부터 패턴에 대해 도구적?방편적인 인식을 가져야 합니다.
미국 캘리포니아 주립대학의 교수 베티 에드워즈(Betty Edwards)가 쓴 책 중에 『Drawing on the Right Side of the Brain』이라는 유명한 베스트셀러가 있습니다. 사람의 뇌와 그림 그리기의 관계에 대한 탁월한 책입니다. 에드워즈는 자신의 그리기 실력을 향상시키기 위해 우뇌를 적극적으로 사용하는 구체적인 방법들을 가르쳐줍니다. 그 중 대표적인 것 하나가 대상을 뒤집어 놓고 그리는 것입니다. 지금 실험해 보길 바랍니다. 1000원권 지폐를 바로 놓고 그걸 비슷하게 그려보고, 이번에는 그걸 위아래가 거꾸로 되게 놓고 따라 그려보십시오. 아마 무척 놀랐을 겁니다. "아니 내가 이렇게 그림을 잘 그리다니! 그것도 거꾸로!" 그렇습니다. 우리는 자신의 머리 속 패턴에 얽매여 세상을 제대로 보지 못 할 때가 많습니다. 실체가 코에 약간이라도 비슷하게 보이면 우리는 그것을
이미 우리 머리 속에 추상적으로 갖고 있던 기하학적 '코'의 패턴으로 대체해버리는 것입니다.

@디자인 패턴 공부

우선은 제 교육철학과 언어교습론, 그리고 공부론 이야기를 잠깐 하겠습니다. 기본적으로 교육은 교육자가 피교육자가에게 지식을 그대로 전달하는 행위가 아닙니다. 진정한 교육은 피교육자의 개인적 체험에 기반한 전폭적 동의에서 출발합니다. 저는 이를 동의에 의한 교육이라고 합니다. 제가 "주석문을 가능하면 쓰지 않는 것이 더 좋다"는 이야기를 했을 때 이 문장을 하나의 사실로 받아들이고 기억하면 당장 그 시점에는 학습이 일어나지 않는다고 봅니다. 대신 여러분이 차후에 여러 가지 경험을 하면서도 이 화두를 놓치지 않고 있다가 어느 순간엔가, "아! 그래, 주석문을 쓰지 않는 게 좋겠구나!"하고 자각하는 순간, 바로 그 시점에 학습과 교육이 이뤄지는 것입니다. 이는 기본적으로 삐아제와 비갓스키(Lev Vygotsky)의 구성주의를 따르는 것이죠. 지식이란 외부에서 입력받는 것이 아니고, 그것에 대한 모델을 학습자 스스로가 내부에서 구축할 때 획득할 수 있는 것이라는 사상이죠. 권법에서 주먹에 대해 달통한 도사가 '권을 내지르는 법'에 대한 규칙들을 정리해서 애제자의 머리 속에 아무리 쑤셔 넣는 데 성공한들 그 제자가 도사만큼 주먹이 나갈리는 만무합니다. 권을 내지르는 법을 유추해 내기까지 그 스승이 겪은 과정을 제자는 완전히 쏙 빼먹고 있기 때문입니다. 소위 '몸'이 만들어지지 않은 것이지요. 제자는 마당 쓸기부터, 물 긷기 등의 수련 과정을 겪어야만 하고 스승이 정리한 그 일련의 규칙에 손뼉을 치고 춤을추며 기쁨의 동의를 할 수 있을 정도로 수련 과정이 축적된 이후에야 비로소 진정한 '가르침'이 이뤄지는 것이며, 청출어람의 가능성도 생각해 볼 수 있는 것입니다. 이런 동의라는 것은 학습자 자신만의 컨텍스트와 문제의식을 바탕으로 한 것입니다. 우리는 많은 경우, 어떤 지식과 동시에 그 지식의 필요성까지도 지식화해서 외부에서 주입을 받습니다. 하지만 진정 체화된 지식을 위해서는 스스로가 이미 문제의식을 갖고 있어야 합니다.
패턴도 마찬가지인데, 대부분 그 패턴의 필요성을 체감하지 못한 채 그냥 도식적 구조를 외우기에만 주력하는 사람이 많습니다만, 사실 그렇게 되면 어떤 경우에 이 패턴이 필요하고 어떤 경우에는 사용하면 안 되는지(GoF는 패턴을 정말 안다는 것은 그 패턴을 쓰면 안 될 때를 아는 것이라 했습니다) 등을 알기 힘듭니다. 설령 책에 나온 가이드를 암기했더라도요. 자신의 삶 속에서 문제의식이 구체적으로 실제 경험으로 형성되지 않았기 때문입니다.
GoF 중 한 명인 랄프 존슨(Ralph Johnson)은 다음과 같이 말합니다.

"우리[GoF]는 책에서, 정말 그 패턴들이 필요하다는 것을 알만큼 충분한 경험을 갖기 전에는 그것을 [시스템 속에] 집어넣는 것을 피해야 한다고 말할 만큼 대담하진 못했다. 하지만 우리 모두는 그 사실을 믿었다. 패턴은 프로그램의 초기 버전이 아니고 프로그램 생애의 훨씬 나중에 가서야 비로소 등장해야 한다고 나는 늘 생각해 왔다."

결국은 어떤 패턴의 필요성을 자신의 경험 속에서 절감하지 못한다면 그 패턴을 제대로 아는 것이 아니라고 말할 수 있을 겁니다. 따라서 패턴 하나를 공부할 때는 가능한 한 실제 예를 많이 접해야 합니다. 그리고 패턴을 적용하지 않은 경우에서 그 필요를 느끼고 설명할 수 있게끔 다양한 코드를 접해야 합니다.

@소프트웨어 개발에 푹 빠지기

패턴 중에 보면 서로 비슷비슷한 것이 상당히 많습니다. 그 구조로는 완전히 동일한 것도 있죠. 초보자를 괴롭히는 것 중 하나입니다. 이것은 외국어를 공부할 때 문법 중심적인 학습을 하면서 부딪치는 문제와 비슷합니다. '주어+동사+목적어'라는 구조로는 동일한 두 개의 문장, 즉 'I love you'와 'I hate you'가 구조적으로는 동일할지라도 의미론적으로는 완전히 반대가 될 수 있는 겁니다. 패턴을 공부할 때는 그 구조보다 의미와 의도를 우선해야 하며, 이는 다양한 실례를 케이스 바이 케이스로 접하면서 추론화 및 자신만의 모델화라는 작업을 통해 하는 것이 최선입니다. 스스로 문법을 발견하고 체득하는 것이라고 할까요.
DP는 사전과 같습니다. 이 책은 순서대로 소설 읽듯이 읽어나가라고 집필된 것이 아니고, 일종의 패턴 레퍼런스로 쓰인 것입니다. 역시 GoF의 한 명인 존 블리스사이즈(John Vlissides)는 다음과 같이 말합니다.

“여기서 내가 강조하고 싶은 것은 디자인패턴, 즉 GoF 책을 어떻게 읽느냐는 것이다. 많은 사람들은 그 내용을 온전히 이해하기 위해서는 순서대로 읽어야 한다고 느낀다. 하지만 GoF는 소설이 아니라 레퍼런스 북이다. 독일어를 배우기 위해 독영 사전의 처음부터 끝까지 하나하나 읽으려고 하는 경우를 생각해 보라. 그렇게는 결코 배울 수 없을 것이다! 독일어를 마스터하기 위해서는 독일어 문화에 자기 자신을 푹 담궈야(immerse) 한다. 독일어로 살아야 하는 것이다. 디자인패턴도 똑같다. 그걸 마스터하기 이전에 소프트웨어 개발에 자신을 푹 담궈야 한다. 패턴으로 살아야 하는 것이다.
만약 꼭 그래야 한다면 소설 읽듯이 디자인패턴 책을 읽어라. 하지만 거의 아무도 그 방식으로 유창해지지 못한다. 소프트웨어 개발 프로젝트의 열기 속에서 패턴이 동작하게 하라. 실제 디자인 문제를 직면했을 때 그 패턴들의 통찰을 이용하라. 이것이 GoF 패턴들을 자신의 것으로 만드는 가장 효율적인 방법이다.“

어떤 지식을 체화하기 위해선 그 지식으로 살아야 한다는 말을 확인할 수 있습니다. 영어를 배우려면 영어로 살고, DP를 배우려면 DP로 살라는 단순하면서도 아주 강력한 말입니다. 어떤 특정 문장 구조를 학습하는 데 최선은 그 문장 구조를 이용한 실제 문장을 나에게 의미 있는 실제 컨텍스트 속에서 많이 접하고 스스로 나름의 모델을 구축하여 교과서의 법칙에 '기쁨에 찬 동의'를 하는 것입니다.
주변에서 특정 패턴이 구현된 코드를 구하기가 힘들다면 이 패턴을 자신이 만지고 있는 코드에 적용해 보려고 노력해 볼 수 있습니다. 이렇게 해보고 저렇게도 해보고, 그러다가 오히려 복잡도만 증가하면 "아 이 경우에는 이 패턴을 쓰면 안 되겠구나"하는 걸 학습할 수도 있죠. GoF는 패턴을 배울 때는 한결 같이 "이 패턴이 적합한 상황과 동시에 이 패턴이 악용, 오용될 수 있는 상황"을 함께 공부하라고 합니다.
이런 식의 '사례 중심'의 공부를 위해서는 스터디 그룹을 조직하는 것이 좋습니다. 혼자 공부를 하건, 그룹으로하건 커리프스키(Joshua Kerievsky)의 「A Learning Guide To Design Patterns」(http://www.industriallogic.com/papers/learning.html)를 참고하세요. 그리고 스터디 그룹을 효과적으로 꾸려나가는 데는 스터디 그룹의 패턴 언어를 서술한 「Knowledge Hydrant」(http://www.industriallogic.com/papers/khdraft.pdf)를 참고하면 많은 도움이 될 겁니다. 이 문서는 뭐든지 간에 그룹 스터디를 한다면 적용할 수 있습니다.
LG2DP(「A Learning Guide To Design Patterns」) 뒷부분에 보면 DP를 공부하는 순서와 각 패턴에서 던질만한 질문이 같이 정리되어 있습니다. DP는 순차적으로 공부해야만 하는 것은 아닙니다. 효과적인 공부의 순서가 있습니다. sorry라는 단어를 모르면서 remorseful이라는 단어를 공부하는 학생을 연상해 보세요. 외국어 공부에서는 자기 몸에 가까운 쉬운 단어부터 공략하는 것이 필수적입니다. 이런 걸 근접 학습(Proximal Learning)이라고도 하죠. 등급별 어휘 목록 같은 게 있으면 좋죠. LG2DP에서 제안하는 순서가 그런 것 중 하나입니다.
랄프 존슨은 이런 순서의 중요성에 관해 다음과 같은 말을 했습니다.

"… 하지만 나는 언제나 싱글톤 패턴을 가르치기 전에 콤포짓, 스트래터지, 템플릿 메쏘드, 팩토리 메쏘드 패턴을 가르친다. 이것이 훨씬 더 일반적인 것들이며, 대다수의 사람들은 아마도 이것들 중 마지막 두 가지를 이미 사용하고 있을 것이다."

@마이크로패턴

그런데 사실 GoF의 DP에 나온 패턴들보다 더 핵심적인 어휘군이 있습니다. 마이크로패턴이라고도 불리는 것들입니다. DP에도 조금 언급되어 있긴 합니다. 이런 마이크로패턴은 우리가 알게 모르게 매일 사용하는 것들이고 그 활용도가 아주 높습니다. 실제로 써보면 알겠지만, DP의 패턴 하나 쓰는 일이 그리 흔한 게 아닙니다. 마이크로패턴은 켄트 벡의 『Smalltalk Best Practice Patterns』에 잘 나와 있습니다. 영어로 치자면 관사나 조동사 같은 것들입니다. 그리고 이런 마이크로패턴과 함께 리팩토링을 공부하는 게 좋습니다. 리팩토링은 패턴의 필요를 느끼게 해줍니다. 제가 리팩토링 공부에서도 언급했지만 OAOO를 지키면서 리팩토링을 하다보면 자연스레 디자인패턴에 도달하는 경우가 많습니다. 이 때는 지나친 엔지니어링(Overengineering)이 발생하지 않고, 오로지 필요한 만큼만 생깁니다. 이에 관해서는 커리프스키의 「Stop Over-Engineering!」(Software Development Magazine, Apr2002, http://www.sdmagazine.com/documents/s=7032/sdm0204b/0204b.htm)의 일독을 권합니다. 리팩토링이 디자인패턴을 어떻게 생성해낼 수 있는지 보여주고 있습니다.
1980년대 이후 최근 알렉산더의 향방도 이런 쪽으로 가고 있습니다. 그는 자신이 발표한 기존 패턴들이 너무 크다고 생각해 그런 패턴들을 구성하고, 자동으로 만들어 내며, 또 관통하는 더 작은 원칙들을 발견하는 데 노력해오고 있습니다. 코플리엔(James Coplien)은 컴퓨터계가 알렉산더의 최근 발전을 쫓아가지 못한다고 늘 이야기합니다.

@제대로 된 패턴 구현을 위한 다양한 접근 시도하기

우리의 지식이라는 것은 한 가지 표현양상(representation)으로만 이뤄져 있지 않습니다. 사과라는 대상을 음식으로도, 그림의 대상으로도 이해할 수 있어야 합니다. 실제 패턴이 적용된 '다양한 경우'를 접하도록 하라는 것이 이런 겁니다. 동일 대상에 대한 다양한 접근을 시도하라는 것이죠. 자바로 구현된 코드도 보고, C++로 된 것도 보고, 스몰토크로 된 것도 봐야 합니다. 설령 '오로지 자바족'이라고 할지라도요(전 이런 사람들을 자바리안(Javarian)이라고 부릅니다. 자바와 바바리안(barbarian)을 합성해서 만든 조어지요). 이런 '오로지 하나만 공부하는 것'의 병폐에 대해서는 존 블리스사이즈가 쓴 「Diversify」(http://www.research.ibm.com/people/v/vlis/pubs/gurus-99.pdf)라는 글을 읽어보세요. 이렇게 다양화를 해야 비로소 자바로도 '상황에 맞는' 제대로 된 패턴을 구현할 수 있습니다. 패턴은 그 구현(implementation)보다 의도(intent)가 더 중요하다는 사실을 꼭 잊지 말고, 설명을 위한 방편으로 채용된 한 가지 도식에 자신의 사고를 구속하는 우를 범하지 않기를 빕니다.
이런 맥락에서 저는 DP를 공부할 때 GoF와 동시에 『Design Patterns Smalltalk Companion』을 필수적으로 읽기를 권합니다. 두 권은 말하자면 양날개입니다. 하나는 정적언어로 구현되었고(간간이 스몰토크 구현이 있긴합니다), 다른 하나는 동적언어로 구현되어 있습니다. 언어와 패턴의 고리를 느슨하게 하고, 패턴을 여러 관점에서 신선하게 볼 수 있는 계기가 될 것입니다. 또, 한 쪽을 보고 이해가 잘 되지 않을 때 다른 쪽을 보면 쉽게 이해됩니다. 서로 상보적인 것이죠. 패턴도 결국 '문제해결'을 위한 한 가지 방편에 지나지 않습니다. 주변에서 "이 경우에는 무조건 이 패턴을 써야합니다"하고 생떼를 쓰는 사람을 보면 씁쓸한 기분을 감출 수 없습니다.

@디자인패턴 추천서

디자인패턴 책 중에 중요한 서적을 몇 권 소개하겠습니다.

◆『Design Patterns Explained』(Shalloway, Trott): 최근 DP 입문서로 급부상하고 있는 명저
◆『Design Patterns Java Workbook』(Steven John Metsker): DPE 다음으로 볼만한 책으로 쏟아져 나오는 시중의 조악한 자바 패턴 책들과는 엄연히 다르다. 워크북 형식을 채용해서 연습문제를 풀고 뒷부분의 답과 대조해 볼 수 있는 등 독학자가 공부하기에 좋다.
◆『Refactoring』(Martin Fowler): DP 공부 이전에 봐서 문제의식 형성하기(망치를 들면 모든 것이 못으로 보이는 오류 탈피)
◆『Design Patterns』: 바이블.
◆『Design Patterns Smalltalk Companion』: GoF가 오른쪽 날개라면 DPSC는 왼쪽 날개
◆『Pattern Hatching』(John Vlissides): DP 심화학습. 얇지만 밀도 높은 책.
◆『Smalltalk Best Practice Patterns』(Kent Beck): 마이크로 패턴. 개발자의 탈무드. 감동의 연속.
◆『Pattern Languages of Program Design』 1,2,3,4: 패턴 컨퍼런스 논문 모음집으로 대부분은 인터넷에서 구할 수 있음
◆『Pattern-Oriented Software Architecture』 1,2: 아키텍처 패턴 모음. 2권은 네트워크 애플리케이션의 아키텍처 모음.
◆『Concurrent Programming in Java』(Doug Lea): 컨커런트 프로그래밍에 대한 최고의 서적.
◆『Patterns of Software』(Richard Gabriel): 패턴에 관한 중요한 에세이 모음.
◆『Analysis Patterns』(Martin Fowler): 비즈니스 분석 패턴 목록. 비즈니스 애플리케이션 개발자에게 많은 도움이 됨.
◆『A Timeless Way of Building』(Christopher Alexander): 프로그래머들이 가장 많이 본 건축 서적. 패턴의 철학적?이론적 배경. '구약'('신약'은 올해 안에 출간 예정인 동저자의 『The Nature of Order』).
◆『A Pattern Language』(Christopher Alexander): 알렉산더의 건축 패턴 모음집.
◆『Problem Frames』(Michael Jackson): DP의 해결(solution) 지향식의 문제점과 극복 방안으로서의 문제 지향식 방법. 마이클 잭슨은 요구 사항 분석 쪽에서 동명의 가수만큼이나 유명.

DP를 처음 공부한다면, DPE와 DPJW를 RF와 함께 보면서 앞서의 두 권을 RF적으로 독해해 나가기를 권합니다(하버드 대학의 뚜웨이밍 교수는 요즘 칸트를 유교적으로 독해하고 있다고 합니다. 하나의 책을 다른 각도에서 독해하는 것, 여기서 배우는 것이 많습니다). 이게 된 후에는 GoF와 DPSC를 함께 볼 수 있습니다. 양자는 상호보완적인 면이 강합니다. 이쯤 되어 SBPP를 보면 상당히 충격을 받을 수 있습니다. 스스로가 생각하기에 코딩경험이 많다면 다른 DP 책 이전에 SBPP를 먼저 봐도 좋습니다.
이 정도의 책을 봤다면 POSA와 PLOPD 등에서 자신이 관심이 가는 패턴들을 찾아 읽는 것이 좋습니다. 그리고 동시에 알렉산더의 원저들을 꼭 읽기를 권합니다. 가브리엘의 책이 알렉산더의 사상 이해에 많은 도움이 될 것입니다.
패턴 공부를 해나가면서 남을 가르치는 것이 공부에 많은 도움이 됩니다(사실 자바 패턴 책 중에 어떤 것은 "내가 패턴을 처음 공부하면서 같이 쓴 것이다"라고 저자가 고백한 것도 있습니다). 보이스카웃에서는 보통 다음 과정을 통해 뭔가를 '학습'하게 한다고 합니다. 처음은 어떻게 하는지를 보여주고, 다음은 스스로 그것을 해보게하고, 다음으로 그걸 남에게 가르치게 합니다. 이 때 중요한 것은 상대가 이해하지 못 하면 그 이유를 자기 자신에게서 찾는 것이 나에게 더 이득이 된다는 것입니다. "내가 설명을 잘못 했군"하고 생각하는 것이죠. 그러면 다음번에는 설명을 좀더 잘 할 수 있게 되고, 동시에 자기의 이해도 더욱 명료해지게 됩니다. 저는 'OOP 개념을 한시간 만에 가르치기'나 '특정 언어 문법을 한 시간 만에 가르치기' 등을 하나의 도전으로 생각하고 즐깁니다. 가르치면서 동시에 배운다는 것은 정말 놀라운 경험입니다.
by 필라르 | 2004/03/26 20:29 | About Programming | 트랙백 | 덧글(0)
2004년 03월 26일
*어떻게 공부할까? 프로그래머를 위한「공부론」IV
@익스트림 프로그래밍 학습에서의 문제

앞의 경우와 비슷합니다. 익스트림 프로그래밍을 공부하는 사람들은 실제로 행해보지 않고 책만 들여다보면 안됩니다. 그렇다고 책이 중요하지 않다는 말은 아닙니다. 하지만 자전거 타기는 자기 몸으로 직접 굴려봐야 합니다. 게다가 켄트 벡 스스로가 『XP Explained』를 만약 다시 쓴다면 뜯어고치고 싶은 부분이 상당히 된다고 말하는 것을 봐도 알 수 있듯이 초기 XP 이후 바뀌고 보완된 점이 상당수 있습니다. 따라서 책만으로 XP를 공부하기는 힘듭니다. 지금은 책 속의 XP가 사람들의 머리 속 XP에 한참 뒤쳐져 있습니다.
어찌 되었든 XP에는 무술이나 춤, 혹은 악기 연주 등과 유사한 면이 많습니다. 따라서 글을 보고 그것을 익히기는 쉽지 않습니다. 그나마 메일링 리스트 같은 '대화'를 보면 훨씬 더 많은 것을 얻을 수 있기는 하지만, 태권도정권 찌르기를 말로 설명하는 것이 불가능에 가깝듯이 XP를 언어를 통해 익히기는 정말 어렵습니다. 우리의 언어는 너무도 성글은 미디어입니다(XP는 매 초, 매 순간 벌어지는 '일상적' 장면의 연속이 매우 중요합니다).

@익스트림 프로그래밍 공부

XP를 이해하려면 다음 기본 자료에 대한 이해가 우선해야 합니다(본지 2001년 12월호 「허실문답 XP 강화」참조).
◆『XP Explained』(Kent Beck): XP 선언서
◆『XP Installed』(Ron Jeffries et al): C3 프로젝트에 적용한 예, 얻은 교훈 등
◆『Planning XP』(Kent Beck, Martin Fowler): 계획 부분 설명(관리자, 코치용)
◆『Refactoring』(Martin Fowler): 리팩토링에 대한 최고의 책
◆『XP Applied』: 유즈넷과 메일링 리스트의 논의 등 최근 자료를 반영
◆『XP Explored』: 가장 쉽고 구체적인 XP 안내서
이 중에서 XPI나 XPX를 먼저 권합니다. XPE는 좀 추상적인 서술이 많아서 봐도 느낌이 별로 없을 수 있습니다
(2001년 본지 11월호에 제가 쓴 리뷰 참고). 여유가 되면 다음 자료를 더 참고합니다.
◆『The Timeless Way of Building』: 패턴 운동을 일으킨 알렉산더의 저작. 현장 고객(On-site Customer), 점진 성장(Piecemeal Growth), 소통(Communication) 등의 아이디어가 여기에서 왔음.
◆『XP in Practice』(Robert C. Martin 외): 두세 사람이 짧은 기간 동안 간단한 프로젝트를 XP로 진행한 것을기록. 자바 사용(중요한 문헌은 아님).
◆『XP Examined』: XP 컨퍼런스에 발표된 논문 모음
◆『Peopleware』(Tom DeMarco): 개발에 있어 인간 중심적 시각의 고전
◆『Adaptive Software Development』(Jim Highsmith): 복잡계 이론을 개발에 적용. 졸트상 수상.
◆『Surviving Object-Oriented Projects』(Alistair Cockburn): 얇고 포괄적인 OO 프로젝트 가이드라인
◆『Software Project Survival Guide』(Steve McConnell): 조금 더 전통적인 SE 시각.
◆『The Psychology of Computer Programming』(Gerald M. Weinberg): 프로그래밍에 심리학을 적용한 고전. 코드 공유와 짝 프로그래밍에 필수인 비자아적 프로그래밍(Egoless Programming)이 여기서 나왔다.
◆『Agile Software Development』(Alistair Cockburn): 전반적 애자일 방법론에 대한 개론서
◆『Software Craftsmanship』(Pete McBreen): 장인으로서의 새로운 프로그래머 상
◆『Agile Software Development with SCRUM』(Schwaber Ken): 최근 확장성(Scalability)을 위해XP+SCRUM의 시도가 애자일 쪽의 큰 화두임.
◆『A Practical Guide to eXtreme Programming』(David Astels 외): 저자들이 직접 참여한 프로젝트를 따라가 보면서 배움. 자바로 구현. XPP보다는 스케일이 큼.
◆『Agile Modeling』(Scott Ambler): 애자일 쪽에서 모델링이 무시되는 느낌이 있을 수 있는데, 그쪽으로 깊게 천착한 사람이 앰블러임.
◆『Agile Software Development Ecosystems』(Jim Highsmith): 각각의 애자일 방법론에 대한 소개와 동시에 각 방법론의 대표자들 인터뷰가 백미.
◆『Test Driven Development』(Kent Beck): 곧(아마 올해 내에) 출간 예정인 최초의 TDD 서적. TDD를 모르면 XP도 모르는 것(TDD를 실제 적용하려면 적어도 반년 정도는 계속 훈련해야 함)
◆IEEE Software/Computer, CACM, Software Development Magazine 등에 실린 기사
◆『XP Conference, XP Universe 등의 논문들(특히 최근 것들)
◆유즈넷, 메일링 리스트, 오리지널 위키(http://c2.com)의 논의들

특히 유즈넷, 메일링 리스트, 오리지널 위키는 늘 가까이 하고 있어야 합니다. 이 세 곳을 살필 때, 특히 다음 사람들의 글은 꼭 읽어보고 항상 레이더를 열어두면 좋습니다(이 외에도 개발 경력 10년, 20년이 넘는 짱짱한 사람이 많으므로 눈 여겨 관찰하세요. 모든 글을 읽는 것은 무리이므로 그들의 대화를 일차적으로 읽어야 합니다).
켄트 벡, 론 제프리즈(Ron Jeffries), 워드 커닝엄(Ward Cunningham), 앨리스테어 코번(Alistair Cockburn), 마틴 파울러, 로버트 마틴 혹은 엉클 밥(Robert C. Martin aka Uncle Bob), 마이클 페더즈(Michael Feathers), 켄아우어(Ken Auer), 윌리엄 웨이크(William Wake), 로이 밀러(Roy Miller), 데이브 토마스(Dave Thomas), 앤디헌트(Andy Hunt), 랄프 존슨, 스카트 앰블러(Scott Ambler), 짐 하이스미스(Jim Highsmith), 조슈아 커리프스키(Joshua Kerievsky), 로렌트 보사빗(Laurent Bossavit), 존 브루어(John Brewer) 등

이런 자료들 외에, 기회가 된다면 주변에서 XP를 직접 사용하는 곳을 방문해서 하루만 같이 생활해 보기를 권합니다. 반년 공부를 앞당길 수 있습니다. 제가 공부할 때는 주변에 XP를 아는 사람이 없어서 혼자 공부했는데, 그것에 비해 XP를 직접 사용하는 상황에 처한 사람은 (제가 억울하리만큼) 더 적은 노력으로 몇 배 이상 빨리 몸에 익히는 것 같았습니다. 이게 힘들면 같이 공부하는 방법이 있습니다(앞서 언급된 스터디 그룹에 관한 패턴 참고). 이 때 같이 책을 공부하거나 하는 것은 시간 낭비가 많습니다. 차라리 공부는 미리 다 해오고 만나서 토론을 하거나 아니면 직접 실험을 해보는 것이 훨씬 좋습니다. 두 사람 당 한 대의 컴퓨터와 커대란 화이트보드를 옆에 두고 말이죠. 제 경우 스터디 팀과 함께 저녁 시간마다 가상 XP 프로젝트를 많이 진행했고, 짤막짤막하게 프로그래밍 세션도 많이 가졌습니다. 나중에 회사에서 직접 XP를 사용할 때 많은 도움이 되었습니다.

@Refactor Me

제가 하고 싶은 말은 더 있지만 이 글은 일단 여기서 끝이 납니다. 서두에서 말씀드렸듯이 애초 쓰려던 '일반론'은 생략하고, 대신 독자들의 몫으로 남겨두려 합니다. 이 글 자체가 여러분의 리팩토링 수련의 연장(延長)이 되었으면 하는 바램입니다. 이 글과 함께 실생활에서 직접 실험을 해보면서 - 이 때 욕심 부리지 않고 한 가지씩 지긋이 해보는 느긋함과 음미의 정신이 필요할지도 모르겠습니다 - 자신의 경험을 축적해 나가고, 동시에 이 글을 적절히 리팩토링해서 자신만의 패턴을 차근히 만들어 나가길 바랍니다. 그렇습니다. 리팩토링은 대상에 대한 이해가 깊고 경험이 많을수록 더 잘할 수 있습니다.
이 글에 소개된 제 공부론은 어찌 보면 상당히 진부해 보이기도 할 것입니다. 하지만 저는 이런 상식적이고 일상적이며 심지어는 소소해 보이는 것들에서 많은 감동을 받아왔습니다. 이 글도 사실 제 감동의 개인사입니다. 저는 "만약 오늘 어떤 것에라도 감동한 것이 없었다면, 오늘은 뭔가 잘못 산 것이다"라는 신조를 갖고 있습니다. 그것이 컴퓨터이건 대화이건 상관없이 말이죠. 저는 날마다 감동하며 살려고 노력합니다. 그러나 이 감동에 뭔가 꼭 대단한 것이 필요한 것은 아닙니다. 저는 오히려 감동 받기 위해 스스로 대단해져야 할 필요를 느끼기도 합니다. '감동'이라는 것은 주어지는 것이 아닙니다. 나와 타자가 공조하여 만드는 대화입니다. 감동해야 체득할 수 있다고 생각합니다. 그리고 이 감동은 개인적 삶 속에서 자기가, 자신의 몸으로, 직접 얻는 것입니다. 工夫 열심히 합시다. @
by 필라르 | 2004/03/26 20:28 | About Programming | 트랙백 | 덧글(0)
2004년 02월 12일
신쥬쿠사진
신쥬쿠사진
by 필라르 | 2004/02/12 10:49 | JapanStreet | 트랙백(1) | 덧글(0)


<< 이전 페이지 | 다음 페이지 >>