본문 바로가기

Programming/Design pattern

[Design pattern] 컴포지트(Composite) 패턴

컴포지트(Composite) 패턴

컴포지트(Composite)패턴은 객체들의 관계를 트리 구조로 구성하여 부분-전체 계층을 표현하는 형태로 개별 객체와 복합 객체를 동일하게 다룰 수 있도록 만드는 구조 패턴입니다. 

컴포지트 패터은 다음과 같은 경우에 사용합니다.

  • 트리 구조(예: 파일/디렉토리, 조직도, 메뉴 구조)를 다룰 때
  • 단일 요소와 복합 요소를 동일한 방식으로 처리해야 할 때
  • 재귀적으로 동작하거나 계층적인 처리를 구현할 때

컴포지트 패턴 구조

[출처] https://ko.wikipedia.org/wiki/%EC%BB%B4%ED%8F%AC%EC%A7%80%ED%8A%B8_%ED%8C%A8%ED%84%B4

 

컴포지트 패턴은 3가지 구성 요소로 이루어져있습니다.

  • Component 
    • Leaf와 Composite 모두가 구현해야할 공통 메소드들을 정의함
  • Leaf 
    • 하위 요소를 포함하지 않는 가장 기본 단위(실제 객체)
  • Composite
    • 다른 Component 객체들을 자식으로 보유하며, 자식들에게 동일한 동작을 위임함

 

컴포지트 패턴 예제

컴포지트 패턴을 설명하기 위해 간단한 문서 시스템을 예제로 구현해보도록 합니다.

문서에는 텍스트,이미지,섹션 같은 요소가 포함됩니다.

하나의 섹션 안에는 또 다른 요소들을 포함할 수 있습니다.

최종적으로는 render()를 호출하여 화면을 출력합니다.

 

Componet interface

class DocumentElement:
    def render(self, indent=0):
        raise NotImplementedError()

 

컴포넌트 인터페이스로 Leaf(텍스트,이미지)와 Composite(섹션) 모두 해당 인터페이스를 상속받습니다.

 

Leaf (단일 요소)

class Text(DocumentElement):
    def __init__(self, content):
        self.content = content

    def render(self, indent=0):
        print(" " * indent + f"Text: {self.content}")

 

class Image(DocumentElement):
    def __init__(self, path):
        self.path = path

    def render(self, indent=0):
        print(" " * indent + f"Image: {self.path}")

Leaf 객체들입니다. Component 인터페이스를 상속받고, render 함수를 구현합니다.

 

Composite(복합요소)

class Section(DocumentElement):
    def __init__(self, title):
        self.title = title
        self.children = []

    def add(self, element: DocumentElement):
        self.children.append(element)

    def render(self, indent=0):
        print(" " * indent + f"Section: {self.title}")
        for child in self.children:
            child.render(indent + 2)

Section 클래스는 자기 아네 다른 요소들(DocumentElement)를 포함할 수 있습니다.

render()함수는 재귀적으로 모든 하위 요소를 출력합니다.

 

컴포지트 패턴 장/단점

장점

1. 단순화된 클라이언트 코드

  • 요소가 단일이든 복합적 요소이든 똑같이 다룰 수 있음

2. 유연한 구조

  • 트리 형태로 자유롭게 구성 가능

3. 재귀적 구성 가능

  • Section 안에 또 Section 가능 (무한 중첩)

4. OCP 원칙 만족

  • 새로운 요소 추가 시 기존 구조 변경 불필요

 

단점

1. 디버깅이 어려움

  • 트리 구조가 복잡해지면 추적이 어려움

2. 설계가 과할 수 있음

  • 단순한 목록 처리에는 오히려 과한 구조가 될 수 있음

3. 요소 간 결합도 존재

  • 중첩 구조가 깊어질수록 코드 흐름 파악이 어려워질 수 있음

 

 

컴포지트 패턴은 계층적 구조를 구성할 때 매우 강력한 패턴입니다.
개별 요소와 그룹 요소를 같은 인터페이스로 추상화함으로써,
복잡한 구조를 간단하게 관리하고 렌더링하거나 처리할 수 있게 해줍니다.