Coupling and Cohesion

Coupling 과 Cohesion 은 소프트웨어 아키텍처 설계에서 모듈 간의 의존성과 모듈 내부 요소들의 응집도를 평가하여 시스템의 품질을 향상시키는 핵심 개념이다. 결합도는 모듈 간 상호 의존성의 강도를 나타내며, 낮을수록 독립적이고 변경에 강한 구조가 된다. 응집도는 모듈 내부 구성요소들이 얼마나 밀접하게 관련되어 있는지를 나타내며, 높을수록 명확한 책임과 목적을 가진 모듈이 된다. 낮은 Coupling 과 높은 Cohesion 은 시스템의 유지보수성, 확장성, 재사용성을 높이며, 이러한 원칙은 모듈화, 정보 은닉, 단일 책임 원칙 등과 밀접하게 연관되어 있다. 현대의 마이크로서비스, 클린 아키텍처 등 모든 아키텍처 패턴의 이론적 기반이 된다.

핵심 개념

항목커플링 (Coupling)응집도 (Cohesion)
정의모듈 간 의존성모듈 내부 요소 간 연관성
목표낮은 결합도 (Loose Coupling)높은 응집도 (High Cohesion)
주요 포인트독립성 확보, 변경 전파 최소화책임 명확화, 유지보수성 향상
이상적 상태각 모듈은 외부와 최소한으로만 통신모듈은 한 가지 책임만 가짐
영향결합도가 낮을수록 변경 영향 최소화, 유지보수 용이
결합도가 높으면 수정 전파 증가
응집도가 높을수록 책임 명확, 코드 이해/재사용 용이
응집도가 낮으면 모듈 기능이 모호
유형- Content
- Common
- Control
- Stamp
- Data
- Message
- No Coupling
- Coincidental
- Logical
- Temporal
- Procedural
- Communicational
- Sequential
- Functional
실무 적용 예인터페이스/DI 로 결합도 최소화SRP 적용으로 기능 명확히 분리
설계 원칙 연계DIP, ISP, OCPSRP, KISS, DRY
측정 기준인터페이스 수, 의존 객체 수기능 목적의 단일성, 내부 연관성
테스트낮을수록 단위 테스트 용이높을수록 단위 테스트 용이

배경

커플링과 응집도 개념은 1960 년대 후반 Larry Constantine 이 Structured Design 방법론의 일환으로 개발했다. Stevens, Myers & Constantine (1974) 논문과 Yourdon & Constantine (1979) 저서를 통해 정립되어 소프트웨어 공학의 표준 용어가 되었다.

목적 및 필요성

특징

주요 원리 및 작동 원리

graph TB
    A[소프트웨어 시스템] --> B[모듈 A]
    A --> C[모듈 B]
    A --> D[모듈 C]
    
    subgraph "커플링 (모듈 간 관계)"
        B -.->|낮은 커플링| C
        B -.->|낮은 커플링| D
        C -.->|낮은 커플링| D
    end
    
    subgraph "응집도 (모듈 내부)"
        B --> B1[기능1]
        B --> B2[기능2]
        B1 ---|높은 응집도| B2
        
        C --> C1[기능1]
        C --> C2[기능2]
        C1 ---|높은 응집도| C2
    end

낮은 결합도 (Low Coupling) 와 높은 응집도 (High Cohesion) 를 달성하기 위한 핵심 원칙

원칙설명적용 대상관련 품질 속성
SRP (Single Responsibility Principle)하나의 모듈은 하나의 책임만을 가져야 함클래스, 함수, 서비스응집도 향상
DIP (Dependency Inversion Principle)고수준 모듈이 저수준 모듈에 의존하지 않도록 추상화에 의존계층 간 통신, 모듈 간 의존성결합도 감소
ISP (Interface Segregation Principle)클라이언트가 사용하지 않는 인터페이스에 의존하지 않아야 함인터페이스 설계결합도 감소, 응집도 향상
OCP (Open/Closed Principle)기능 확장은 열려 있고 변경에는 닫혀 있어야 함모듈, 클래스 구조변경 최소화, 결합도 감소
DRY (Don’t Repeat Yourself)중복된 로직을 제거하고 재사용성을 높임함수, 유틸리티, 서비스응집도 향상
KISS (Keep It Simple, Stupid)단순한 구조와 설계를 유지전반적 아키텍처구조적 응집도 향상
모듈화 (Modularity)시스템을 작고 독립적인 구성 요소로 분리아키텍처, 프로젝트 구성결합도 감소, 응집도 향상
정보 은닉 (Encapsulation)객체 내부 구현을 외부에 노출하지 않음클래스, 객체결합도 감소

낮은 결합도와 높은 응집도를 위한 구현 기법

