결합도

모듈 간의 의존성 정도를 나타내는 척도로, 낮을수록 좋은 설계입니다.

결합도 단계 (높음 → 낮음)

단계이름설명
1내용 결합다른 모듈 내부를 직접 참조/수정
2공통 결합전역 변수를 공유
3외부 결합외부 데이터 포맷/프로토콜에 의존
4제어 결합제어 신호(플래그)를 전달
5스탬프 결합필요 이상의 데이터 구조를 전달
6데이터 결합필요한 데이터만 전달 O
7메시지 결합메서드 호출만으로 통신 OO

높은 결합도 예시

// X 내용 결합 - 다른 클래스 내부에 직접 접근
class OrderService {
    void process(Order order) {
        // 다른 클래스의 내부 필드를 직접 수정
        order.status = "PAID";
        order.paymentDate = LocalDate.now();
    }
}

// X 공통 결합 - 전역 변수 공유
class Global {
    static int userCount = 0;  // 여러 클래스가 직접 접근
}

// X 제어 결합 - 플래그로 동작 제어
class FileExporter {
    void export(Data data, boolean isCSV) {  // 플래그로 분기
        if (isCSV) { ... }
        else { ... }        // 호출자가 내부 동작을 제어
    }
}

낮은 결합도 예시

// O 데이터 결합 - 필요한 데이터만 전달
class OrderService {
    void process(Long orderId, String status) {  // 필요한 값만 전달
        orderRepository.updateStatus(orderId, status);
    }
}

// O 메시지 결합 - 인터페이스를 통한 통신
interface FileExporter {
    void export(Data data);
}

class CsvExporter implements FileExporter { ... }
class ExcelExporter implements FileExporter { ... }

// 호출자는 구현체를 몰라도 됨
class ReportService {
    private final FileExporter exporter;  // 인터페이스에만 의존

    ReportService(FileExporter exporter) {
        this.exporter = exporter;
    }
}

결합도를 낮추는 방법

// 1. 의존성 주입 (DI)
// X 직접 생성
class OrderService {
    EmailSender sender = new EmailSender();  // 강한 결합
}

// O 주입받음
class OrderService {
    private final EmailSender sender;
    OrderService(EmailSender sender) {  // 외부에서 주입
        this.sender = sender;
    }
}

// 2. 인터페이스 활용
// X 구체 클래스에 의존
class OrderService {
    private final KakaoEmailSender sender;  // 카카오에 종속
}

// O 인터페이스에 의존
class OrderService {
    private final EmailSender sender;  // 구현체 교체 자유로움
}

응집도 vs 결합도

항목응집도결합도
관심사모듈 내부모듈 간 관계
좋은 방향높을수록 O낮을수록 O
나쁠 때책임이 분산됨변경 시 연쇄 영향
결합도가 높으면:
A 수정 → B 수정 → C 수정 → D 수정 ...
        연쇄적 변경 발생 X

결합도가 낮으면:
A 수정 → A만 수정하면 됨 O

결합도를 낮추는 핵심은 "구체적인 것이 아닌 추상적인 것에 의존" 하는 것입니다. 이것이 객체지향 원칙 중 DIP(의존 역전 원칙) 의 핵심입니다.

CSLOG에서 보기