[마이크로 소프트웨어], 2002년 6월호
[nML과 함께하는 프로그래밍 여행, 제1편]
프로그래밍을 지배하는 프로그래밍 언어생각이 바뀌면 어려웠던 문제가 쉽게 풀린다. 문제를 바라보는 시각이 조정되는 순간에, 예전에 어렵게 보였던 문제가 쉽게 풀리는 것이다.
이번 [nML과 함께하는 프로그래밍 여행] 시리즈에서는 프로그래머의 생각의 틀을 다양하게 해 주는 프로그래밍 언어로 nML이란 것을 소개하려고한다. 이번 첫 기사에서는 nML이 안내하는 생각의 틀은 어떤 것인지를 우선 살펴보도록 한다. 제목에서 눈치챘겠지만, 그것은 값중심으로 생각하기이다(value-oriented programming). 값중심의 프로그래밍아래의 프로그램을 생각해 보자.a := 1; b := 2; c := a + b; d := a + b; 위의 프로그램이 실행되었다고 하고, 몇가지 질문을 던져보자.
이제, 정수보다는 복잡한(컴퓨터에 구현하려할 때 할 일이 많은) 값을 다루는 프로그램에 대해서 비슷한 질문을 해보자. 집합을 다루는 프로그램을 생각하자. 아래 프로그램에서, set(1,2,3)은 1,2,3으로 구성된 집합을 만들고, setUnion(x,y)는 집합 x와 y의 합집합을 만든다. a := set(1,2,3); b := set(4,5,6); c := setUnion(a,b); d := setUnion(a,b); 위의 프로그램이 실행된 후, 이전과 같은 질문을 해 보자.
이야기가 필요이상으로 복잡해졌는데, 값중심(value-oriented)의 프로그래밍 스타일을 물건중심(object-oriented)의 스타일과 대비해서 요약하면 다음과 같다. 물건은 끊임없이 변하지만, 값은 일단 만들어 졌으면 변하지 않는다. 정수 1은 변하지 않는다. 1이 어느날 변해서 1.2가 되거나 99가 되지 않는다. 집합 {1,2}는 변하지 않는다. 이 집합이 변해서 {1,2,3}이 된 것이 아니고, 집합 {1,2}와 {1,2,3}은 서로 다른 집합인 것이다. 1과 1.2가 다른 값이듯이. 물건 S를 집합 {1,2,3}라고 하자. 이 집합에 원소 4를 더하는 경우 S.add(4) 물건 S는 집합 {1,2,3} 이었다가 {1,2,3,4} 라는 새로운 집합으로 변하게 되는 것이다(그림 5).
물건은 어떤 작업을 통해서 항상 그 상태가 변하간다. 반면에, 값중심의 프로그래밍인 경우, 집합 S ({1,2,3})라는 값에 원소 4를 추가하는 경우 add(S, 4) 새롭게 만들어 지는 집합은 S라는 집합을 변화시키지 않는다. 오직 다른 집합 {1,2,3,4}를 의미하는 것 뿐이다. 이때, 값중심의 프로그래밍에서는 값이 변하지 않으므로, 지금까지 계산된 집합들을 최대한 공유하면서 새로운 집합을 표현할 수 있을 것이다 (그림 6).
값중심의 프로그래밍은 특별한 것이 아니다``값중심의 프로그래밍'' 이라는 호칭이 또다른 개념의 프로그래밍 파라다임을 뜻하나 보다, 라고 긴장할 필요는 없다. 그것은 우리 프로그래머들이 까마득히 잊고 있었던, 예전(중고등학교 시절 컴퓨터 프로그래밍을 배우기 전)에는 너무도 익숙했던 프로그래밍 스타일이었다.왜 잊고 있었던 것일까? 지금까지 익혀 온 컴퓨터 프로그래밍은 그것과 달리 복잡했기 때문이다. 왜 다르고 복잡했던 것이었을까? 그것은 자연스러운 ``값중심의 프로그래밍''을 효과적으로 지원하는 기술이 아직 컴퓨터에 없었기 때문이다. 그래서 컴퓨터 프로그래밍은 복잡한 스타일의 생각을 강요해왔던 것이다. 하지만 이제는, ``값중심의 프로그래밍''기술을 가능하게 하는 튼튼한 연구성과들이 꾸준히 쌓여서, 그러한 자연스러운 프로그래밍을 회복할 수 있게 되었다. 값중심의 프로그래밍을 제대로 지원하는 프로그래밍 언어는 이미 학교의 연구실에서 나와서, 산업 현장의 중요한 구석에서 맹활약을 해오고 있다. 이 시리즈에서 소개할 nML이라는 언어는 그런 류의 언어들에 대해서 우리가 내놓을 수 있는 대표선수이다. ML이라는 언어계열의 한국 사투리쯤으로 생각해도 좋다. 다시 이 섹션의 본래 논지로 돌아와서, 사실, 지금까지 300년 이상 동안 수학이라는 언어가 사용한 서술 방식이 바로 값중심의 프로그래밍이었다. 수학에서 사용하는 모든 연산은 값을 만들 뿐이지 만든 값을 바꾸지 않는다. 새로운 값을 계산하는 것 뿐이다. 어느 수학책의 한 페이지에서 따온 다음의 단락을 보자: ``V를 (interior A) U f(W) 라고 하자. 그러면 V U (interior W) = f(A) 가 사실임을 알 수 있다.'' 여기서 첫 문장에 나타나는 interior A가 A가 가지는 값을 변화시키는가? 그래서 두번째 문장에 나타나는 A는 처음의 A와 다른것이던가? 그렇지 않다. A가 가지는 값은 변하지 않는다. interior A는 A를 가지고 정의되는 어떤 새로운 값을 지칭할 뿐이지 A를 건들지는 않는 것이다. f(W)라는 연산도 마찬가지다. W가 그 연산에 의해서 값이 변하는 것이 아니다. 첫문장에서나 두번째 문장에서나 W는 같은 값을 가질 뿐이다. 이러한 값중심의 서술방식이 수학(그리고 모든 과학) 분야에서 사람들끼리 소통하는 기본적인 프로그래밍 언어로 유구하게 이용된 이유는 뭘까? 그 이유는, 간단하고 편리해서이다. 간단하므로 편리한 것인데, 이것은 수학이나 과학이 성공한 중요한 인프라이다. 수학의 프로그램(수학의 논증들)은 그것이 옳고 그른지를 확인할 수 있을 때에만 생명이 있다. 옳고 그른지를 확인하기 편리하려면 서술하는 언어가 간단해야만 한다. 그렇게 간단하게 하는 데 기여한 언어의 주요 성질이 바로 값중심으로 프로그램하기인 것이다. 그렇다면, 컴퓨터 프로그램을 짜는 우리가 수학자들을 따라가야 할 이유는 무엇인가? 컴퓨터 소프트웨어는 수학의 프로그램에서와 똑같이, 그 참/거짓을 판명해야 하는 필요성이 명백해지고 있기 때문이다. 수학에서 프로그램의 참/거짓을 판명하는 것이 수학의 존재와 발전의 근간이었듯이, 컴퓨터 소프트웨어의 존재와 발전의 근간은 이제 프로그램의 참/거짓을 판명하는 기술이다. 프로그램이 옳고 그른지를 판명하는 것은 다름아니라 프로그램이 생각대로 작동할 지 안할 지 를 확인하는 것이다. 프로그램이 생각대로 작동한다는 것은, 프로그램이 버그없이 실행된다는 것을 뜻한다. 작성한 프로그램이 버그없이 실행될 지를 미리 자동으로 확인하는 기술, 이 기술을 달성하는 그룹이 앞으로 소프트웨어 발전의 헤게모니를 차지하게 될 텐데, 이 기술이 꽃피는 땅은 값중심의 프로그래밍 언어로 짜여진 프로그램들이 될 것이다. 수학의 참/거짓을 효과적으로 소통시켰던 언어가 값중심의 언어였다는 사실이 이 주장을 떠받치고 있다. 프로그램이 버그없이 실행될 지를 미리 자동으로 확인해 주는 기술이 왜 중요하고, 지금까지의 연구성과들이 어디까지 와 있고, 값중심의 프로그래밍 언어, 특히 이 시리즈에서 소개할 nML이라는 언어는 이 맥락에서 무슨 역할을 하는지에 대한 자세한 내용은 다음호에 계획되어 있으므로 그때로 미루기로 하고(간단한 글은 여기를), 다시 우리의 본론으로 돌아가자. 값중심의 프로그래밍은 비싸지 않다값중심의 프로그래밍을 지원하려는 데 걱정되는 비용이 혹시 있지 않을까? 값중심 프로그래밍의 핵심은, 만들어진 값은 변하지 않는다, 이므로, 새로운 값을 만들때 새로운 메모리를 소모해야 하는 게 아닐까? 이 추측이 맞지 않은 이유를 구체적으로 살펴보면서 이번 첫 회를 마무리 하자.값중심의 프로그래밍이 계산자원의 낭비를 오히려 막을 수 있는 이유는, 값중심의 프로그래밍의 핵심에 있다. 만들어진 값은 변하지 않는다, 는 핵심 덕택에, 항상 안심하고 이미 있는 값들을 공유할 수 있게된다; ``철수야, 9번 버스로 통학하는구나. 너 통학하면서 9번이 다른 노선을 운행하도록 바꾸지 않을거지? 나도 않바꿔. 그래, 같이 9번 버스로 통학할 수 있겠구나.'' 값을 만드는 시간은 어떤가? 공유하므로 값을 반복해서 다시 만드는 시간이 줄어든다. 구체적인 프로그램으로 이야기해 보자. 예로 들었던, 정수들의 집합을 계산하는 프로그램을 생각해 보자. 정수의 집합을 구현하는 방법으로 이진 탐색 트리(binary search tree)를 이용한다고 하자. 이 방법은 집합의 원소들을 두갈래로 갈라지는(binary) 가지구조(tree)위에 특별한 방식으로 분포시켜서 원소를 찾기가(search) 빨라지도록 하는 것이다. 특별한 방식의 분포란, 갈라지는 지점(node)에 있는 원소는 항상 그 왼편에 매달린 모든 원소들보다 크거나 같고 오른편에 매달린 원소들 보다 작다. 예를들어, 집합 {1,2,3,5,6,7}은 [그림 7]과 같이 표현되는 것이다. 그러한 조건 덕택에 어떤 원소를 찾는데 데 필요한 시간은 원소들의 총 갯수 N이 아니라 log N(트리의 꼭대기에서 아래로만 내려가는 한 개 경로의 길이) 만큼만 필요하게 된다. 새로운 원소를 넣을 때에도, 넣을 위치를 찾아가야 하므로 log N의 시간이 필요하다.
자 이제 따져보도록 하자. 새로운 원소를 추가해서 새로운 집합을 만들어 내는 경우를 따져보자. 우선 프로그램에서 두가지 경우가 있을 수 있겠다. 새로운 집합을 만들면 예전 집합과 새로운 집합들을 모두 유지해야 하는 경우와, 항상 새롭게 만든 집합만을 사용하고 예전의 것은 버려도 되는 경우.
마치면서값중심의 프로그래밍(value-oriented programming)은 기존의 물건중심의 프로그래밍(object-oriented programming)과는 다른 생각의 틀을 제공한다. 물건(object)을 만들고 변화시키는 과정을 프로그램으로 작성하는 것이 아니고, 값(value)을 정의하고 계산하는 과정을 프로그램으로 꾸미도록 한다. 물건과 값의 차이는, 물건은 변하지만, 값은 변하지 않는다는 것이다. 항상 변화하는 물건을 생각하면서 프로그래밍 하는 복잡함 대신에, 프로그램은 값을 계산하고 정의하는 것 뿐이라는, 우리가 사실 중고등학교 수학에서 익숙하게 사용하던 쉽고 간단한 프로그래밍 스타일인 것이다.사실 이 자연스러운 개념은 지난 300년이상 수학(과학)의 발전을 소통시켰던 간편한 언어 인프라였고, 컴퓨터 소프트웨어의 발전을 위해서도 이러한 개념을 갖춘 언어가 사용될 필요가 있다. 우리가 이미 익숙한 바 있는 이러한 프로그래밍 언어의 개념이 지금까지 묻혀졌던 것은, 컴퓨터에서 그 개념을 효과적으로 지원하는 방법이 없었기 때문이다. 하지만, 이제는 그러한 자연스럽고 간단한 프로그래밍 개념을 효과적으로 지원하는 언어들이 이미 현장으로 나오기 시작했다. 값중심의 프로그램들은 실행 비용이 많이 드는 건 아닐까 염려할 필요는 없다. 전통적인 컴파일러 기술들이 에셈블리 프로그래밍을 만족스럽게 대체시켰듯이, 값중심의 프로그래밍 언어를 구현하는 새로운 컴파일러 기술들은 이미 그러한 염려를 기우에 가깝게 만들어 놓았다. 문제는 기존의 프로그래밍 방식의 사회/경제적 관성을 어떻게 거스르냐는 것이다. 그것을 거스르는 해커들, 이미 짜여진 매트릭스를 거슬러 새로운 프로그래밍의 세계를 확인하고 싶어하는 네오(영화 [매트릭스]의 주인공) 들이 나설 무대는 준비되어 있다. 이쯤해서 이번 첫회의 내용을 마치도록 하자. 다음호에서는, 이 시리즈가 다루기로한 nML이라는 값중심의 프로그래밍 언어가 컴퓨터 소프트웨어의 발달과정에서 어느 위치에서 어떤 역할을 하도록 고안되고 있는지를 살펴보도록 하겠다. 그렇게 두 회의 글을 통해서 nML을 보는 우리의 안목을 준비한 후에, 3회 부터는 구체적인 nML 프로그래밍의 세계로 여행해보도록 하자. |