구현 기법정의구성 요소목적 / 효과실제 예시
인터페이스 기반 설계
(Interface-Based Design)
구현체가 아닌 추상화에 의존하여 설계- 인터페이스
- 다형성 구현체
- 팩토리 또는 DI
- 결합도 감소
- 확장성 향상
- PaymentProcessor 인터페이스
Java interface, Python ABC
의존성 주입 (DI)
(Dependency Injection)
필요한 의존성을 외부에서 주입- 인터페이스
- 구현체
- 주입 방식 (생성자, 세터 등)
DI 컨테이너
- 강한 결합 해소
- 테스트 용이
- Spring Framework, NestJS, FastAPI DI
모듈화 / 캡슐화
(Modularization / Encapsulation)
시스템을 기능 단위 모듈로 분리하고 내부 구현은 숨김- 기능별 디렉터리 구조
- 네임스페이스
- 접근 제어자
- 응집도 향상
- 내부 변경 영향 최소화
- Python 패키지, Java 모듈, npm 패키지
단일 책임 분리
(Single Responsibility Principle)
클래스나 모듈이 하나의 책임만 가지도록 분리- 책임 단위 기준 수립
- 역할 기반 분리
- 높은 응집도 확보
- 유지보수 용이성 증가
- OrderService vs PaymentService 분리
이벤트 기반 아키텍처
(Event-Driven Architecture)
이벤트를 중심으로 모듈 간 비동기 통신 구현- Publisher / Subscriber
Event Bus / Queue
- 메시지 포맷
- 느슨한 결합
- 확장성과 병렬 처리 가능
- Kafka, RabbitMQ, Custom EventBus
리팩토링
(Refactoring)
기능은 유지하면서 코드 구조를 개선하는 과정- 코드 스멜 탐지
- 책임 이동
- 중복 제거
- 응집도 증가
- 결합도 감소
- 유지보수성 향상
- Extract Method, Replace Inheritance with Composition
계층 분리
(Layered Architecture)
기능을 계층으로 나눠 책임 분리- Presentation Layer
Application Layer
Domain Layer
Infrastructure Layer
- 응집도 증가
- 결합도 감소 및 관심사 분리
- MVC, Clean Architecture, Onion Architecture

분류에 따른 종류 및 유형

커플링 유형

유형정의특징영향실무 고려사항권장 여부예시
Content Coupling(내용 결합)한 모듈이 다른 모듈의 내부 구현 (변수, 로직 등) 에 직접 접근가장 강한 결합내부 변경 시 외부 영향 큼유지보수성 낮음디버깅 어려움모듈 간 캡슐화 원칙 위배로 인해 위험❌ 피해야 함모듈 A 가 모듈 B 의 내부 변수에 직접 접근
Common Coupling(공통 결합)여러 모듈이 동일한 전역 변수나 공유 자원 사용모듈 간 간접 연결전역 상태 공유사이드 이펙트 발생 가능성 높음테스트 어려움, 상태 동기화 문제❌ 피하는 것이 바람직여러 모듈이 동일한 전역 변수 사용
External Coupling(외부 결합)외부 환경이나 프로토콜에 종속파일 포맷, 외부 API, 디바이스 종속성 존재외부 변경에 의한 영향 큼외부 API/파일 포맷에 의존할 경우 버전 관리 필수⚠ 통제 불가 외부 조건 시 불가피특정 파일 형식, 통신 프로토콜
Control Coupling(제어 결합)호출자가 호출 대상에게 제어 플래그 전달제어 흐름이 호출자에 의해 결정됨흐름 변경에 의존, 유연성 낮음책임이 불명확, 조건 분기 로직 증가⚠ 필요 최소한으로 제한함수에 동작 방식을 결정하는 플래그 전달
Stamp Coupling(스탬프 결합)복합 구조체 (객체, DTO 등) 를 전달하지만 일부 필드만 사용필요한 필드 외에도 전체 구조 전달인터페이스 불명확, 재사용성 낮음명확한 인터페이스 정의로 해결 가능⚠ 최소화 권장함수에 전체 객체를 전달하지만 일부 필드만 사용
Data Coupling(데이터 결합)간단한 데이터 (값, 기본 타입) 만 전달가장 약한 결합모듈 독립성 유지유연성 높고 재사용 쉬움인터페이스 명확, 유닛 테스트 용이✅ 적극 권장기본 데이터 타입만 매개변수로 전달
시나리오 기반 예시

시나리오: 주문 처리 시스템

결합도 유형별 문제점 및 리팩토링 요약

내용 결합 (Content Coupling)

문제 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# inventory.py
class Inventory:
    def __init__(self):
        self.stock = {'item1': 10}

# order.py
from inventory import Inventory

inventory = Inventory()
inventory.stock['item1'] -= 1  # 직접 접근하여 수정

문제점:

리팩토링 방안:

개선 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# inventory.py
class Inventory:
    def __init__(self):
        self.stock = {'item1': 10}

    def decrease_stock(self, item, quantity):
        if item in self.stock:
            self.stock[item] -= quantity

# order.py
from inventory import Inventory

inventory = Inventory()
inventory.decrease_stock('item1', 1)
공통 결합 (Common Coupling)

문제 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# common.py
GRAVITY = 9.8

# module_a.py
from common import GRAVITY
def calculate_force(mass):
    return mass * GRAVITY

