티스토리 뷰
Tool. 도구. 인간이 무언가 원하는 결과를 얻기 위해서 동원하는 것. 우리의 아득한 조상님들이 나무를 자르고 사냥을 하기 위해 갈고 던지고 꽂았던 돌덩어리들부터 시작해서 내가 출근하자마자 제일 먼저 실행하는 이클립스에 이르기까지, 인간을 인간답게 만들어주는 것이자 동시에 우리가 다른 동물들에 비해서 눈부신 발전을 이루게 해준 가장 큰 원인 중 하나. 도구를 쓰는 동물이 인간만 있는 것은 아니지만, 인간을 제외한 그 어떤 동물들도 이클립스 같은 도구를 상상하지 못 을 것 같다.
Type. 타입. 일정한 기준으로 나누어진 분류. 세상의 모든 개념들은 기준에 따라서 하나로도, 두 개로도, N개로도 구분할 수 있다. 학교에서 대수학(Algebra)을 배울 때였는지 정수론(Number Theory)을 배울 때였는지 하여튼 Classfication이라는 개념을 배운 적이 있었는데, 지금은 기억도 잘 나지 않지만 숫자들은 무언가 기준에 따라 분류했던 것 같았다. 왜 우리는 공대인데 공업수학을 안 배우고 이런 걸 배울까 한탄하던 와중에 익숙한 개념이 나와서 반가웠던 것 같았다. 시스템을 개발하는 것은 결국 세상에 존재하는 개념들을 논리적으로 바꾸는 일이고, 이를 위해서 개발자들은 가장 먼저 세상에 있는 사물들, 사람들, 개념들을 일정한 기준에 따라서 분류하여 정의하는 것부터 시작한다. 이를 보통 클래스(Class)라고 부르는데, 자바에서는 정적인 개념이 아닌 동적인 행동에 해당하는 개념 - 혹은 무언가 할 수 있다는 가능성을 인터페이스(Interface)라는 형태로 정의하여서 사용하고, 잘 알려져 있지는 않지만 클래스와 인터페이스를 묶어서 타입(Type)이라고 부른다.
Action. 행동. 원하는 결과를 얻기 위해서 수행하는 움직임. 돌덩어리를 던지는 것부터 시작해서 내 눈 앞에 있는 키보드를 집어던지는 것까지 세상에는 수많은 행동들이 존재한다. 거기에는 어떠한 결과를 기대하면서 시도하는 유의미한 행동들도, 딱히 결과도 과정도 시작도 중요하지 않은 무의미한 행동들도 있다. 프로그래밍에서는 이러한 행동들을 결국 함수의 형태로 표현하는데, 이러한 함수들을 구조화시키기 시작한 것이 객체지향 프로그래밍의 시작이 아니었을까 싶다. 객체지향 프로그래밍이 등장하기 전의 구조체(Structure)들과 객체(Object)의 가장 큰 차이는 행동을 할 수 있느냐 없느냐라고 볼 수도 있으니까.
Tool이 뭔지도, Type이 뭔지도, Action이 뭔지도 알 것 같았다. 내가 각각 단어들의 뜻을 모르는 것은 아니라는 사실을 확인하고 화면을 다시 들여다봤다. 화면에는 getToolTypeAction 이라는 글자가 떠있었다. 굳이 원천을 따지자면 내가 입력한 글자이기는 한데 정작 저 글자를 쓴 내가 저게 무슨 뜻인지 감을 못 잡고 있다는 사실이 부끄러웠다. 굳이 변명을 하자면 이클립스가 워낙 성능이 좋아서 에디터에 get만 써도 현재 상황에서 내가 가져올 수 있는 모든 가능성을 자동으로 제시해줬고, 나는 그중에서 가장 적당할 만한 것을 키보드나 마우스로 선택만 하면 되었다. 내가 선택한 함수가 어떤 입력을 받고 어떤 출력을 하는지를 확인하는 것은 그다음 문제였고, 보통은 함수의 이름에서 유추되는 입력을 받고 함수의 이름에서 유추되는 동작을 하고 함수의 이름에서 유추되는 결과를 돌려주었다. 문제는 함수의 이름에서 유추할 수 있는 것이 별로 없었다는 것이었다.
get Tool,Type,Action 이라고 해석하면 맞을까. 도구와 타입과 행동 사이에는 별 연관성이 없을 것 같았다. 그렇다면 저 3가지를 가져오라는 함수로 생각하면 편하지 않을까. 그런데 프로그래밍 이론을 떠나서 수학적인 정의에서도 함수는 다수의 입력을 받을지언정 결과는 무조건 하나만 돌려준다. 프로그래밍에서의 함수들도 마찬가지였다. 결과를 반환하지 않는 함수는 있을지언정 두 개 이상의 결과를 반환하는 함수는 없다. 굳이 Tool, Type, Action을 모두 반환하고 싶으면 계산하라고 전달받은 인자에 변형을 가하는 몹쓸 짓을 하거나, 결과를 하나로 묶어서 포장한 다음에 반환해줘야 되었다. 쇼핑몰에서 묶음배송하듯이. 그리고 이 함수는 int를 반환했다. Integer의 줄임말인 int는 -21억에서부터 +21억 정도 되는 숫자 중 하나를 표현한다. 이러한 숫자라든지 참, 거짓 처럼 절대적이고 수학적인 진리로 표현될 수 있는 데이터들을 원시 타입 (Primitive Type)이라고 부르는데 이러한 타입들이 가지고 있는 특성들 중에 흥미로운 특성이 상당히 많지만 그중에서 지금 나에게 가장 중요한 것은 스카이넷이 세상을 지배하더라도 int 형은 단 하나의 숫자만 표현한다는 점이다. Tool, Type, Action의 3가지 의미를 전달할 수 있을리가 없었다.
아, 잠깐. 전달할 수 있을 리가 없지는 않았다. int형은 32비트 정수니까. 만약에 Tool, Type, Action이 2진수로 표현되어서 각각을 AND 연산으로 이어서 반환한다면? int 형은 32개의 0과 1로 표현될 수 있으니까 Tool, Type, Action은 대충 10개식의 비트를 사용할 수 있다. 최상위 10개 비트로 Tool을 표현하고 그다음 10개 비트로 Type을 표현하고 그다음 10개 비트로 Action을 표현하면 1024개의 Tool, 1024개의 Type, 1024개의 Action, 그리고 이것들이 가지는 10억개의 조합을 하나의 int에 담아서 반환할 수 있다. 이를 검사하기 위해서는 비트 마스크를 OR 연산으로 덮어서 연산하고 적당히 시프트 해주면 하나의 숫자에서 3개의 값을 꺼내오는 마술을 부릴 수 있다. 객체지향 프로그래밍이 발달하고 나서는 거의 안 쓰는 기법이지만, 만약에 이 함수를 개발한 사람이 매우 레트로한 혹은 변태적인 취향이라면 이런 식으로 결과를 반환할 수도 있겠다는 생각을 했다.
이러한 가정을 하고 열심히 테스트를 해봤다. 분명 결과를 이진수로 바꿔서 해독하면 유의미한 데이터가 나올꺼야. 그 잠시간의 기대에 마음속이 아주 편해졌다. 프로그램을 수정하고 실행할 때만 해도 '이게 정말 비트 연산으로 구해야 되는 거면 대박인데. 이렇게 만든 것도 대박이고 이걸 추리해서 답을 구한 나도 대박이고.'라는 생각에 기분이 매우 좋아졌다. 그리고 결과가 이진수로는 전혀 의미 없는 값임을 확인하면서 기분은 2의 보수를 더한 것 마냥 반전되었다.
키보드를 집어 던지고 싶은 기분이 다시 드는 것을 간신히 진정시키고, 처음부터 다시 생각해봤다. 내가 가지고 있는 정보가 얼마나 될까? 이 함수가 int를 반환한다는 것은 사실 사전에 어딘가에 정의된 상수를 반환하고 있을 가능성이 가장 컸다. 요즘 프로그래밍이라면 그렇게 생각하는 것이 비트연산을 추리하는 것에 비해서 21억배는 자연스러웠다. 그렇다면 그 상수는 어디에 정의되어 있을까? 옛날에는 상수들만을 가지고 있는 별도의 타입을 정의하는 것이 유행이었을 때도 있었다. 하지만 이 함수는 분명 만들어진지 1년이 안 된 함수였고, (정확히 말하면 릴리즈 된지 2주도 안 된 함수였다.) 요즘 프로그래밍에서는 그 함수가 반환하는 상수들은 그 함수를 정의하고 있는 클래스에 정의하는 것이 일반적인 유행이었다. 그래서 무작정 이 클래스에 정의된 상수들이 있나 싶어서 컨트롤 키와 스페이스 키를 같이 강하게 눌렀고, 거기에는 ACTION_NONE 부터 ACTION_STROKE, ACTION_ERASER 등등 이 함수가 반환할 것으로 추정되는 상수들이 분명히 정의되어 있었다. 아무리 찾아도 없었던 편지가 알고보니 우체통에 꽂혀있었던 것 처럼.
프로그램을 다시 돌려봤고, 이 함수가 저 상수들을 반환하고 있다는 확신을 가질 수 있었다. 펜을 선택하니까 ACTION_STROKE를 반환했고, 지우개를 선택하니까 ACTION_ERASER를 반환했으니까. 그럼 이 함수는 Tool이랑 Type은 반환하지 않고 Action만 반환하는 것일까. Tool과 Type은 어디에 있을까.
문득 함수를 호출하고 있던 줄에 다시 눈이 갔다. 함수는 f(x) = 10 처럼 전달받은 값이 아무 의미가 없어서 전달을 받지 않는 함수도 있고 f(x) = x + 1 처럼 전달받은 값이 의미가 있어서 특정한 인자를 전달받는 함수가 있었다. getToolTypeAction은 무언가를 전달받는 함수였고, 나는 거기에 무언가를 전달했었다. getToolTypeAction(TOOL_SPEN) 이렇게. TOOL_SPEN이라니. 내가 저걸 언제 쳤지? 가만히 생각해보니까 get까지 치고 ToolTypeAction을 자동 완성 시키고 나서 안에 전달할 인자를 써넣어야 될때도 뭘 써넣을지 몰라서 자동완성 시켰다가 무의식중에 가장 적당한 상수를 골라넣었던 것 같았다. 그럼 저 함수는 뭘 전달받는걸까 싶어서 TOOL_SPEN 이라는 인자를 지우고 다시 자동완성을 시켜봤다. 이클립스는 다시 한 번 이 함수를 완성시키기 위해 전달해야 되는 인자의 이름, 그러니까 함수의 정의를 화면에 뿌려줬다. 화면에 표시된 함수의 시그니쳐에는 int getToolTypeAction(int toolType) 이라고 분명히 써있었다.
애드가 앨런 포우는 과도한 영리함 만큼 현인들을 불편하게 만드는 것은 없다고 그랬는데 이건 과도한 영리함이 아니라 과도한 멍청함과 자만심이 바보 같은 나를 불편하게 만든 것이 아닐까 라는 생각이 들었다. 함수가 반환하는 숫자들이 뭘지 고민하기 전에 함수 정의만 다시 한 번 확인했어도 명쾌하게 해결 되는 것이었는데. 수수께끼는 모두 풀렸다. getToolTypeAction은 getAction of ToolType 이었고, ToolType을 전달 받아서 Action을 반환한다. 멍청함에 한없이 가라앉는 듯한 기분이 들어서 '사실은 getAction(int ToolType)이 맞는 정의야'라고 궁시렁 거리기는 했지만 그래도 하지 않아도 될 삽질을 너무 깊게 한 것 같은 느낌이 들었다.
이제 모든 문제가 풀렸다. getToolTypeAction 함수는 현재 내가 쓰고 있는 도구가 어떤 동작을 할지, 그러니까 그림을 그릴지 지워버릴지 선택을 할지 등등을 반환해준다. 그럼 내가 지우개를 쓰기 위해서는 setToolTypeAction 함수에 ACTION_ERASER를 전달하면 되는것이었다. get 함수가 반환하는 값을 set 함수에서 세팅해주는 것은 매우 유서깊은 규칙이었다. 지우개 버튼에 이벤트 리스너(Event Listener)를 추가하고 setToolTypeAction(ACTION_ERASER) 구문을 추가하고, 실행을 했다. 이론상 이건 100% 동작한다고 확신하면서.
화면에 무언가 떴을 때 일반적인 인간이 그것을 인식하고 최초의 반응을 내는 시간이 대략 500ms 정도라고 하니, 확신은 0.5초 만에 깨졌다. 실행이 되지 않았다. 아까 키보드 집어 던지려고 움찔거릴때 노트북에 연결해둔 테스트용 태블릿의 케이블이 빠진것인가 싶어서 고개를 숙이려고 하는데 화면에 떠있는 선명한 빨간 줄이 보였다. 초등학교 시절에 맞춤법이 틀릴때마다 선생님들이 빨간펜으로 지적을 해주는 문화가 서양에도 있는지는 모르겠지만, 서양에서 만들어진 이클립스는 내가 작성한 코드가 상상력이 빈곤한 컴퓨터가 보기에도 터무니 없이 틀렸을 때 빨간 줄을 그어서 표시해준다. 그 빨간줄은 내가 방금 입력한 setToolTypeAction 함수에 그어져 있었다.
인간들은 어리석어서 끊임없이 같은 실수를 반복한다고 하니까, 어리석었던 나를 반성하면서 다시 한 번 함수의 정의를 확인해봤다. setToolTypeAction(int toolType, int action) 이라는 시그니쳐가 표시되었다. 아, 함수에 2개의 인자를 전달해야 되는데 하나만 전달했으니까 컴퓨터가 보기에도 한심했구나. 그럼 2개를 전달하면 저 빨간줄이 사라지겠구나. 그런데 뭘 전달해야 되는거지?
시험삼아서 getToolTypeAction에서 toolType을 TOOL_SPEN이라고 전달했으니까 setToolTypeAction에도 TOOL_SPEN과 ACITON_ERASER와 마음을 담아서 전달해봤다. 고백 후 대답을 듣기 까지의 시간처럼 실제로는 짧게 느껴지지만 심정적으로는 영원처럼 느껴지는 시간이 지나고 화면에 프로그램이 떴고, 지우개 버튼을 누르고 펜을 움직여봤더니 실제로 지우개가 동작했다. 성공이었다.
왜 성공했지? 도대체 저 TOOL_SPEN이 가지는 의미가 뭐지? 저기에 다른 것도 들어갈 수 있나 싶어서 확인해봤더니 TOOL_FINGER도 있고 TOOL_MOUSE도 있었다. 왜 화면에 그림을 그릴때 ACTION_STROKE를 전달하고 지우개를 사용할 때 ACTION_ERASER를 전달하는 것으로 끝나지 않고 TOOL_어쩌구를 같이 전달해서 세팅하고 TOOL_어쩌구를 같이 전달해서 현재 상태를 가져와야 되는 것일까. 펜으로 선을 그리나 손가락으로 선을 그리나 다 같은 선인데.
그 생각이 궁금했다. 따지고 보면 setAction(int action) 이어야 되고, getAction() 이어야 되는 함수들이었다. 내가 만들었다면 분명 그렇게 만들었을 것 같았다. 왜 저기에 사용하는 도구를 전달해서 세팅을 하고 값을 확인해야 되는 것일까. 도대체 이 함수를 만든 사람은 무슨 생각으로 이 함수들을 만들었을까. 그것이 바르다 바르지 않다의 문제가 아니었다. 이 함수들이 가지고 있는 의미가, 도대체 여기에는 어떤 법칙이 있고 어떤 규칙이 있으며 어떤 생각으로 어떤 의도로 어떤 꿈을 가지고 이 함수들을 만들어서 세상에 내보냈을지가 궁금했다.
어쨌든 프로그램은 의도대로 돌아갔다. 이해하지 못하는 코드가 포함되어 있다는 점에서 매우 기분이 나쁘기는 했지만 어쨌든 목표했던 기능들은 다 만들었으니 집에 가도 좋을 것 같았다. 짐을 싸서 도망치듯이 퇴근하면서 계속 생각해봤다. 이 함수를 만든 사람도 나처럼 야근을 했을까. 이 함수를 만든 사람도 나와 같은 고민을 했을까.
세상은 알 수 없는 것 투성이였다. 내일은 집에 일찍 갈 수 있을지 없을지도, 이거 정말 시간내에 다 개발 할 수 있을까도, 지하철도 끊기고 버스도 몇십 분 뒤에 올 것 같은데 택시 안 타고 걸어가면 내일 많이 피곤할까 하는 점도, 내 몸과 꿈을 담고 있던 부서를 하루 아침에 없애버린 회사의 생각도. setToolTypeAction 이 전달받는 toolType이라는 인자의 의미도,
나는 정말로 당신의 생각을 알고 싶었다. 그 결과는 반항하지 않고 받아들일테니, 다만 이유라도 알려달라고 하고 싶었다. 사실 정말 단순하고 쉬운건데 내가 멍청해서 잘 모르는 것이라면 멍청이를 위해서 조금 더 친절을 베풀어 주면 안되냐고 물어보고 싶었다. setToolTypeAction이라는 함수의 설명이 달랑 set action for tooltype 이라는 건 너무한 것 아니냐고 물어보고 싶었다. 반대로 내 생각은 궁금하지 않냐고 물어보고 싶었다. 막상 나는 그 당신이 누군지도 모른다는 생각을 하니 이 모든 상황이 정말 웃긴 것 처럼 느껴졌다. 그럻게 짧은 생각은 스러져갔고, 지금은 어떻게 집에 갈지를 고민하는 것이 가장 현실적이고 현명한 일이라는 생각이 들었다. 세상은 알 수 없는 것 투성이 이기도 하지만, 어쩔 수 없는 것 투성이 이기도 하니까.
'에세이' 카테고리의 다른 글
개발의 현황 (0) | 2015.09.23 |
---|---|
전역변수 Apocalypse (0) | 2015.03.28 |
Last man standing (0) | 2013.11.16 |
근로자의 날 (0) | 2013.05.20 |
private war (0) | 2013.04.15 |