2025년 6월 21일 작성

결합도는 낮추고 응집도는 높이기

결합도를 낮추고 응집도를 높이는 것은 software 품질을 향상시키는 핵심 원칙입니다.

낮은 결합도 + 높은 응집도

  • 소프트웨어 설계에서 결합도(Coupling)는 낮추고 응집도(Cohesion)는 높이는 것이 품질 좋은 system을 만드는 핵심 원칙입니다.
  • 결합도는 module 간의 의존성과 상호작용의 정도를 나타내고, 응집도는 module 내부 요소들이 얼마나 밀접하게 관련되어 있는지를 나타냅니다.
  • 낮은 결합도와 높은 응집도를 유지하면 code의 유지 보수성, 재사용성, 확장성이 크게 향상됩니다.

결합도 (Coupling)

  • 결합도는 서로 다른 module이나 component 간의 의존성 정도를 측정하는 지표입니다.
  • 결합도가 높다는 것은 module들이 서로 강하게 의존하고 있어서, 하나의 module을 변경할 때 다른 module들도 함께 수정해야 한다는 의미입니다.
  • 반대로 결합도가 낮다는 것은 module들이 독립적으로 동작할 수 있어서, 한 module의 변경이 다른 module에 미치는 영향이 최소한이라는 의미입니다.

결합도가 낮은 설계의 좋은 점

  • 독립적인 개발과 배포가 가능해집니다.
    • 각 module을 별도의 team에서 독립적으로 개발할 수 있습니다.
    • module별로 다른 배포 주기를 가질 수 있어서 개발 속도가 빨라집니다.
  • 장애 격리가 쉬워집니다.
    • 한 module에서 발생한 문제가 다른 module로 전파되지 않습니다.
    • system의 전체 가용성이 향상됩니다.
  • 기술 선택의 자유도가 높아집니다.
    • 각 module에서 서로 다른 programming language나 framework를 사용할 수 있습니다.
    • 요구 사항에 가장 적합한 기술을 module별로 선택할 수 있습니다.
  • test 작성과 실행이 간단해집니다.
    • mock이나 stub을 활용하여 격리된 환경에서 test할 수 있습니다.
    • 병렬로 test를 실행할 수 있어서 전체 test 시간이 단축됩니다.

결합도가 높은 설계의 문제점

  • 변경 시 파급 효과가 크기 때문에 code 수정이 어려워집니다.
    • 하나의 module을 수정하면 관련된 여러 module을 동시에 수정해야 합니다.
    • 예상하지 못한 곳에서 bug가 발생할 가능성이 높아집니다.
  • testing이 복잡해지고 시간이 많이 소요됩니다.
    • 의존 관계가 복잡하기 때문에 단위 test를 작성하기 어려워집니다.
    • test를 위해 여러 module을 함께 준비해야 합니다.
  • code 재사용이 어려워집니다.
    • module을 다른 project에서 사용하려면 의존하는 모든 module을 함께 가져와야 합니다.

응집도 (Cohesion)

  • 응집도는 하나의 module 내부에서 요소들이 얼마나 밀접하게 관련되어 있는지를 나타내는 지표입니다.
  • 응집도가 높다는 것은 module 내의 모든 요소가 하나의 명확한 목적을 위해 협력하고 있다는 의미입니다.
  • 응집도가 낮다는 것은 module 내에 서로 관련 없는 기능들이 섞여 있어서 module의 목적이 불분명하다는 의미입니다.

응집도가 높은 설계의 좋은 점

  • 명확한 책임과 역할로 인해 code를 이해하기 쉬워집니다.
    • module의 이름만 봐도 어떤 일을 하는지 직관적으로 알 수 있습니다.
    • 새로운 개발자도 빠르게 code 구조를 파악할 수 있습니다.
  • 변경의 영향 범위가 명확하고 제한적입니다.
    • 특정 기능을 수정할 때 어느 module을 건드려야 하는지 쉽게 파악할 수 있습니다.
    • 한 module 내에서 변경이 완료되어 side effect를 예측하기 쉽습니다.
  • 재사용성과 모듈화가 극대화됩니다.
    • 완전한 기능 단위로 module이 구성되어 있어서 다른 context에서도 그대로 사용할 수 있습니다.
    • 불필요한 dependency 없이 필요한 기능만 선택적으로 사용할 수 있습니다.
  • debugging과 maintenance가 효율적입니다.
    • 문제가 발생했을 때 관련 module을 빠르게 찾을 수 있습니다.
    • 기능별로 명확히 분리되어 있어서 성능 최적화나 refactoring이 안전합니다.