# module_b.py
from common import GRAVITY
def calculate_potential_energy(mass, height):
    return mass * GRAVITY * height

문제점:

리팩토링 방안:

개선 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# physics.py
class Physics:
    GRAVITY = 9.8

    @staticmethod
    def calculate_force(mass):
        return mass * Physics.GRAVITY

    @staticmethod
    def calculate_potential_energy(mass, height):
        return mass * Physics.GRAVITY * height
외부 결합 (External Coupling)

문제 코드 (Python):

1
2
3
4
# data_reader.py
def read_data(file_path):
    with open(file_path, 'r') as file:
        return file.read()

문제점:

리팩토링 방안:

개선 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# reader_interface.py
from abc import ABC, abstractmethod

class DataReader(ABC):
    @abstractmethod
    def read(self, file_path):
        pass

# txt_reader.py
from reader_interface import DataReader

class TxtReader(DataReader):
    def read(self, file_path):
        with open(file_path, 'r') as file:
            return file.read()

# csv_reader.py
import csv
from reader_interface import DataReader

class CsvReader(DataReader):
    def read(self, file_path):
        with open(file_path, newline='') as csvfile:
            return list(csv.reader(csvfile))
제어 결합 (Control Coupling)

문제 코드 (Python):

1
2
3
4
5
6
7
def process_data(data, mode):
    if mode == 'json':
        # JSON 처리
        pass
    elif mode == 'xml':
        # XML 처리
        pass

문제점:

리팩토링 방안:

개선 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from abc import ABC, abstractmethod

class DataProcessor(ABC):
    @abstractmethod
    def process(self, data):
        pass

class JsonProcessor(DataProcessor):
    def process(self, data):
        # JSON 처리 로직
        pass

class XmlProcessor(DataProcessor):
    def process(self, data):
        # XML 처리 로직
        pass

def process_data(processor: DataProcessor, data):
    processor.process(data)
스탬프 결합 (Stamp Coupling)

문제 코드 (Python):

1
2
3
4
5
6
7
8
9
class Order:
    def __init__(self, id, customer, items, total):
        self.id = id
        self.customer = customer
        self.items = items
        self.total = total

def print_order_summary(order):
    print(f"Order ID: {order.id}")

문제점:

리팩토링 방안:

개선 코드 (Python):

1
2
def print_order_summary(order_id):
    print(f"Order ID: {order_id}")
데이터 결합 (Data Coupling)

예시 코드 (Python):

1
2
def calculate_discount(price, discount_rate):
    return price * discount_rate

특징:

응집도 유형

응집도 유형설명특징예시
우연적 응집 (Coincidental Cohesion)관련 없는 기능들이 우연히 하나의 모듈에 포함됨가장 낮은 응집도, 유지보수 어려움다양한 유틸리티 함수들이 하나의 클래스에 모여 있음
논리적 응집 (Logical Cohesion)유사한 기능들이 하나의 모듈에 포함되지만, 각 기능이 독립적으로 작동기능 간 연관성 약함입력 처리 모듈이 키보드, 마우스, 터치 입력을 모두 처리
시간적 응집 (Temporal Cohesion)동시에 실행되는 작업들이 하나의 모듈에 포함됨실행 시점이 동일하지만 기능 간 연관성 약함시스템 초기화 시 실행되는 설정 로딩, 로그 초기화 등
절차적 응집 (Procedural Cohesion)특정 순서로 실행되는 작업들이 하나의 모듈에 포함됨순서에 의존, 데이터 공유는 없음파일 열기 → 데이터 읽기 → 데이터 처리
통신적 응집 (Communicational Cohesion)동일한 데이터를 사용하는 작업들이 하나의 모듈에 포함됨데이터 중심, 기능 간 연관성 있음고객 정보 조회, 수정, 삭제 기능이 하나의 모듈에 포함됨
순차적 응집 (Sequential Cohesion)한 작업의 출력이 다음 작업의 입력이 되는 작업들이 하나의 모듈에 포함됨데이터 흐름 중심, 기능 간 강한 연관성데이터 수집 → 데이터 정제 → 데이터 저장
기능적 응집 (Functional Cohesion)모듈 내 모든 요소가 단일 기능 수행에 기여가장 높은 응집도, 이상적 구조수학 계산 모듈이 덧셈, 뺄셈, 곱셈, 나눗셈을 수행
시나리오 기반 예시

시나리오: 사용자 데이터 처리

우연적 응집 (Coincidental Cohesion)

문제 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Utility:
    def read_file(self, filename):
        # 파일 읽기
        pass

    def calculate_discount(self, price):
        # 할인 계산
        pass

    def send_email(self, recipient):
        # 이메일 전송
        pass

문제점:

리팩토링 방법:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class FileReader:
    def read_file(self, filename):
        pass

class DiscountCalculator:
    def calculate_discount(self, price):
        pass

class EmailSender:
    def send_email(self, recipient):
        pass
논리적 응집 (Logical Cohesion)

문제 코드 (Python):

