컴포지트 패턴(Composite Pattern)은 객체들을 트리 구조로 구성하여 부분-전체 계층을 표현하는 구조적 디자인 패턴이다. 이 패턴을 사용하면 클라이언트가 단일 객체(Leaf)와 복합 객체(Composite)를 동일하게 다룰 수 있어, 재귀적 구조를 단순하고 일관되게 처리할 수 있다.
개요
컴포지트 패턴의 정의
컴포지트 패턴은 개별 객체와 복합 객체를 같은 타입으로 취급하여, 동일한 인터페이스를 통해 다룰 수 있게 한다. 트리 구조로 이루어진 계층적 데이터를 처리할 때 특히 유용하며, 클라이언트는 전체 구조를 신경 쓰지 않고 동일한 방식으로 모든 요소를 처리할 수 있다.
패턴의 필요성 및 사용 사례
컴포지트 패턴은 다음과 같은 상황에서 유용하다:
- 파일 시스템: 파일과 폴더를 동일하게 취급
- GUI 컴포넌트: 버튼, 패널, 윈도우 등을 계층적으로 구성
- 조직 구조: 직원과 부서를 트리 형태로 표현
- 메뉴 시스템: 메뉴 항목과 서브메뉴를 동일하게 처리
- 그래픽 편집기: 기본 도형과 그룹화된 도형을 동일하게 다룸
패턴의 장점과 단점
| 장점 | 단점 |
|---|---|
| 단일/복합 객체를 동일하게 처리 | 지나치게 일반적인 설계가 될 수 있음 |
| 새로운 종류의 컴포넌트 추가 용이 | 컴포넌트 타입 제한이 어려움 |
| 재귀적 구조 처리 단순화 | 공통 인터페이스 설계가 어려울 수 있음 |
| 클라이언트 코드 단순화 | Leaf에서 불필요한 메서드 구현 필요 |
컴포지트 패턴의 구성 요소
| |
1. Component (컴포넌트)
- 모든 객체(Leaf와 Composite)의 공통 인터페이스 정의
- 기본 동작과 자식 관리 메서드 선언
- 필요에 따라 기본 구현 제공
2. Leaf (리프)
- 더 이상 자식이 없는 말단 객체
- Component 인터페이스의 실제 동작 구현
- 자식 관리 메서드는 보통 빈 구현이거나 예외 발생
3. Composite (컴포지트)
- 자식 컴포넌트를 포함하는 복합 객체
- 자식 추가/제거/조회 메서드 구현
- operation()에서 자식들의 operation()을 재귀적으로 호출
구현 예제
Python 예제 - 파일 시스템
| |
Java 예제 - 조직 구조
| |
C# 예제 - 메뉴 시스템
| |
실제 사용 사례
1. Java Swing/AWT
| |
2. DOM (Document Object Model)
| |
3. React 컴포넌트
| |
4. 파일 시스템 API
운영체제의 파일 시스템이 파일과 디렉토리를 동일하게 다루는 전형적인 예이다.
관련 패턴
| 패턴 | 컴포지트와의 관계 |
|---|---|
| Decorator | 둘 다 재귀적 합성 사용, Decorator는 기능 추가에 초점 |
| Iterator | 컴포지트 구조를 순회할 때 사용 |
| Visitor | 컴포지트 구조의 요소들에 연산을 적용할 때 사용 |
| Flyweight | 공유 가능한 Leaf 노드를 플라이웨이트로 구현 |
FAQ
Q1: Leaf에서 자식 관리 메서드를 어떻게 처리해야 하나요?
두 가지 접근 방식이 있습니다. 1) 예외를 발생시키거나, 2) 빈 구현을 제공합니다. 투명성(Transparency)을 위해서는 Component에 모든 메서드를 두고, 안전성(Safety)을 위해서는 Composite에만 자식 관리 메서드를 둡니다.
Q2: 순환 참조 문제는 어떻게 방지하나요?
add() 메서드에서 순환 참조를 검사하거나, 부모 참조를 유지하여 이미 조상에 있는 컴포넌트는 추가할 수 없도록 해야 합니다.
Q3: 컴포지트 패턴에서 자식 순서가 중요한가요?
애플리케이션에 따라 다릅니다. GUI 컴포넌트에서는 순서가 렌더링 순서에 영향을 미치지만, 파일 시스템에서는 보통 중요하지 않습니다.
Q4: 특정 타입의 컴포넌트만 추가하도록 제한할 수 있나요?
타입 검사를 통해 가능하지만, 이는 컴포지트 패턴의 균일성 원칙에 어긋납니다. 필요하다면 별도의 패턴이나 제약 조건을 추가해야 합니다.
참고 자료
- GoF의 “Design Patterns: Elements of Reusable Object-Oriented Software”
- Head First Design Patterns
- Java Swing API 문서
![Featured image of post [Design Pattern] Composite - 컴포지트 패턴](/post/designpattern/08_composite/tmp_wordcloud_hu_9da2c58100831efd.png)
![[Design Pattern] Adapter - 어댑터 패턴](/post/designpattern/06_adapter/tmp_wordcloud_hu_9c98c3aa5074382f.png)
![[Design Pattern] Bridge - 브릿지 패턴](/post/designpattern/07_bridge/tmp_wordcloud_hu_83e6bad072544abf.png)
![[Design Pattern] Composite - 컴포지트 패턴](/post/designpattern/08_composite/tmp_wordcloud_hu_127f86e1fcdf3b3b.png)
![[Design Pattern] Decorator - 데코레이터 패턴](/post/designpattern/09_decorator/tmp_wordcloud_hu_2fe4899ffc2b9123.png)
![[Design Pattern] Facade - 퍼사드 패턴](/post/designpattern/10_facade/tmp_wordcloud_hu_2a2ec8eb7cdad284.png)
![[Design Pattern] Iterator - 반복자 패턴](/post/designpattern/17_iterator/tmp_wordcloud_hu_7d58ede73554457e.png)