코드 중복 vs. 잘못된 추상화: DRY와 과도한 설계의 균형

잘못된 추상화의 비용

중복된 코드를 유지하는 것이 잘못된 추상화를 관리하는 것보다 종종 훨씬 저렴합니다. DRY(Do not Repeat Yourself) 원칙은 널리 가르쳐지지만, 이를 조기에 혹은 교조적으로 적용하면 단순한 중복보다 수정하기 어려운 "과도하게 설계된" 코드베이스가 될 수 있습니다.

과소 설계된 코드베이스는 일반적으로 복잡하고 경직된 추상화에 얽매여 문제 영역을 정확히 반영하지 못하는 코드베이스보다 작업하기 쉽습니다. 추상화가 잘못되면 개발자는 자신이 만든 프레임워크와 싸우게 되고, 단 하나의 변경이 상속된 클래스나 매개변수화된 함수의 미로를 헤쳐야 하는 취약한 시스템이 됩니다.

우연한 중복 vs. 실제 중복 구분

모든 코드 중복이 동일하게 취급되는 것은 아닙니다. 추상화를 할지는 중복이 "실제"인지 "우연"인지에 달려 있습니다.

  • 실제 중복: 동일한 논리가 여러 곳에서 적용되는 경우로, 이는 단일하고 보편적인 진리(예: 특정 물리 공식)를 나타냅니다. 이는 "단일 진리 원천"을 보장하기 위해 추상화해야 합니다.
  • 우연한 중복: 두 개의 서로 다른 기능이 현재는 동일하게 보이지만 독립적으로 진화하는 경우입니다. 이를 하나의 추상화로 강제하면 한 기능의 변경이 다른 기능을 예기치 않게 깨뜨리는 "장거리 결합"이 발생합니다.

한 기여자가 언급했듯이, 두 갈래가 하나로 강제될 경우 발생할 버그를 방지하기 위해 코드를 중복하는 것이 필요하다면 리팩터링이 필요합니다. 그러나 추상화가 단순히 편의를 위해 존재하다가 불편해지기 시작하면 그 목적에 실패한 것입니다.

추상화 시점을 판단하는 전략

중복과 추상화 사이의 균형을 찾는 것은 핵심 엔지니어링 기술입니다. 적절한 시점을 판단하기 위해 여러 휴리스틱이 사용됩니다:

삼법칙 (Rule of Three)

많은 개발자는 "삼법칙"을 따릅니다. 이는 중복이 두 번은 허용되지만, 같은 패턴이 세 번째로 나타날 때 추상화할 시점이라는 의미입니다. 이는 단일 유사성 사례에 기반한 조기 추상화를 방지합니다.

압축 vs. 추상화

코드 라인 수를 줄이는 것(압축)과 개념적으로 일관된 부분을 끌어올리는 것(추상화)을 구분하는 것이 도움이 됩니다. 고품질 엔지니어링은 단순 라인 수 압축보다 개념적 추상화를 우선시합니다.

인터페이스 우선, 상속은 뒤로

DRY에 과도하게 집착해 깊은 상속 트리가 생기는 함정을 피하기 위해 많은 엔지니어는 인터페이스 사용을 선호합니다. 이는 직교적인 코드를 가능하게 하여 경직된 클래스 계층보다 유연하고 유지보수가 쉬워집니다.

중복에 대한 반론과 위험

"중복이 더 저렴하다"는 주장은 인기가 있지만, 특히 규모가 커질 때 위험을 동반합니다:

  • 규모에 따른 유지보수 부담: 프로젝트가 일정 규모(예: 수십 개 고객) 이상으로 커지면 중복이 금단의 비용이 될 수 있습니다. 많은 인스턴스에 걸친 중복 코드를 유지하는 것은 개발자 자원을 크게 소모합니다.
  • LLM 요인: AI 생성 코드 시대에 중복은 위험할 수 있습니다. LLM이 모든 중복된 패턴에 동일한 수정을 일관되게 적용하지 못하면 일관성 없는 버그가 발생할 수 있습니다.
  • 매몰 비용과 관성: 일부는 광범위한 중복이 유지보수 비용을 높여 누구도 리팩터링할 힘을 갖지 못하게 만든다고 주장합니다. 이는 잘못된 추상화가 초래하는 기술 부채와는 다른 형태의 부채를 만들게 됩니다.

엔지니어링 트레이드오프 요약

접근법 주요 장점 주요 위험
중복 허용 조기이면서 경직된 추상화를 피하고 빠르게 반복 가능 분기 위험; 반복적인 변경에 대한 높은 수작업 비용
추상화 적용 단일 진리 원천; 라인 수 감소; 전역 업데이트 용이 "잘못된" 추상화 위험; 복잡한 결합 생성; 되돌리기 어려움

요약 중복된 코드를 유지하는 것이 잘못된 추상화를 관리하는 것보다 비용이 적게 드는 경우가 많지만, 엔지니어는 분기 위험과 규모에 따른 위험을 균형 있게 고려해야 합니다.

제목 코드 중복 vs. 잘못된 추상화: DRY와 과도한 설계의 균형

Sources