1
2
3
4
5
6
7
8
9
class InputHandler:
    def handle_keyboard_input(self):
        pass

    def handle_mouse_input(self):
        pass

    def handle_touch_input(self):
        pass

문제점:

리팩토링 방법:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class KeyboardInputHandler:
    def handle_input(self):
        pass

class MouseInputHandler:
    def handle_input(self):
        pass

class TouchInputHandler:
    def handle_input(self):
        pass
시간적 응집 (Temporal Cohesion)

문제 코드 (Python):

1
2
3
4
5
6
7
8
9
class SystemInitializer:
    def load_config(self):
        pass

    def initialize_logger(self):
        pass

    def connect_to_database(self):
        pass

문제점:

리팩토링 방법:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class ConfigLoader:
    def load(self):
        pass

class LoggerInitializer:
    def initialize(self):
        pass

class DatabaseConnector:
    def connect(self):
        pass

class SystemInitializer:
    def initialize_system(self):
        ConfigLoader().load()
        LoggerInitializer().initialize()
        DatabaseConnector().connect()
절차적 응집 (Procedural Cohesion)

문제 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class DataProcessor:
    def process_data(self):
        self.read_data()
        self.transform_data()
        self.save_data()

    def read_data(self):
        pass

    def transform_data(self):
        pass

    def save_data(self):
        pass

문제점:

리팩토링 방법:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class DataReader:
    def read(self):
        pass

class DataTransformer:
    def transform(self, data):
        pass

class DataSaver:
    def save(self, data):
        pass

class DataProcessingPipeline:
    def process(self):
        data = DataReader().read()
        transformed = DataTransformer().transform(data)
        DataSaver().save(transformed)
통신적 응집 (Communicational Cohesion)

문제 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 문제 코드 - 하나의 클래스가 모든 고객 관련 기능을 처리
class CustomerDataHandler:
    def __init__(self, db):
        self.db = db

    def retrieve_customer_info(self, customer_id):
        return self.db.query(f"SELECT * FROM customers WHERE id = {customer_id}")

    def update_customer_info(self, customer_id, data):
        return self.db.execute(f"UPDATE customers SET name = '{data['name']}' WHERE id = {customer_id}")

    def delete_customer_info(self, customer_id):
        return self.db.execute(f"DELETE FROM customers WHERE id = {customer_id}")

문제점:

리팩토링 방법:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 데이터 접근 책임 분리 (`CustomerRepository`)
class CustomerRepository:
    def __init__(self, db):
        self.db = db

    def find_by_id(self, customer_id):
        return self.db.query(f"SELECT * FROM customers WHERE id = {customer_id}")

    def update(self, customer_id, data):
        return self.db.execute(f"UPDATE customers SET name = '{data['name']}' WHERE id = {customer_id}")

    def delete(self, customer_id):
        return self.db.execute(f"DELETE FROM customers WHERE id = {customer_id}")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 비즈니스 로직 책임 분리 (`CustomerService`)
class CustomerService:
    def __init__(self, repository: CustomerRepository):
        self.repository = repository

    def get_customer_info(self, customer_id):
        return self.repository.find_by_id(customer_id)

    def update_customer(self, customer_id, data):
        return self.repository.update(customer_id, data)

    def delete_customer(self, customer_id):
        return self.repository.delete(customer_id)
순차적 응집 (Sequential Cohesion)

문제 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class DataPipeline:
    def execute(self):
        data = self.extract_data()
        transformed = self.transform_data(data)
        self.load_data(transformed)

    def extract_data(self):
        pass

    def transform_data(self, data):
        pass

    def load_data(self, data):
        pass

문제점:

리팩토링 방법:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class DataExtractor:
    def extract(self):
        print("Extracting data")
        return "raw data"

class DataTransformer:
    def transform(self, data):
        print("Transforming data")
        return data.upper()

class DataLoader:
    def load(self, data):
        print(f"Loading data: {data}")

class DataPipeline:
    def __init__(self, extractor, transformer, loader):
        self.extractor = extractor
        self.transformer = transformer
        self.loader = loader

    def execute(self):
        data = self.extractor.extract()
        transformed = self.transformer.transform(data)
        self.loader.load(transformed)
기능적 응집 (Functional Cohesion)

문제 코드 (Python):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class MathOperations:
    def add(self, x, y):
        return x + y

    def subtract(self, x, y):
        return x - y

    def multiply(self, x, y):
        return x * y

    def divide(self, x, y):
        return x / y

문제점:

리팩토링 방법:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Addition:
    def compute(self, x, y):
        return x + y

class Subtraction:
    def compute(self, x, y):
        return x - y

class Multiplication:
    def compute(self, x, y):
        return x * y

class Division:
    def compute(self, x, y):
        return x / y

장점과 단점

