5. 관계가 의미를 만든다
데이터베이스에 orders 테이블이 하나 있다고 하자. 이 테이블의 각 행에는 주문 번호, 수량, 가격 같은 값들이 들어 있다. 그런데 이 행에서 의미를 바꾸는 열이 하나 있다. user_id라는 외래 키다. 이 숫자 하나가 없으면 주문은 수량과 가격만 덩그러니 남은 숫자 뭉치가 된다. 어떤 사용자가 무엇을 샀는지, 왜 이 주문이 존재하는지를 알려주는 것은 오직 users 테이블의 어느 행을 가리키고 있는가다. 주문의 의미 가운데 가장 중요한 부분은 주문 자체의 속성이 아니라 다른 테이블과 맺는 이 연결에 담겨 있다.
체스판 위의 나이트는 이 관찰을 더 극단적으로 밀어붙인다. 나이트를 나무로 깎든 플라스틱으로 찍어내든, 그 모양이나 재질은 게임에 아무 영향을 주지 않는다. 심지어 나이트를 잃어버려서 동전 하나로 대신 표시해도 게임은 멀쩡히 진행된다. 나이트를 나이트답게 만드는 것은 딱 하나, 어느 칸에서 어느 칸으로 이동할 수 있는가라는 규칙뿐이다. 이 말이 판 위의 다른 말들과 어떤 관계를 맺을 수 있는지가 정해지는 순간 나이트라는 정체성이 성립하고, 그 규칙을 걷어내는 순간 나이트는 그저 말 모양의 물체로 돌아간다. 재질도 색깔도 다 버려도 나이트는 나이트로 남지만, 이동 규칙 하나만 빼면 나이트는 사라진다.
이런 장면은 프로그래밍 곳곳에 흩어져 있다. URL 하나는 그 자체로는 문자열일 뿐이지만, 어느 서버의 어느 자원을 가리키는가라는 관계 속에서만 의미를 갖는다. 파일 경로도 마찬가지다. /home/user/notes.txt라는 이름은 그 파일이 어느 디렉터리 아래 놓여 있는가라는 관계를 그대로 옮겨 적은 것에 지나지 않는다. Git의 커밋도 다르지 않다. 커밋은 부모 커밋을 가리키는 해시를 함께 저장한다. 그래서 커밋은 혼자 존재하지 않고, 이전 기록과 이어진 관계 속에서 의미를 갖는다. 세 경우 모두 대상을 이루는 실체보다, 그 대상이 다른 대상과 어떤 관계를 맺고 있는가가 더 중요하다.
많은 경우 대상을 이해하는 가장 좋은 방법은 그 안을 들여다보는 것이 아니라, 다른 대상과 어떻게 연결되는지를 보는 일이다. 하지만 관계가 존재한다는 것만으로는 충분하지 않다. 프로그램은 그 관계를 실제로 따라가고 활용할 수 있어야 한다. 어떤 주문에서 사용자로, 어떤 커밋에서 부모 커밋으로 건너갈 수 있어야 한다. 프로그래밍 언어는 이 역할을 함수에게 맡긴다. 함수는 단순히 값을 계산하는 도구가 아니라, 하나의 대상에서 다른 대상으로 건너가는 다리다. 다음 화에서는 함수를 관계의 기록이자 통로로 다시 들여다본다.