BE 공부/클린 코드

[소프트웨어 설계] 응집도

꼬질꼬질두부 2025. 6. 28. 18:21
반응형

1. 공부하게 된 계기

커플링 개념을 공부하면서 자주 같이 등장하던 ‘응집도’가 눈에 들어왔습니다.
설계 원칙 중 “커플링은 낮게, 응집도는 높게”라는 말은 많이 들었지만, 응집도에 대해 정확히 이해하고 있지는 않았습니다.

 

따라서 응집도가 구체적으로 뭔지, 어떻게 구분하고 판단해야 알기 위해

좋은 구조와 나쁜 구조를 비교하며 응집도에 대한 개념을 정리해보게 되었습니다.


2. 핵심 요약

  • 응집도(Cohesion)는 모듈이나 클래스가 얼마나 하나의 책임에 집중하고 있는지를 나타내는 지표입니다.
  • 응집도가 높을수록 모듈이 명확한 목적을 갖고 재사용성, 유지보수성이 좋아집니다.
  • 응집도는 총 7단계로 나뉘며, 기능적 응집(Function Cohesion)이 가장 이상적입니다.

3. 개념 정리

✅ 응집도란?

  • 클래스나 함수 같은 모듈이 얼마나 하나의 목적에 집중되어 있는지를 측정하는 개념입니다.
  • 낮은 응집도는 서로 관련 없는 기능이 한 모듈에 섞여 있는 상태,
  • 높은 응집도 모든 기능이 하나의 목표를 위해 유기적으로 구성된 상태입니다.

✅ 응집도의 종류 (낮은 → 높은 순)

응집도 종류 설명  예시 특징
우연적 (Coincidental) 관련 없는 기능이 우연히 묶임 초기화 + 로깅 + 이메일 발송 최악
논리적 (Logical) 비슷한 종류의 작업이 함께 존재 여러 출력 방식 제어 if/else 많음
시간적 (Temporal) 특정 시점에 실행되는 기능 묶음 시작 시: 설정 로딩, 로그 등 시점은 같지만 목적은 다름
절차적 (Procedural) 순서대로 실행되는 기능들 단계별 처리 흐름이 중요
통신적 (Communicational) 같은 데이터를 사용하는 기능 같은 파일 읽기/처리 데이터 중심
순차적 (Sequential) 한 결과가 다음 작업의 입력이 됨 데이터 파싱 → 처리 → 저장 연결된 처리 과정
기능적 (Functional) 하나의 목적을 위한 구성 주문 처리 전용 클래스 이상적!

 


4. 예제 코드

1) 우연적 응집도

class Utility {
  initDB() {
    console.log("DB 초기화");
  }
  sendEmail() {
    console.log("이메일 발송");
  }
  logMessage() {
    console.log("로그 기록");
  }
}

이 클래스는 전혀 관련 없는 기능들을 모아놓은 예입니다.

데이터베이스 초기화, 이메일 전송, 로그 출력은 서로 다른 책임을 가지는데,

이를 한 클래스에 담으면 이 클래스가 무엇을 위한 클래스인지 알기 어려워지고, 유지보수도 어렵습니다.

이런 구조를 우연적 응집(Coincidental Cohesion)이라 하며, 가장 피해야 할 형태입니다.

2) 논리적 응집도

class Printer {
  printToConsole(data) {
    console.log(data);
  }
  printToFile(data) {
    console.log("파일 출력 완료");
  }
  printToPDF(data) {
    console.log("PDF 출력 완료");
  }
}

이 클래스는 모두 '출력'이라는 논리적 범주에 속한 기능이지만, 출력 방식이 다르고 구현도 다릅니다.

나중에 사용자가 출력 방식에 따라 조건 분기를 하게 되면 if/else가 많아지고 구조가 복잡해질 수 있습니다.

이는 논리적 응집(Logical Cohesion)의 예입니다.

3) 시간적 응집도

class StartupTasks {
  loadConfig() {
    console.log("설정 로딩");
  }
  connectDB() {
    console.log("DB 연결");
  }
  initializeLogger() {
    console.log("로깅 초기화");
  }
}

이 클래스는 애플리케이션 시작 시 실행되는 작업들을 모아 놓은 것으로 보이지만, 각 기능의 목적은 서로 다릅니다.

단순히 실행 시점이 비슷하다는 이유로 묶여 있으며, 이처럼 시점 기반으로 묶은 것을 시간적 응집(Temporal Cohesion)이라 합니다.

4) 절차적 응집도

class DataPipeline {
  loadData() {
    console.log("데이터 로딩");
  }
  processData() {
    console.log("데이터 처리");
  }
  saveResult() {
    console.log("결과 저장");
  }
}

이 클래스는 정해진 순서대로 동작해야 의미가 있는 절차형 구조입니다.

예를 들어 데이터를 로딩하지 않고 처리하면 에러가 발생할 수 있습니다.

이런 흐름에 의존하는 구조를 절차적 응집(Procedural Cohesion)이라고 하며, 중간 정도의 응집도입니다.

5) 통신적 응집도

class ReportGenerator {
  fetchData() {
    console.log("데이터 가져오기");
  }
  analyzeData() {
    console.log("데이터 분석");
  }
  generateReport() {
    console.log("보고서 생성");
  }
}

이 클래스의 모든 메서드는 같은 데이터(보고서용 데이터)를 중심으로 작업을 수행합니다.

같은 데이터를 처리하는 기능들이기 때문에 이 구조는 통신적 응집(Communicational Cohesion)에 해당합니다.

6) 순차적 응집도

class ProcessingPipeline {
  parse() {
    console.log("데이터 파싱");
  }
  transform() {
    console.log("데이터 변환");
  }
  export() {
    console.log("데이터 저장");
  }
}

각 메서드가 앞 단계의 결과를 받아서 다음 단계로 넘기는 데이터 흐름 기반 구조입니다.

파싱한 데이터를 변환하고, 그걸 다시 저장하는 식으로 기능들이 순차적으로 이어지는 구조이며, 응집도가 높은 편입니다.

이는 순차적 응집(Sequential Cohesion)입니다.

7) 기능적 응집도

class OrderProcessor {
  validateOrder() {
    console.log("주문 검증");
  }
  calculateTotal() {
    console.log("총액 계산");
  }
  submitOrder() {
    console.log("주문 전송");
  }
}

이 클래스는 '주문 처리'라는 하나의 명확한 목적을 가지고 있고, 각 기능은 그 목적을 달성하기 위한 단계입니다.

구조가 명확하고 확장 및 테스트가 쉬운 이상적인 구조로, 이를 기능적 응집(Functional Cohesion)이라 합니다.


5. 이해 포인트 or 실수했던 점

  • 기능들의 목적이 하나가 아닐 경우 유지보수에 악영향을 줍니다.
  • 시간적으로 묶은 초기화 작업들이 실제로는 목적이 다르다는 걸 나중에서야 깨달았습니다.

6. 정리 요약

각 모듈이 하나의 목적에 집중할 수 있도록 설계해야 유지보수성과 재사용성이 높아집니다.
반응형