9. 추상화는 무엇을 버리는가
자동차 핸들을 오른쪽으로 돌리면 차체가 오른쪽으로 방향을 튼다. 그 순간 핸들 축과 연결된 랙과 피니언 기어가 맞물리며 돌아가고, 타이로드가 좌우로 밀리며 앞바퀴의 각도를 조금씩 바꾼다. 하지만 운전하는 사람의 머릿속에는 이 기계 장치의 존재가 거의 없다. 핸들을 돌리면 차가 돈다는 사실 하나만 남아 있을 뿐이다.
이 무시는 게으름이 아니라 선택이다. 운전자는 랙과 피니언 기어의 잇수나 타이로드의 길이, 서스펜션의 기하학적 배치를 몰라도 핸들과 바퀴 방향 사이의 대응 관계 하나만 붙잡고 있으면 운전할 수 있다. 2장에서 같음의 기준을 정하는 행위는 개별 값들 사이에서 일어났다. 지금 벌어지는 일은 그 압축이 훨씬 더 큰 덩어리, 즉 수십 개의 부품과 그 상호작용 전체를 향해 일어난다는 점이 다르다. 복잡한 기계 장치는 핸들이라는 하나의 조작 아래에서 “돌리면 방향이 바뀐다”는 관계 하나로 모습을 드러낸다.
프로그래밍에서도 같은 일이 함수 하나마다 벌어진다. 7장과 8장에서 다뤘던 주문 객체에 getTotal()이라는 메서드를 하나 더 붙여 보자. 이 함수를 호출하면 수량과 단가를 곱하고, 할인 쿠폰을 적용하고, 세율을 반영하고, 필요하다면 환율까지 계산해서 최종 금액 하나를 돌려준다. 이 함수를 쓰는 사람은 이 모든 계산 과정을 몰라도 된다. getTotal()을 호출하면 최종 금액이 나온다는 사실 하나만 알면 충분하다.
여기서 버려지는 것의 정체를 조금 더 정확히 짚어볼 필요가 있다. 사라지는 것은 정보가 아니라 정보에 대한 접근이다. 할인 쿠폰을 어떻게 적용했는지, 세율을 어느 시점에 반영했는지는 함수 내부에 여전히 존재한다. 다만 그 함수를 호출하는 바깥 코드의 시야에서만 사라졌을 뿐이다. 핸들을 돌리는 운전자에게 랙과 피니언 기어가 없어진 것이 아니라 보이지 않게 된 것과 같은 이치다.
이 감춤은 대부분 편리하지만, 가끔 값을 치르게 만든다. 핸들에 갑자기 이상한 유격이 생기면 운전자는 그제야 자신이 랙과 피니언 기어라는 기계 장치 위에 손을 얹고 있었다는 사실을 실감한다. getTotal()이 이상한 금액을 돌려줄 때도 마찬가지다. 평소에는 존재하지 않는 것처럼 여겨지던 세금 계산 로직과 할인 규칙이, 오류가 발생하는 순간 갑자기 그 실체를 드러낸다. 소프트웨어 공학에서는 이런 현상을 새는 추상화라고 부른다. 버려진 것은 사라진 것이 아니라 잠시 시야 밖으로 밀려났을 뿐이라는 사실을 이 순간 다시 확인하게 된다.
그렇다면 바깥에 남아 있는 것은 무엇일까. 핸들의 경우에는 “돌리면 방향이 바뀐다”는 조작과 결과의 관계가, getTotal()의 경우에는 “주문을 넣으면 금액이 나온다”는 약속이 남는다. 추상화는 복잡한 내부를 감추는 동시에, 바깥에서 붙잡아야 할 최소한의 약속만 남긴다. 다음 화에서는 이 약속에 이름을 붙였을 때 그것이 왜 인터페이스가 되는지 살펴본다.