구분항목설명
✅ 장점유지보수성 향상모듈 간 독립성으로 인해 변경 영향 범위 최소화
재사용성 증대독립적인 모듈을 다른 프로젝트에서 재사용 가능
테스트 용이성각 모듈을 독립적으로 단위 테스트 가능
확장성새로운 기능 추가 시 기존 코드 영향 최소화
병렬 개발팀원들이 독립적인 모듈을 동시에 개발 가능
가독성 향상명확한 책임 분리로 코드 이해 용이
⚠️ 단점초기 복잡도 증가설계 단계에서 더 많은 시간과 노력 필요
성능 오버헤드모듈 간 통신으로 인한 런타임 비용
과도한 추상화불필요한 인터페이스로 인한 복잡성 증가
일관성 관리 어려움분산된 모듈 간 데이터 일관성 유지 복잡
디버깅 복잡성모듈 간 상호작용 추적의 어려움

도전 과제 및 해결책

도전 과제설명해결책상세 전략 / 기술
모듈 간 강한 결합하나의 모듈 변경이 다른 모듈에 파급 영향의존성 주입 (DI), 인터페이스 분리DIP, IoC 컨테이너, 인터페이스 기반 설계
낮은 응집도모듈 내 기능 간 연관성이 낮아 코드가 분산됨단일 책임 원칙 (SRP), 기능 단위 모듈화SRP, 기능 중심 디렉터리 구조
테스트 어려움결합도 높고 응집도 낮아 단위 테스트 불가모듈 분리, 의존성 주입, Mock 객체 활용TDD, 테스트 더블 (Mock, Stub), pytest, unittest
변경 전파 위험한 곳 변경 시 연쇄적 영향 발생모듈 경계 명확화, 계층 아키텍처 적용계층적 설계 (Presentation-Application-Domain-Infrastructure)
과도한 추상화불필요하게 복잡한 계층, 인터페이스 설계변경 요구에 맞춘 점진적 리팩토링실제 요구 중심 추상화, YAGNI 원칙 적용
추상화 부족구체 구현에 의존 → 테스트 및 변경 어려움인터페이스 도입, 전략 패턴 활용인터페이스, 팩토리 패턴, OCP 적용
성능 vs 유연성느슨한 결합은 성능 저하 유발 가능병목 지점 파악 후 선택적 최적화프로파일링 도구, 캐싱, CQRS 분리
분산 시스템 일관성마이크로서비스 간 데이터 일관성 유지 어려움이벤트 소싱, Saga, CQRS 패턴Kafka, EventBridge, Outbox 패턴
인터페이스 변경 위험인터페이스 변경 시 다른 팀/모듈에 영향계약 테스트, API 버전 관리Pact, Swagger, OpenAPI, SemVer
모듈 과도 분리너무 많은 모듈로 인한 복잡도 증가유사 책임 통합, 도메인 중심 모듈화DDD, Bounded Context 설계
협업 및 코드 일관성다양한 설계 스타일, 코드 리뷰 난이도코드 리뷰 가이드, 자동화 도구SonarQube, ESLint, Black, Prettier
지속적 품질 유지시간 지남에 따라 설계 원칙 붕괴 위험주기적 리팩토링 및 리뷰 프로세스리팩토링 스프린트, 코드 헬스 체크
도메인과 설계 간 괴리기술 중심 구조로 도메인 이해도 저하도메인 모델 중심 아키텍처 설계DDD (Domain-Driven Design)

실무 적용 예시

분야적용 사례커플링 감소 방법응집도 향상 방법
웹 애플리케이션MVC 아키텍처Controller-Service-Repository 계층 분리각 계층별 단일 책임 할당
마이크로서비스서비스 분해API Gateway, 이벤트 스트리밍도메인별 서비스 분할
모바일 앱MVVM 패턴데이터 바인딩, 옵저버 패턴View 별 ViewModel 분리
라이브러리 설계플러그인 시스템인터페이스 기반 확장기능별 플러그인 모듈화
데이터베이스ORM 계층Repository 패턴엔티티별 Repository 분리

활용 사례

사례 1: 전자상거래 플랫폼

시나리오: 대규모 전자상거래 플랫폼의 마이크로서비스 아키텍처 설계
시스템 구성:

graph TB
    subgraph "Frontend"
        Web[웹 앱]
        Mobile[모바일 앱]
    end
    
    subgraph "API Gateway"
        Gateway[API Gateway]
    end
    
    subgraph "Core Services"
        User[사용자 서비스]
        Product[상품 서비스]
        Order[주문 서비스]
        Payment[결제 서비스]
        Inventory[재고 서비스]
    end
    
    subgraph "Supporting Services"
        Notification[알림 서비스]
        Analytics[분석 서비스]
        Search[검색 서비스]
    end
    
    subgraph "Data Layer"
        EventStore[(이벤트 스토어)]
        UserDB[(사용자 DB)]
        ProductDB[(상품 DB)]
        OrderDB[(주문 DB)]
    end
    
    Web --> Gateway
    Mobile --> Gateway
    Gateway --> User
    Gateway --> Product
    Gateway --> Order
    Gateway --> Payment
    
    Order -.->|이벤트| EventStore
    Payment -.->|이벤트| EventStore
    Inventory -.->|이벤트| EventStore
    
    EventStore -.-> Notification
    EventStore -.-> Analytics
    
    User --> UserDB
    Product --> ProductDB
    Order --> OrderDB