응집도가 낮은 설계의 문제점

  • module의 역할과 책임이 불분명해집니다.
    • 하나의 module이 여러 가지 서로 다른 일을 처리하게 됩니다.
    • code를 읽고 이해하기 어려워집니다.
  • 변경과 확장이 어려워집니다.
    • 특정 기능만 수정하려고 해도 관련 없는 기능까지 영향을 받을 수 있습니다.
    • 새로운 기능을 추가할 때 어느 module에 넣어야 할지 판단하기 어려워집니다.
  • 재사용성이 떨어집니다.
    • 필요한 기능만 사용하고 싶어도 불필요한 기능까지 함께 포함되어 있습니다.

낮은 결합도와 높은 응집도 = Software 품질 향상

  • 결합도를 낮추고 응집도를 높이면, software의 품질이 크게 향상됩니다.

유지 보수성 향상

  • 독립적인 module 구조로 인해 변경 사항의 파급 효과가 최소화됩니다.
    • 특정 module의 내부 구현을 변경해도 다른 module에 영향을 주지 않습니다.
    • bug 수정이나 기능 개선 시 수정 범위를 예측하고 제한할 수 있습니다.
  • 명확한 책임 분리로 인해 문제 발생 시 원인을 빠르게 파악할 수 있습니다.

개발 효율성 증대

  • 병렬 개발이 가능해집니다.
    • 서로 다른 개발자가 독립적인 module을 동시에 개발할 수 있습니다.
    • module 간 interface만 합의하면 각자 내부 구현에 집중할 수 있습니다.
  • testing이 단순해집니다.
    • 각 module을 독립적으로 test할 수 있어서 unit test 작성이 쉬워집니다.
    • mock object를 활용한 격리된 test 환경 구성이 가능합니다.

재사용성과 확장성 확보

  • module의 독립성 덕분에 다른 project에서도 쉽게 재사용할 수 있습니다.
  • 새로운 기능 추가 시 기존 code에 미치는 영향을 최소화할 수 있습니다.
    • 새로운 module을 추가하거나 기존 module을 교체하는 것이 안전해집니다.

Code 품질 향상

  • 가독성이 좋아집니다.
    • 각 module의 역할이 명확하기 때문에 code를 이해하기 쉬워집니다.
    • 전체 system의 구조를 파악하기 쉬워집니다.
  • 설계의 일관성이 유지됩니다.
    • 명확한 책임 분리로 인해 architecture가 안정적으로 유지됩니다.

실무에서의 적용 방법

  • 낮은 결합도와 높은 응집도를 실현하기 위해, 다양한 설계 원칙과 pattern을 적용할 수 있습니다.

Interface 활용

  • 추상화된 interface를 통해 module 간 통신하여 결합도를 낮춥니다.
    • 구체적인 구현체가 아닌 interface에 의존하도록 설계합니다.
    • Dependency Injection pattern을 활용하여 의존성을 외부에서 주입받습니다.

단일 책임 원칙 준수

  • 하나의 module은 하나의 책임만 가지도록 설계하여 응집도를 높입니다.
    • class나 function이 변경되는 이유가 오직 하나여야 합니다.
    • 서로 다른 이유로 변경되는 기능들은 별도의 module로 분리합니다.

정보 은닉 적용

  • module 내부의 구현 세부 사항을 외부에서 직접 접근할 수 없도록 숨깁니다.
    • public interface를 통해서만 module과 상호작용하도록 제한합니다.
    • 내부 구현 변경 시 외부에 미치는 영향을 차단합니다.

계층화 구조 설계

  • 관심사별로 계층을 분리하여 각 계층의 응집도를 높이고 계층 간 결합도를 낮춥니다.
    • presentation layer, business logic layer, data access layer로 구분합니다.
    • 상위 계층이 하위 계층에만 의존하도록 dependency 방향을 통제합니다.

목차