결합도(Coupling)와 응집도(Cohesion)의 개념과 특징

여우는 야옹야옹·2025년 11월 1일
0

정보처리기사

목록 보기
1/3

결합도의 개념

  • 결합도는 내부 모듈이 아니라 외부 모듈과의 상호의존성을 나타내는 정도
  • 결합도는 소프트웨어 구조에서 모듈 간의 관련성을 측정하는 척도
  • 결합도가 낮을수록 품질(=Low Coupling)이 좋아진다. 독립적이고 유지보수가 쉬운 구조가 되기 때문이다.

결합도의 특징

모듈연관성 없음: 결합도가 낮으면 각 모듈이 독립적으로 동작할 수 있다. 다른 모듈의 내부 로직을 몰라도 인터페이스만 알면 사용 가능하다.
인터페이스 의존성 : 내부 구현이 아닌 정의된 인터페이스(입출력 규약)만 사용되 연결된다. 덕분에 수정시 다른 모듈에 영향이 거의 없다.
복잡성 감소 : 모듈 간 얽힘이 줄어드니 시스템 전체 구조가 단순해진다. 테스트 수정,확장이 쉬워진다.
파급효과 최소화 : 한 모듈을 변경해도 다른 모듈에 영향이 거의 없다. 즉, 유지보수 시 리스크가 적다.

결합도의 유형은 내용>공통>외부>제어>스탬프>자료로 결합도가 낮아진다.

내용 결합도(Content Coupling) : 다른 모듈에 있는 변수나 기능을 다른 모듈에서 사용하는 경우, 하나의 모듈이 다른 모듈에 기능을 직접적으로 참조할 때 두 모듈은 내용적으로 결합되어 있는 경우의 결합도

정의

  • 한 모듈이 다른 모듈의 내부(필드/내부/데이터 로직)를 직접 건드릴때
  • 타 모듈의 private한 것을 우회해서 쓰거나, 내부 파일 포맷/메모리 레이아웃에 의존

예시(나쁨)

class OrderRepository {
    List<Order> data = new ArrayList<>(); // 내부 컬렉션을 외부에 노출 (package/private로 가정)
}
class ReportService {
    void make() {
        OrderRepository repo = new OrderRepository();
        repo.data.sort(...);     // 내부 컬렉션을 직접 조작 → 내부 변경에 취약
    }
}

문제점

  • 내부가 바뀌면(자료구조 교체 등) 연쇄 수정. 테스트/유지보수 악몽

개선

  • 캡슐화, 공개 메서드만 사용
class OrderRepository {
    public List<Order> findAllSortedBy(...){ ... } // 내부 숨기기
}

공통 결합도(Common Coupling) : 파라미터가 아닌 모듈 밖에 선언되어 있는 전역 변수를 참조하고 전역 변수를 갱신하는 식으로 상호작용하는 결합도

정의

  • 여러 모듈이 공유 전역 데이터(static 변수, 전역 상태)에 의존.

예시(나쁨)

class Globals { public static String CURRENCY = "KRW"; }
class A { void foo(){ if (Globals.CURRENCY.equals("USD")) ... } }
class B { void bar(){ Globals.CURRENCY = "EUR"; } } // A의 동작이 갑자기 바뀜

문제점

  • 숨은 의존성(누가 언제 값을 바꾸는지 모름) → 디버깅 지옥.

개선

  • 전역 상태 대신 의존성 주입(DI), 구성 객체(config) 전달, 불변값 사용.

외부 결합도(External Coupling) : 모듈이 다수의 관련 기능을 가질 때 모듈 안의 구성요소들이 그 기능을 순차적으로 수행할 경우의 결합도

정의

  • 모듈들이 외부에서 강제된 약속(표준 파일 형식, 통신 프로토콜, DB 스키마, 디바이스 드라이버 인터페이스 등)에 같이 의존.

예시(나쁨)

// 외부 API가 "yyyy-MM-dd" 형식 문자열을 강제
interface ExternalApi { String getDate(); }

class Client {
    LocalDate fetch() {
        String s = api.getDate();           // 외부 규격에 의존
        return LocalDate.parse(s, DateTimeFormatter.ISO_DATE);
    }
}

문제점

  • 외부 규격 변경 시 파급. 다수 모듈이 동시 수정.

개선

  • Anti-corruption Layer/Adapter를 둬서 외부 형식을 내부 도메인 모델로 변환, 내부는 안정화.

제어 결합도(Control Coupling) : 어떤 모듈이 다른 모듈의 내부 논리 조직을 제어하기 위한 목적으로 제어 신호를 이용하여 통신하는 경우로, 하위 모듈에서 상위 모듈로 제어 신호가 이동하여 상위 모듈에게 처리 명령을 부여하는 권리 전도 현상이 발생하는 결합도

정의

  • 호출자가 처리 절차를 지시하는 제어 신호/플래그를 파라미터로 넘김(“이 분기 타!”).

예시(나쁨)

void render(boolean asPdf) {  // 제어 플래그
    if (asPdf) renderPdf(); else renderHtml();
}

문제점

  • 호출 측이 상대 모듈의 내부 흐름을 알아야 함 → 응집도 저하, 테스트 케이스 폭증.

개선

  • 전략 패턴/다형성으로 분리.
interface Renderer { void render(); }
class PdfRenderer implements Renderer { ... }
class HtmlRenderer implements Renderer { ... }
// 호출자는 적절한 구현체만 선택

스탬프 결합도(Stamp Coupling) : 모듈 간의 인터페이스로 배열이나 객체,구조 등이 전달되는 경우의 결합도

정의

  • 필요한 일부 정보만 쓰는데도 큰 구조체/DTO/엔티티를 통째로 전달.

예시(나쁨)

class Order { Long id; Customer customer; List<Item> items; ... }
void notifyShipping(Order order) {        // 사실 필요한 건 id, 주소뿐
    send(order.customer.getAddress(), order.getId());
}

문제점

  • 과도한 파라미터 표면적 → 변경 전이. 불필요한 의존.

개선

  • 정확히 필요한 것만 담은 전용 DTO(골라 담기) 로 축소.
record ShippingInfo(Long orderId, Address address){}
void notifyShipping(ShippingInfo info){ ... }

자료 결합도(Data Coupling) 👍최선 : 모듈 간의 인터페이스로 전달되는 파라미터를 통해서만 모듈 간의 상호 작용이 일어나는 경우의 결합도

정의

  • 모듈이 필요한 데이터만 파라미터로 주고받음. 순수 함수 스타일에 가까움.
    예시(좋음)
Money convert(Money amount, Currency to) { ... }  // 부작용 없음, 필요한 데이터만

장점

  • 인터페이스가 작고 명확. 변경 격리, 테스트 쉬움, 재사용성↑.

실무 체크리스트

전역(static) 상태를 읽거나 바꾸는가? → 공통 결합
boolean/enum 플래그로 분기시키는가? → 제어 결합
거대 엔티티/DTO를 통째로 넘기는가? → 스탬프 결합
외부 포맷/프로토콜이 코드 전반에 퍼졌는가? → 외부 결합 → 어댑터로 격리
private 자료구조를 외부가 건드리나? → 내용 결합 → 캡슐화

이런 조건들을 숙지하고 있으면 실무에서 결합도를 의식하며 더 견고한 코드를 작성할 수 있다.

profile
성장중인 개발자 (머리속의 생각을 글로 옮기는 연습을 하고 있습니다.)

0개의 댓글