워크플로우:

  1. 주문 생성: 고객이 주문 생성 → Order Service 가 주문 정보 저장
  2. 재고 확인: Order Service 가 ‘ORDER_CREATED’ 이벤트 발행 → Inventory Service 가 재고 확인
  3. 결제 처리: 재고 확인 완료 후 ‘INVENTORY_RESERVED’ 이벤트 → Payment Service 가 결제 처리
  4. 완료 처리: 결제 완료 후 ‘PAYMENT_COMPLETED’ 이벤트 → Order Service 가 주문 상태 업데이트
  5. 알림 발송: 각 단계별 이벤트 → Notification Service 가 고객에게 알림 발송

각 서비스의 역할:

실무에서 효과적으로 적용하기 위한 고려사항 및 주의할 점

고려사항설명권장사항 / 적용 전략
기능별 모듈화관련된 기능을 하나의 모듈로 묶어 높은 응집도 유지단일 책임 원칙 (SRP), DDD 의 Bounded Context 기반 기능 분리
모듈 간 명확한 경계모듈 간 책임과 범위를 명확히 하여 불필요한 의존 제거모듈 인터페이스 설계 명확화, 외부 접근 제한 (private, internal, 패키지 분리 등)
인터페이스 기반 설계구현에 의존하지 않고 인터페이스에 의존하게 하여 결합도 완화Interface Segregation Principle(ISP), DIP 적용
의존성 관리의존 대상 변경이 전체 시스템에 영향을 주지 않도록 관리의존성 주입 (DI), 팩토리/어댑터 패턴, IoC 컨테이너 활용
계층 아키텍처 적용관심사를 분리하여 설계의 응집도 확보 + 결합도 완화Presentation / Application / Domain / Infrastructure 계층 구분
테스트 가능성 확보모듈이 독립적으로 테스트 가능한 구조로 설계의존성 주입을 통한 Mock 대체 가능 구조, 유닛 테스트 우선
API 계약 명세화모듈 간 API 및 데이터 계약이 변경되었을 때 오류 방지Swagger, OpenAPI, Pact (Contract Testing) 활용
레거시 시스템 대응기존 모놀리식 시스템에서 점진적 개선이 가능하도록 적용리팩토링 시 우선순위 지정, 모듈 단위 개선부터 시작
도메인 중심 구조비즈니스 도메인을 중심으로 기능 및 책임 분리 → 설계 응집도 향상도메인 주도 설계 (DDD), Aggregate / Entity / Value Object 구분
성능 고려과도한 분리로 인해 발생하는 호출 비용이나 오버헤드에 주의이벤트 기반 아키텍처, CQRS, 성능 병목 파악 후 선택적 최적화
개발자 커뮤니케이션인터페이스나 경계 정의가 불명확하면 팀 간 협업 시 충돌 발생공유 문서화, API 설계 리뷰, 도메인 공유 세션 운영
리팩토링 주기화시간이 지나며 응집도는 낮아지고 결합도는 높아지는 구조적 부패 방지SonarQube, 코드 리뷰, 정적 분석, 리팩토링 스프린트 설정

결합도 감소 & 응집도 증가를 위한 리팩토링 단계별 가이드

1 단계: 현황 분석
항목설명
🔍 의존성 맵 작성모듈 간 직접 참조, 순환 참조, 전역 변수 사용 등을 시각화 (Structure101, Dependency Cruiser, SonarQube 등 활용)
📊 결합도/응집도 진단각 클래스 또는 모듈별 책임의 집중도와 외부 호출 관계 분석 (CodeScene, JDepend 등)
🔁 변경 이력 확인Git 로그/PR 에서 자주 변경되는 파일 조합을 분석 (Hotspot 분석)
2 단계: 모듈 책임 재정의 및 리패키징
항목설명
📁 관심사 기준 리패키징기능/도메인 중심으로 패키지나 디렉터리 구조를 재구성 (예: order/, payment/)
📌 SRP(Single Responsibility Principle) 적용하나의 클래스/모듈이 하나의 책임만 가지도록 분리
📦 공통 책임 분리Utility, Helper, Validator 등 역할이 중복된 부분을 공용 모듈로 분리
✅ 결과응집도 증가 (기능 밀접도↑), 클래스 간 관계 간결화
3 단계: 결합도 감소를 위한 의존성 전환
항목설명
🔁 직접 의존 → 인터페이스 추상화구현체 직접 호출을 인터페이스로 대체하여 DIP 적용
🧩 의존성 주입 (DI) 적용생성자, 팩토리, 프레임워크 (Dagger, Spring, NestJS 등) 를 통한 주입 구조 전환
✂ 순환 참조 제거두 모듈이 서로를 호출하면 중간 인터페이스 또는 메시징을 도입
✅ 결과테스트 용이성 확보, 변경 시 영향 범위 최소화

예시 (Python)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Before
class OrderService:
    def process(self):
        payment = PaymentService()
        payment.charge()

