Interface Abstraction

2025-09-23

추상화를 하기 위한 방법은 여러가지 있다. Interface를 통해 계약으로 사용하거나, 내부 구현을 안으로 집어넣는 캡슐화 같은 추상화.. 등등

이 문서에서는 Interface Abstraction을 다룰 것이다. 인터페이스는 polymorphism과 abstraction을 위한 수단으로 시그니처를 정의하는 일종의 설계도와 비슷하다.

인터페이스의 힘은 다형성에서 나타난다. 여러 구현을 동일한 계약(인터페이스)으로 구현될 때 유용하게 사용된다.

하지만, 인터페이스를 적용하면 호출 지점에서 실제 구현을 추적하는 비용이 커진다. IDE에서도 command + b와 같은 단축키를 눌러도 인터페이스 정의로만 이동해 구현에 도달하기 위해 흐름을 찾아봐야한다.

== “읽기 어렵고 디버깅이 어려운 코드”에 더 가까워지는 것이다. 이게 정말 좋은 관행일까?

문제의 경우는 인터페이스와 구현체가 일대일로 유지될 때이다.

모든 함수가 인터페이스를 인자로 받고, 반환하며, 실제 구현은 하나뿐인 구조가 반복된다. 이런 구조는 나중에 다른 구현을 도입할 가능성이 극히 낮은데도, 현재를 지속해서 복잡하게 만든다.

“10개 중 한두 개만 새로운 구현이 필요할 수 있는데, 그 20%를 미리 편하게 하려고 80%의 일을 불편하게 만드는 비효율적 선택”

또한, 새로운 구현을 도입하는 시점에는 기존 인터페이스 설계 자체가 적합하지 않아 인터페이스까지 변경해야 할 가능성이 높다.

인터페이스가 올바르게 사용될 때는 다중 구현(다형성), 외부 라이브러리가 있을 수 있다.

  • 다중 구현을 동일한 계약(인터페이스)으로 취급하는 경우에 여러 구현체를 한 타입으로 다루면서 호출 일관성을 확보한다.
  • 외부에 제공하는 라이브러리에서 확장 포인트로 인터페이스를 노출하는 경우 외부 개발자가 동일 계약(인터페이스)으로 자체 구현을 제공할 수 있게 된다.

위의 상황이 아닌 이상 concrete class를 직접 쓰는 편이 낫다.

Premature optimization is the root of all evil

처음부터 성급하게 인터페이스를 만들지 말고, 필요할 때 도입하면 된다.

과도한 추상화, 불필요한 인터페이스는 읽기 편하고 디버깅 쉬운 코드와 점점 멀어진다. 반드시 필요성 검증 후 최소화해야 한다.

책에서 읽은 ‘좋은 방식’이라도 맥락 없이 적용하면 오히려 복잡성이 높아질 수 있다.