Soyeon Park 님의 블로그
결합도와 응집도 (Coupling and Cohension) 본문
결합도(Coupling)
1. 자료(Data) 결합도
기본 자료형 데이터만 주고 받는 것이다.
주차요금청구서 모듈은 필요한 "주차시간"만 넘겨주고, 주차요금계산기 모듈이 "주차요금"을 계산해서 전달해준다.

2. 스탬프(Stamp) 결합도
배열이나 객체 같은 자료구조를 참조하는 형태이다.
주차요금청구서 모듈은 주차시간(time)만 넘겨주면 되는데, "이용기록(record)" 자료구조를 넘긴다.


Record를 계속 넘겨주고 있다. 결합력을 낮추기 위해서 Record 자료구조로 넘기기보다는 각자의 멤버변수로 만드는게 좋겠다.
만약에 Record 자료구조에서 useTime이 useMin으로 수정이 발생했다고 하자. 그러면 Bill, Fee도 수정되어야 한다. 다른 모듈에 의해서 내 모듈이 고쳐져야 한다면 결합도가 높은 것이다.
3. 제어(Control) 결합도
한 모듈이 다른 모듈 내부의 논리적인 흐름을 제어하는 제어요소를 전달한다. 상위 모듈이 하위 모듈의 상세한 처리 절차를 통제하는 것이다. 이는 캡슐화(Encapsulation)의 원칙에 위배된다. 왜냐하면, 상위 모듈이 하위 모듈의 내부 구현을 알고 있는 것이기 때문이다. 캡슐화가 잘 되어있다면, "무엇"을 하는지만 외부에 공개될 뿐 안에서 "어떻게" 실현되느냐는 알릴 필요가 없다.
주차요금청구서 모듈은 "주차시간 + 회원 여부"를 넘긴다. 주차요금계산기 모듈은 받은 "회원 여부"에 따라서 내부 논리 흐름을 결정하고 있다. 할인 여부를 주차요금청구서에서 결정하고, Fee 모듈은 계산만 하도록 해야지, 왜 회원 여부에 따른 판단을 계산 모듈에서 하고있는가? 로 이해하면 된다.

아래에 로깅에 대한 예시를 하나 더 보자. 현재 DataProcessor 클래스에서 조건에 따라서 로깅을 어떻게 보여줄건지를 결정하고 있다. 외부에서 DataProcessor를 호출할 때, 로그를 찍을지 말지 결정하는 isVerbose 제어 요소를 전달해야하므로 결합도가 높아졌다.

DataProcessor는 데이터를 조작하는 로직만 다루자. 로깅에 대한 것은 다른 클래스로 빼는 것이 좋겠다. 책임을 분리하도록 수정하였다.


4. 외부(External) 결합도
외부 결합도는 내가 할 수 있는 일임에도 불구하고 외부 모듈을 따로 두는 것이다. 이는 외부 API, 외부 시스템을 활용하는 것과는 차이가 좀 있다. 모든게 내 제어범위 안에 있을 때를 말하는거다.


AddFee라고 할증 관련하여 외부 모듈을 두었다. 그나마 좀 개선할 수 있는 부분을 바꿔본다면 아래와 같다.


근데...이것도 사실 별로다. 자료 결합으로 가는 것이 가장 좋다. AddFee와 같은 쓸데없는 외부 모듈 참조 자체를 없애자.
5. 공통(Common) 결합도
공통결합하면 전역변수를 떠올리면 된다. 전역변수는 되도록 사용하지 말자. 누가 언제 어떻게 접근했는지 추적이 어렵기 때문이다. 클래스 내 멤버변수를 get, set으로 접근하자.

6. 내용(Content) 결합도
한 모듈이 다른 모듈의 내부 기능과 내부 데이터를 직접 참조한다. 다른 모듈의 내부 기능, 데이터를 그대로 가져와 사용하고 수정한다.

name과 age는 User의 멤버변수로 두는 것이 자연스럽다. 지금은 public으로 외부 접근을 다 허용하고 있으므로, 다른 사람이 내 나이를 바꿀 수가 있다. 캡슐화 원칙을 위배한다. 객체를 외부에서 바꾸려(제어)하는 것을 막아야 한다.
응집도(Cohension)
결합도는 모듈 간의 관계를 본 것이라면, 응집도는 한 모듈 내를 본다. 얼만큼 뭉쳐야 하는가이다. 한 클래스가 기능에 집중하기 위한 모든 정보와 역할을 가진다. 하나의 모듈을 하나의 기능을 가진다면 응집도가 높다. 하나의 모듈에 여러 기능을 가진다면 응집도가 낮다.
응집도가 높은 모듈: 하나의 모듈 안에 함수와 데이터가 하나의 기능을 구현하기 위해 필요한 것들만을 배치한다.
응집도가 낮은 모듈: 서로 관련 없는 함수와 데이터가 공존하고 서로 다른 목적을 추구하는 것이 하나의 모듈에 들어있다.
예를 들어, 주문을 처리하는 클래스인데 회원 정보를 업데이트하는 메서드가 있다면, 많은 책임을 하나의 모듈에 넣어 응집도가 낮아진 것이다. 단일책임원칙을 위반했다. 응집도가 높으면 수정 후 다른 모듈에게 영향을 주지 않아서 유지보수에 유리하다.
1. 기능적(functional) 응집도
모든 기능이 단일 목적을 가진다. 모듈 내부의 요소들이 모듈에 대하여 정의된 하나의 기능에 모두 기여하고 밀접하게 관련되어 모였다. 응집도가 높아서 좋다. Stack 클래스 안에 push, pop 가지고 있는 것이다.

