1. 들어가며
요즘 나는 블로그 댓글 보는 재미로 산다. 사람들의 칭찬 한마디 보는게 이제 8개월된 딸내미의 방긋대는 얼굴만큼 흐뭇하다. ‘이러다 너드들 사이에서 강풀 (만화가)되는거 아냐?, 우훗’, 상상도 해보다가 이내 짧은 글심이 떠올라 좋은 주제나 찾아야지 생각하게 된다. 이번에 풀고 싶은 주제 역시 지난번처럼 신문기사를 읽다가 떠올랐다. 안철수님의 “하드웨어 대응 만으로는 승산없다” 라는 기사의 한 부분에 이런 언급이 나온다:
“얼마 전 하드웨어·소프트웨어·인터넷 서비스 등으로 분류해 IT업계 트렌드를 설명했더니 대기업 전자회사 최고기술책임자(CTO) 한 분이 소프트웨어는 하드웨어를 구동시키는 하나의 부분이므로 분류가 잘못됐다고 지적하더라.”
“소프트웨어가 하드웨어를 구동 시키는 하나의 부분”이다. 왠지 울컥하다. 그래, 하드웨어로 성공한 우리나라에서 소프트웨어의 역할은 그게 맞다. 빠른 CPU, 넓은 메모리에 광활하고 밝은 디스플레이, 미려한 외관으로 장식된 하드웨어를 소프트웨어는 “구동” 시키고 있다. “구동”이 주는 어감….그렇지, 소프트웨어는 뛰어난 하드웨어가 돋보이도록 낮은곳에 숨어 봉사하고 있다. SW에 큰 관심없는 일반인들에겐, 형체없는 소프트웨어를 설명하는데 이것보다 더 좋은 표현이 있을까?. 얼마전 SW벤쳐에서 일하는 내게 아버지가 “너희 회사 공장은 어디있냐?” 하신적도 있다 (공장은 마음속에 있어요 아버지). 아마도 “하드웨어 나고, 소프트웨어가 나오는 거다” 라는게 상식처럼 되어버린 세상인데, 근데, SW로 온가족이 먹고 살아서 그런가, 왜 나는 이 기사에 울컥하고, 뜨거운 것이 솟아오르는 건가?…그렇게 고민하며 주말을 보냈다.
나는 이 에세이에서 그 반대의 이야기를 하고싶다. “소프트웨어가 하드웨어의 애비다” 라고 외쳐본다. 여기에서 나는 소프트웨어-본질-의 역사와 하드웨어-우연-의 역사에 대해서 소개하고, 역사가 우리 프로그래머들에게 던지는 의미에 대해 쓴다. 이 글의 큰 줄거리는 지난 블로그에서도 소개했던 [1] 에서 영감을 얻었다. 그리고 좀 더 깊게 들어가는 증명은 컴퓨터 이론 텍스트북 [2,3] 에서 찾을 수 있다 (뭐, 증명이라고? — 그렇다. 심하게 재미 없을수도 있다).
2. 라이프니치의 꿈
계산과 논리는 인류가 기록물을 남긴 시절 이전부터 존재했을거다. 1+1=2 라는 사칙연산말고도, 일련의 논리적 절차를 거쳐서 결과를 보이는 계산 — 즉 알고리즘– 에 대한 인류의 자각은 아주 먼 옛날(bc)의 기록에서도 찾을 수 있다 [4]. 비 전공자에게 알고리즘은 좀 낯설수 있으니 예를 들면서 시작하자.
문제: 주어진 임의의 숫자 나열 중 가장 큰 숫자를 찾아라
1) 제일 큰 숫자를 저장할 공간을 a 라고 부른다.
2) 제일 처음 숫자를 a에 집어 넣는다.
3) 모든 수에 대해서 a와 비교해, a보다 더 큰 숫자가 나오면 a에 집어 넣는다.
4) a를 출력한다.
엄청 간단하다. 한단계 이상의 논리적 절차를 걸쳐서 결론을 냈으니 아무튼 알고리즘이다. 조금 더 복잡한 알고리즘을 소개하자면 binary search같은것이 있겠다.
문제: 순차적으로 정렬된 숫자들 가운데서 숫자 K를 찾아라
1) K와 중앙에 위치한 수를 비교한다.
2) 비교한 결과 같을 경우, 찾았음을 알리고 종료한다.
3) K가 작을 경우엔, 처음부터 중앙 바로 전까지의 숫자를 가지고 1)을 반복한다.
4) K가 클 경우엔, 중앙 다음부터 마지막까지 숫자를 가지고 1)을 반복한다.
이같은 알고리즘의 기록은 bc.300 년전 이상으로 올라간다 [4]. 일련의 논리적 절차를 거치는 계산이 알고리즘인것은 알았지만, 17세기까지 아직 절차를 어떻게 표현할 것인가는 인식하지 못했다. 현대의 프로그래밍 언어가 바로 그런 역할을 한다.
그런데 역사상 최고의 수학자중 한명인 독일의 라이프니츠(1646-1716)는 그 옛날 이런 발칙한 상상을 시작한다.
“계산과정(알고리즘)을 몇가지 글자로 표현할 수 있다면, 그럼 어쩌면 세상 모든 알고리즘에 항상 답을 주는 마법과 같은 기계(machine)를 만들수 있지 않을까?”
다시 말해서, 알고리즘을 정해진 언어로 표현해 낼 수 있다면, 그럼 우리는 그 언어로 써내려간 스토리를 마법의 공식에 집어 넣을 수 있지 않을까? 그리고 그 공식은 즉각 답을 내어준다니, 라이프니츠의 상상은 진정 대인배다웠다. 프로그래머라면 금방 알것인데, 라이프니츠의 상상은 우리가 매일 하는 그짓이다. 프로그래밍 언어로 알고리즘을 써내려가고, 이를 컴퓨터에게 주면, 컴퓨터는 항상 답을 준다. 그런데, 그가 발칙한 이유는 이 단어, “항상 (Always)”, 에 있다. 정말 모든 질문에 컴퓨터는 정답을 이야기 하나? 이 질문이 주는 깊이는 대단해서, 참으로 증명되면 적절한 데이터를 주었을때 “신이 존재하는가?” 의 질문에도 답을 할수 있다는 뜻이다. 이에 감명받은 어떤 신학자는 수학 공식으로 신의 존재를 증명하려는 잉여행동까지 감행한다.
이를 라이프니츠의 Dream Machine 이라고 부른다. 그가 상상한 마법의 기계(Machine)는 물리적 기계(하드웨어)가 아닌 무형의 “공식” 혹은 “알고리즘” 이다. 그당시 상상으로는 이 마법 레서피가 적힌 책을 들고 있는 사람에게 알고 싶은 질문을 (프로그램 언어로)써서 주면 그 사람이 마법 레서피로 주어진 문제를 계산해 결과를 가르쳐주는 것이다. 컴퓨터는 컴퓨터인데, 사람이 계산하는 컴퓨터라니, 엄청 느렸을 거고 담당자의 기분 따라서 결과가 달라졌겠지?
어쨌든, 라이프니츠는 인류가 “Let us calculate!” 이렇게 외치는 순간이 곧 올 것이라 믿었다. 라이프니츠 이후, 불(Boole), 프뤠게(Frege), 칸토(Cantor), 힐버트(Hilbert)로 이어지는 논리학, 수학의 거장들이 하나 하나 문제 해결을 위한 단초를 제공하게 된다. 그들은 이 문제에 대해, “Yes: 그래 그런 마법의 공식은 존재해!”, 혹은 “No: 그런 마법 공식은 존재할 수 없어!”, 이 둘 중 한가지를 증명해내기 위해 평생을 잉여짓으로 보낸다. 그리고 20세기에 와서야 우리는 결론에 도달했다.
3. 튜링의 잉여짓
수백년을 이어온 이 질문은 영국의 젊은 천재 수학자 튜링 (Alan Turing, 1912-1954)[6]에게도 최고의 도전거리였다. 하지만 안타깝게도 그 보다 앞서 이 질문에 답을 한 또 하나의 천재 수학자가 있었으니 그가 바로 오스트리아 출신 괴델 (Kurt Godel)[7]이다. 괴델은 25세 되던 1931년 Incompleteness Theorem 을 발표하고, 라이프니츠의 꿈 – Dream Machine – 은 존재할 수 없음을 증명했다. 즉 세상엔 답을 할 수 없는 어떤 문제 (질문)가 존재하는 것이다. 어쩌면 당연하다. 어떻게,”엄마 좋아, 아빠 좋아?” 혹은 “짜장이 갑이냐, 짬뽕이 갑이냐?” 이런 질문들에 답을 할 수 있겠는가?
괴델의 완벽한 증명에도 불구하고 튜링은 왠 똥고집이었는지, 자신만의 사고로 Dream Machine이 존재할 수 없음을 증명하기 시작했다. 잉여짓의 좋은 예다. 그 결과가 컴퓨터 학과 학생들의 헬게이트를 열어버린 튜링 머신이다. 여기서 나도 뭔 똥배짱인지는 모르지만, 튜링의 증명을 소개한다. 그동안 두편의 블로그로 쌓아온 “이해하기 쉽게 쓰는 블로거”의 이미지를 한방에 날려버릴 절호의 찬스다! 굳이 이런 짓을 하는 이유는, 이 증명안에 설명하긴 참 어렵지만, 심오한 진리가 있기 때문이다.
컴퓨터 프로그램은 가장 단순히 표현하면 위의 그림과 같은 일을 한다. 즉 프로그램 P는 주어진 인풋 데이터를 가지고, 질문이 참인지 거짓인지를 대답한다. 바로 이때, “어 근데 어떤 질문들은 참/거짓 말고 다른 대답을 하잖소?” 라고 물을 것이다. 예를 들어, 아까 설명한 최대값 찾는 알고리즘은 결과값이 숫자여야 한다. 하지만 그런 질문들은 쉽게 참/거짓으로 변환이 가능하다. 즉, 나열된 숫자에 대해서 “1보다 더큰 수 있냐?”, “2보다 더큰 수 있냐?” 이런 식으로, “아니오” 가 나올때까지 질문하는 것이다. 이것이 라이프니츠 전까지 존재했던 모든 알고리즘 혹은 논리적 사고의 가장 단순한 형태다.
우리들의 아버지 튜링은, Input, P, 와 T/F 결과값으로 이루어지는 이 단순한 형식을 신비하게 변형시킨다. 아래의 그림은 그의 Halting 프로그램을 표현 한 것이다.
이 프로그램은 특이하게 인풋으로 프로그램(P)과 데이터(I)를 모두 받는다. 그리고 내부에서 하는 일은 받은 P를 데이터 I를 넣어 돌리는것이다 (너드 언어로 에뮬레이션 한다). 그리고 나온 결과 값이 참일 경우, 거짓을 출력하고, 반대로 거짓일 경우 참을 출력한다. 그럼 이런 프로그램을 진짜 만들 수 있냐? 라는 질문이 나오는데, 조금만 생각해 보면 그리 어렵지 않다. 잠시 “너드” 모드로 들어가서 설명하자면:
– H라는 프로그램과 P라는 프로그램 모두 C 언어로 짠다.
– H는 내부에서 gcc 를 콜해서 P를 컴파일 한다. P의 바이너리가 나온다.
– Fork하고 execute해서 P를 돌린다. 데이터는 I를 넣어준다.
– 나오는 결과값 검사해서 반대를 출력한다.
여기까지 읽고 계신분들께 존경을 표한다. 갈길이 그리 멀지 않다. 여기서 한가지 이상한 짓을 해보자. 아래와 같이 H 프로그램의 인풋으로 H 프로그램 소스코드를 두번 넣는 것이다.
이 경우 H프로그램이 하는 일은 무엇일까? 다름 아니고 H프로그램 자신의 소스코드를 컴파일하고, 돌려서 결과를 반대로 출력하는 것이다. 그럼 위의 경우에 H 프로그램의 결과값은 무엇이 될수 있을까?
참: H가 참이 되려면 안에서 돌아간 H가 거짓이어야 한다…어?
거짓: H가 거짓이려면 안에서 돌아간 H가 참이어야 한다…어?
말이 안된다. H는 어떤 결과도 낼 수 없다. 다시 말해 H라는 프로그램은 존재 할 수가 없는 것이다. 바로 이것이 튜링이 라이프니츠의 Dream Machine을 반증하기 위해 만들어낸 존재할 수 없는 알고리즘 (Undecidable problem) 인 것이다.
4. 폰뉴먼과 우연한 하드웨어
과학에 2등은 없다. 튜링은 괴델보다 늦게 증명을 했으니 그는 루저였다. 그러나 튜링은 괴델과 함께 타임지의 20세기 100대 인물에 올라가 있고, 컴퓨터의 아버지라 불리고 있다. 매년 주어지는 컴퓨터의 노벨상을 튜링 어워드라 부른다. 튜링의 놀라운 업적은 증명과정에서 보여준 H라는 프로그램에 있다. 튜링 전에도 원시 형태의 컴퓨터들이 있었는데, 이것들은 기계나 전기를 활용하여 단 한종류의 알고리즘만을 구현하는 것이었다. 이를테면 아래의 사진은 튜링보다 100년이나 앞서 시도됐던 Charles Babbage의 초대형 미분방적 계산기 부속품이다. 오로지 미분방적식만 풀 수 있는 거대한 기계다.
그런데 튜링의 증명과정에서 보여준 H 프로그램은 그 내부에서 임의의 프로그램 P를 수행할 수 있다. 그는 어떤 형태의 프로그램 P든 간에 돌리고 결과값을 산출할 수 있는 H 프로그램을 어떻게 만들어 내는지를, 읽고 쓰기가 자유로운 테이프를 활용해서 보여주었고, 이를 우리는 Universal 튜링 머신이라 부른다. 어떠한 종류의 프로그램 (SW)이든 받아서 돌리고, 결과를 보여주는 어떤것, 왠지 컴퓨터의 냄새가 솔솔 나지 않는가?
이 아이디어를 처음 하드웨어로 구현한 사람은 바로 폰 뉴먼 (John Von Neumann) [8]이다. 폰 뉴먼은 20세기 최고의 천재로 불렸고, 별의 별 분야(사실 잘 모르니 이렇게 표현할 수 밖에)에 업적을 남긴 수학자였다. 그는 1945년, 튜링이 생각해낸 방식을 좀 더 구체화시켜서, 프로그램이 메모리에 저장되는 컴퓨터 EDVAC [5]의 컴퓨터 구조를 고안했다(너드언어로, 프로그램 카운터, 논리연산, 레지스터, 연산과 데이터 메모리 통합 고 따위것들이다). 그가 써내려간 구조를 하드웨어 천재들 ( John Mauchly and J. Presper Eckert)이 구현해 내는데, 이것 저것 잡다한 아날로그 전기부품을 다 써보다가, 우연히 TV등에 널리쓰인 진공관을 활용해 이런 괴물 컴퓨터를 만들어 내기에 이른다.
여담으로, 폰뉴먼은 낚아채기의 달인이다. 폰뉴먼은 튜링의 논문에서 아이디어를 얻었으면서도 자기 저서들에서 이를 언급하지 않았다. 또 함께 일했던 하드웨어 달인들의 영향을 무시하고 무명의 용사들로 만들어 버린 결과, 훗날 그들과 특허 전쟁을 치룬다. 괴델과 튜링 모두 타임지의 20세기 100인에 선정되었지만, 폰뉴먼은 대단한 업적에도 불구하고 선정되지 못했다. 어쨌든, 폰뉴먼의 구조는 70년이 지난 지금도 여전히 유효해서, PC, 타블렛, 스마트폰 모두 여전히 폰뉴먼 구조라 부른다. 다 알다시피, 이후 6-70년대 실리콘과 마이크로프로세서의 혁명으로, 컴퓨터는 인류에게 본격적으로 침투했다.
5. 결론
여기까지 써놓으니 읽는분들께 왠지 미안하다. “이따위 길고 지루한 역사 이야기만 하다니, 대 실망이다!” , 이런 원망이 들리는듯 하다. 내 얕아빠진 지식을 길게, 가까스로 풀어놓은 이유는…
“소프트웨어는 하드웨어를 구동시키는 하나의 부분 ”
나는 이 말이 진정 듣기 싫기 때문이다.
bc 300년전에도 존재한 유클리드의 알고리즘, 라이프니츠가 상상한 모든 질문에 대답해 주는 Dream Machine, 그리고 컴퓨터의 표본인 튜링의 Universal Machine 까지, 그 어떤 것도 하드웨어가 아니었다. 인간의 두뼘남짓 뇌에서 피어난 논리의 결과물, “지식(Knowledge)이란 무엇인가?” 이 질문에 인생을 걸었던 철학/과학자들의 피와 땀이 만들어 낸 결과물은 바로 소프트웨어다. (참고로 철학박사인 친한 형과 비슷한 대화를 나눈적이 있다. 그 형은 위에 언급된 모든 사람들을 알고 있었다.)
위 카툰처럼 우리의 소프트웨어와 프로그래머들이 받고 있는 대접이 너무 씁쓸하다. 소프트웨어는 우연의 산물 하드웨어를 보조해주는 또 다른 우연이 아니라, 태초부터 인간의 인간다움속에 내재돼있던 고귀한 창조물이다. 학부 1학년이 과제로 짜는 100줄의 코드도, 수백명 엔지니어가 함께 짜는 안드로이드의 100만줄 코드도 모두 동일하다. 주어지는 문제는 다르지만, 우리의 이 작은 뇌로 고도의 생각을 집중하고, 논리의 다리를 쌓아나가 목표에 다다른다. 우연한 하드웨어 (x86, 메모리 크기, 디스크의 속도)와 환경 (데드라인, 돈, 사회적 시선)의 제한에 둘려쌓여 있지만, 우리는 그 한계들마저 소프트웨어로 계산하고, 하나 하나 해결해 나가는 그 즐거움에 취해 산다.
“소프트웨어는 하드웨어를 구동시키는 하나의 부분 “
천하에 불효자들이나 지껄일 수 있는 소리일 뿐이다.
– 박상민 http://twitter.com/#!/sm_park
[1] The Universal Computer: The Road from Leibniz to Turing by Martin Davis
[2] Introduction to Automata Theory, Languages, and Computation, by John E. Hopcroft, et al.
[3] Introduction to the Theory of Computation, by Michael Sipser
[4] Euclidean Algorithm: http://en.wikipedia.org/wiki/Euclidean_algorithm
[5] EDVAC: http://en.wikipedia.org/wiki/EDVAC
[6] People of the century: Alan Turing (http://www.time.com/time/magazine/article/0,9171,990624,00.html)
[7] People of the century: Kurt Godel (http://www.time.com/time/magazine/article/0,9171,990621,00.html )
[8] John Von Neumann: http://en.wikipedia.org/wiki/John_von_Neumann