# After
class IPaymentService:
    def charge(self): pass

class OrderService:
    def __init__(self, payment: IPaymentService):
        self.payment = payment
4 단계: 상호작용 구조 재설계 (느슨한 결합)
항목설명
📡 이벤트 기반 구조 도입Kafka, RabbitMQ, EventEmitter 등을 사용해 직접 호출 제거
🌉 Anti-Corruption Layer외부 시스템이나 레거시 모듈과 연결 시 중간 계층 도입
🎯 인터페이스 계약 명확화DTO(Data Transfer Object), OpenAPI 문서화 등으로 명확한 인터페이스 정의
✅ 결과유연성 향상, 독립 배포 가능 구조 확보
5 단계: 응집도 극대화를 위한 도메인 중심 재구성
항목설명
🧠 도메인 모델 도입DDD (Domain-Driven Design) 방식으로 도메인마다 모델/서비스 구성
📌 Aggregate 중심 책임 통합한 도메인 내에서 밀접한 기능은 하나의 서비스/클래스에서 관리
📁 모듈 단위 유틸 제거도메인 외부에서만 사용하는 유틸리티 분리 (DRY 원칙 재점검)
✅ 결과기능 중심 구조 → 의미 기반 구조로 전환됨 (재사용성과 명확성↑)
6 단계: 자동화 기반 리팩토링 품질 확보
항목설명
🧪 테스트 커버리지 강화단위 테스트, 통합 테스트를 통해 변경 영향 최소화
🔍 정적 분석 도구 통합SonarQube, ESLint, PMD 등으로 구조/복잡도 지속 분석
🧪 테스트 기반 리팩토링 (TDD)변경 전에 테스트를 작성하여 의도된 동작을 보장
✅ 결과리팩토링 품질 확보, 회귀 방지

최적화하기 위한 고려사항

고려사항설명권장사항 및 적용 전략
모듈 간 통신 최적화느슨한 결합으로 인한 과도한 원격 호출, 네트워크 비용 발생모듈 간 직접 호출 대신 이벤트 기반 통신, 캐싱, 동기/비동기 조합 설계
데이터 일관성 유지느슨한 결합 구조에서 데이터 동기화가 지연되거나 불일치 발생 가능이벤트 소싱 (Event Sourcing), CQRS, Saga 패턴을 통해 일관성 지연 허용 및 복구 가능 구조 설계
과도한 추상화 오버헤드계층 분리 또는 설계 유연성을 위해 도입한 추상화가 성능 병목으로 이어질 수 있음필수적 계층만 유지, 경량화된 인터페이스 정의, 의존성 최소화 (특히 실시간 경로)
모듈 크기 최적화너무 작게 쪼개진 모듈은 호출 비용 증가, 너무 큰 모듈은 응집도 저하도메인 중심으로 모듈 크기를 조정하여 응집도 높이고, 호출 경로 최소화
캐시 및 리소스 활용재사용 가능한 계산 결과나 데이터에 대한 반복 요청 발생 시 성능 저하응집도 높은 모듈 단위로 캐싱 적용 (예: 서비스 레벨 캐시, DAO 캐시), Redis/Memcached 활용
비동기/배치 처리 설계실시간 처리가 불필요한 작업까지 동기 호출로 처리할 경우 응답 지연모듈 간 결합을 이벤트/메시지 큐로 분리하여 비동기 처리, Kafka, RabbitMQ, AWS SQS 활용
DB 접근 최적화응집도 낮은 DAO, Repository 가 무분별한 쿼리 호출 시 N+1 문제 발생배치 로딩 (fetch join), 응집도 높은 단위로 트랜잭션 범위 최소화 설계
자원 관리 일관성여러 모듈에서 동일 자원을 관리하며 충돌 발생 가능자원에 대한 책임을 명확히 분리하여 단일 모듈에서 관리하도록 설계
장애 전파 방지결합된 모듈 중 하나의 장애가 전체 서비스 중단으로 확산될 수 있음Circuit Breaker, Timeout, Fallback 설계 (Resilience4j, Hystrix)
로깅 및 모니터링성능 병목 지점이나 모듈간 통신 트래픽 파악이 어려운 경우 분석 불가로그 상호연관 ID 설정 (trace ID), APM 도구 (New Relic, Datadog, Jaeger 등) 활용

하위 주제별 추가 학습 내용

카테고리주제설명
고급 개념Connascence커플링의 더 정교한 분류 체계
의존성 그래프 분석시스템 의존성 시각화 및 분석
설계 방법론도메인 주도 설계 (DDD)비즈니스 도메인 기반 모듈 분할
이벤트 스토밍도메인 이벤트 식별 및 서비스 경계 정의
구현 기술의존성 주입 프레임워크Spring, Guice, Dagger 등
메시지 큐 시스템RabbitMQ, Apache Kafka, Amazon SQS
측정 및 분석코드 메트릭커플링과 응집도 측정 도구
아키텍처 테스트ArchUnit 을 통한 아키텍처 규칙 검증
설계 패턴디자인 패턴과 결합도/응집도패턴별 결합도/응집도 최적화 전략