2. 순차적(Sequential) 응집도
모듈 내에서 한 구문의 출력값이 다음 구문의 입력 데이터로 사용되는 경우이다.

numberGrade를 computeLetter의 입력값으로 쓰고 있다. 이렇게 하기보다, num은 num대로 뽑고, letter는 num을 기본 datatype으로 넘겨 받는 방법이 좋겠다.
3. 교환적(Communication) 응집도
공통된 파라미터가 메서드 호출에 사용되는 경우이다. 순차적 응집도와 다르게, 처리 순서가 중요하지 않다. 의존관계도 없다. 단지 동일한 입력과 출력을 사용한다는 이유로 모아져 있는 것이다. 좋지 않다.

transform_matrix와 inverse_matrix는 서로 다른 기능이다. aMatrix라는 동일 매개변수를 받고 있어서 하나의 클래스로 모였다. 그래서 그들 간의 순서는 중요하지 않다.
4. 절차적(Procedural) 응집도
하나의 클래스에서 다수의 기능을 순차적으로 수행한다. 여러개의 메소드를 호출하는데, 서로 관련된건 아니다. 그러니 의존 관계도 없다. 그냥 순서대로만 될 뿐이다.

본문 쓰기 → 인사말 쓰기 → 보내기. 이 3개는 각각 다른 기능을 하고 있지만 편지를 쓰기 위해 순서대로 이루어져야해서 묶여있다.
5. 시간적(Temporal) 응집도
각 기능 요소들이 순서에 상관없이 특정 시점에 수행되어서 모여있다. 연관이 되어있지 않을 수 있다. 예를 들면 변수의 초기화, Exception error 같은게 있다. 시스템 로딩 시 변수가 다 초기화된다. 하지만 변수끼리 서로 관련이 없는데 모여있게 된다. 예외처리도 마찬가지이다. Exception 안에 다 몰아 넣고 e로 퉁치는 것은 안좋다.


변수 초기화를 위해서 모였지만, no_student, no_department, university_name 변수들은 서로 관련이 없다. 애플리케이션 켜졌을 때, 설정파일 읽기, 로깅시스템 초기화, DB 연결, 캐시 초기화를 같은 시간에 하지만 서로 관련은 없다.

readFile, parseContent, saveToDatabase는 파일 처리하는 같은 시간에 동작하지만, 서로 관련이 없다. 그리고 지금 예외를 e 하나로 잡고 있는데, 서로 다른 것들을 모두 e로 잡으면 안된다.

이렇게 하는게 좋겠다. 하나의 Exception안에는 걔랑 관련된 것만 나오도록 설계한다.
6. 논리적(Logical) 응집도
논리적으로 유사하고 성격이 비슷한 기능이 모인 것이다. 카테고리가 비슷해서 그냥 묶은 것이기 때문에, 조건문이 많아지고 복잡도가 상승한다. 안에 들어있는 하나의 기능이 바뀌면 내부 로직을 뜯어 고쳐야 한다. 수정이 잦아지므로, 개방-폐쇄 원칙에 위배된다.

방정식을 푼다는 큰 카테고리에 묶여 있을 뿐 그 안에서는 서로 관련이 없다. 왜 복잡하게 이 안에서 조건문으로 결정하고 있냐는거다. 내가 어떤 조건에서 무엇을 해야할지는 동적으로 Equation 인터페이스를 구현하는 각각의 Equation solving 객체들에서 결정을 해야한다. 전략 패턴을 생각하자.

왜 height와 width를 같이 결정하는 모듈을 둬서, 조건문 처리로 하느냐...

동일한 예시이다. hadleMessage는 각 객체별로 handleMessage interface 구현해서 각자가 결정해야한다. 아래와 같이 구현하자. sender = new EmailSender() 처럼 동형적으로 결정하자.


7. 우연적(Concidental) 응집도
최악이다. 유연성이 전혀 없다. 문법만 객체지향을 따랐을 뿐, 아무 상관 없는 애들이 모여 있다.

'소프트웨어공학' 카테고리의 다른 글
| GoF Design Pattern (0) | 2026.04.18 |
|---|---|
| SOLID - 코드로 이해하기 (0) | 2026.04.14 |
| 객체지향 설계 원리 (0) | 2026.04.14 |
| 전통적인 설계 원리 (0) | 2026.04.13 |