10. 인터페이스는 무엇을 남기는가
오래된 아파트의 엘리베이터와 새로 지은 빌딩의 엘리베이터는 내부 구조가 완전히 다르다. 어떤 엘리베이터는 굵은 강철 케이블과 도르래로 움직이고, 어떤 엘리베이터는 유압 실린더로 밀어 올리며, 최근에는 케이블 없이 리니어 모터로 움직이는 방식도 등장했다. 그런데도 이용자가 마주하는 버튼판은 어디를 가나 거의 같다. 숫자가 적힌 버튼을 누르면 문이 닫히고, 얼마 뒤 그 층에서 문이 열린다.
9장에서는 핸들과 getTotal()이 각각 무엇을 버렸는지 살펴봤다. 이번에는 반대편에서 같은 장면을 들여다볼 차례다. 도르래든 유압이든 리니어 모터든, 내부가 무엇이든 이용자가 마주하는 버튼과 그 사용법은 거의 달라지지 않는다. 버려진 것이 기계 장치라면, 남은 것은 “버튼을 누르면 원하는 층에 도착한다”는 약속이다. 이 바깥으로 드러난 약속에 이름을 붙이면 우리는 그것을 인터페이스라고 부른다.
인터페이스가 흥미로운 이유는 단순히 무언가를 감춰서가 아니라, 그 감춤 덕분에 서로 다른 내부를 가진 것들이 똑같은 자리에 끼워질 수 있게 되기 때문이다. 도르래 엘리베이터를 유압 엘리베이터로 통째로 바꿔도 이용자는 아무것도 다시 배울 필요가 없다. 바깥으로 드러난 약속이 그대로이기 때문이다. 내부가 통째로 달라져도 바깥에서 보이는 약속만 지켜지면, 그 자리를 차지하고 있는 것이 무엇이든 상관없어진다.
프로그래밍에서도 이 자리바꿈은 흔하게 일어난다. 주문을 결제할 때 신용카드로 낼 수도 있고, 카카오페이나 계좌이체로 낼 수도 있다. 이 각각의 결제 수단은 내부적으로 전혀 다른 절차를 밟는다. 카드사에 승인 요청을 보내는 방식과 간편결제 앱에 딥링크를 던지는 방식은 코드 수준에서 완전히 다른 이야기다. 하지만 주문 시스템의 입장에서는 pay(amount)라는 함수 하나만 호출하면 그만이다. 결제 수단이 무엇이든 이 함수를 호출하는 코드는 단 한 줄도 바뀌지 않는다.
여기서 8장에서 다룬 약속이라는 개념이 조금 더 넓어진다. 타입이 값과 함수의 모양을 약속한다면, 인터페이스는 여러 구현이 함께 지켜야 할 모양을 약속한다. 신용카드 결제와 카카오페이 결제는 내부적으로는 완전히 다른 절차를 거치지만, 둘 다 pay(amount)라는 같은 모양을 지키기로 했기 때문에 주문 시스템 앞에서는 같은 자리를 차지한다. 인터페이스는 이 공통된 모양을 통해 구현을 교체할 수 있게 만드는 계약이다.
그런데 이 자리바꿈은 결제 수단에서만 일어나는 특별한 현상이 아니다. 로그를 파일에 남길지 서버로 전송할지, 데이터를 메모리에 캐싱할지 디스크에 저장할지, 알림을 이메일로 보낼지 문자로 보낼지. 서로 무관해 보이는 문제들에서 자꾸 똑같은 모양의 해법이 반복해서 나타난다. 왜 이렇게 다른 문제들이 자꾸 같은 모양으로 풀리는 걸까. 다음 화에서는 이 반복되는 모양, 즉 디자인 패턴이 왜 자꾸 등장하는지 살펴본다.