주제와 관련하여 추가적으로 학습해야 할 내용

카테고리주제간략한 설명
설계 원칙SOLID 원칙객체 지향 설계의 5 가지 원칙으로, 응집도와 결합도에 직접적인 영향을 미침
GRASP 패턴객체 지향 설계에서 책임 할당에 대한 9 가지 원칙으로, 응집도와 결합도에 대한 지침을 제공
정보 은닉 (Information Hiding)모듈의 내부 구현을 숨기고, 인터페이스를 통해 상호작용하여 결합도를 낮추는 설계 원칙
캡슐화 (Encapsulation)데이터와 메서드를 하나의 단위로 묶어, 모듈의 응집도를 높이는 설계 원칙
아키텍처 패턴마이크로서비스, 레이어드결합도/응집도 중심 아키텍처 패턴
도구의존성 분석, 코드 시각화결합도/응집도 진단 및 개선 도구
테스트단위/통합 테스트결합도/응집도와 테스트 전략
보안모듈 경계 보안결합도 완화와 보안성 강화

관련 분야별 학습 내용

관련 분야주제설명
클라우드 컴퓨팅서버리스 아키텍처Function as a Service 의 결합도 특성
컨테이너 오케스트레이션Kubernetes 의 마이크로서비스 관리
데이터 엔지니어링데이터 파이프라인ETL/ELT 프로세스의 모듈화
스트림 처리Apache Kafka Streams, Apache Flink
보안API 보안마이크로서비스 간 인증/인가
제로 트러스트분산 시스템 보안 모델
DevOpsCI/CD 파이프라인독립적인 서비스 배포 전략
모니터링분산 추적, 로그 집계

용어 정리

용어설명
LCOM (Lack of Cohesion in Methods)클래스 메서드 간의 응집도를 측정하는 정량적 메트릭
CBO (Coupling Between Objects)클래스 간 결합도 수치를 나타내는 메트릭
모듈화 (Modularization)시스템을 독립적이고 재사용 가능한 구성 요소로 분할하는 설계 기법
의존성 주입 (Dependency Injection)객체의 의존성을 외부에서 주입받아 결합도를 낮추는 설계 패턴
단일 책임 원칙 (Single Responsibility Principle, SRP)클래스나 모듈은 하나의 책임만을 가져야 한다는 원칙
인터페이스 분리 원칙 (Interface Segregation Principle, ISP)사용하지 않는 메서드에 의존하지 않도록 인터페이스를 분리하는 원칙
의존성 역전 원칙 (Dependency Inversion Principle, DIP)고수준 모듈이 저수준 모듈이 아닌 추상화에 의존하도록 설계
관심사 분리 (Separation of Concerns)기능과 책임을 분리하여 각 구성 요소의 응집도를 높이는 설계 원칙
정보 은닉 (Information Hiding)모듈의 내부 구현 세부사항을 외부에 숨기고, 인터페이스만 노출
이벤트 소싱 (Event Sourcing)상태 변경을 이벤트로 저장하여, 이를 기반으로 현재 상태를 재구성하는 패턴
CQRS (Command Query Responsibility Segregation)읽기 (조회) 와 쓰기 (명령) 모델을 명확히 분리하는 설계 방식
API 게이트웨이 (API Gateway)마이크로서비스 환경에서 클라이언트 요청을 단일 진입점으로 수렴하는 구성 요소

참고 및 출처

  1. GeeksforGeeks - Coupling and Cohesion
  2. GeeksforGeeks - Coupling and Cohesion in System Design
  3. Wikipedia - Coupling (computer programming)
  4. Wikipedia - Cohesion (computer science)
  5. Loose coupling - Wikipedia
  6. Interface Segregation Principle - Wikipedia
  7. Single Responsibility Principle - Wikipedia
  8. Separation of Concerns - Wikipedia
  9. Better Software Design With Coupling and Cohesion - OmbuLabs
  10. Coupling and Cohesion in Software Engineering - Hero Vired
  11. Coupling and Cohesion - Engati Glossary
  12. Coupling and Cohesion - Scaler Topics
  13. The Valuable Dev - Cohesion and Coupling Guide with Examples
  14. CodeOpinion - SOLID? Nope, just Coupling and Cohesion
  15. Medium - Difference Between Cohesion and Coupling with Real-Life Example
  16. LinkedIn - Software Engineering Principle: Coupling & Cohesion
  17. LinkedIn - The Role of Code Coupling and Cohesion in Developing Applications
  18. Coupling and Cohesion: The Two Principles for Effective Architecture - ByteByteGo
  19. GraphAI - Coupling vs Cohesion: 이해와 차이점 정리
  20. SOA Design Principle: Coupling, Cohesion, and Granularity - francescolelli.info
  21. Examining Software Coupling and Cohesion Patterns using Social Network Analysis - IJCA (PDF)
  22. Types of Cohesion and Coupling - Study Material (PDF)