컴포지트 composite 패턴 - 자바스크립트 예제

SW설계
읽는데 4분 소요
처음 쓰여진 날: 2025-09-01
마지막 수정일: 2025-09-01

요약

컴포지트(Composite) 패턴을 자바스크립트 코드와 함께 알아봅니다. 정보처리기사 대비 문제가 포함되어있습니다.

컴포지트 패턴 요약

패턴 종류핵심 키워드
컴포지트 (Composite)트리 구조, 부분-전체 계층 표현
컴포지트 패턴 감자
컴포지트 패턴 감자

컴포지트 패턴은 객체들을 트리 구조로 구성하여 '부분-전체' 계층을 표현하는 디자인 패턴입니다. 이 패턴을 사용하면 클라이언트가 개별 객체(Leaf)와 복합 객체(Composite)를 동일한 방식으로 다룰 수 있습니다. 즉, 단일 객체이든 여러 객체로 이루어진 집합이든 똑같은 인터페이스로 제어할 수 있게 됩니다.

가장 대표적인 예는 컴퓨터의 파일 시스템입니다. 폴더(복합 객체) 안에는 다른 폴더나 파일(개별 객체)이 들어갈 수 있습니다. 사용자는 폴더와 파일을 구분하지 않고 '이름 변경', '삭제' 등의 동일한 작업을 수행할 수 있습니다.

기본 구조

  • Component: Leaf와 Composite가 모두 구현해야 하는 공통 인터페이스입니다. 트리 구조의 모든 객체에 대한 일관된 작업을 정의합니다.
  • Leaf: 트리의 가장 말단에 있는 개별 객체입니다. 자식을 가지지 않습니다. (예: 파일)
  • Composite: 자식(Leaf 또는 다른 Composite)을 가질 수 있는 복합 객체입니다. 자식들을 관리하는 메서드(add, remove 등)를 구현하며, Component 인터페이스의 메서드를 자식들에게 재귀적으로 전달합니다. (예: 폴더)

예시: 파일 시스템 표현하기

파일과 폴더로 구성된 간단한 파일 시스템을 컴포지트 패턴으로 구현해 보겠습니다.

javascript
// Component: 공통 인터페이스
class FileSystemComponent {
  constructor(name) {
    this.name = name;
  }

  // 모든 컴포넌트가 공통으로 가질 작업
  display(indent = "") {
    throw new Error("display() 메서드는 반드시 구현되어야 합니다.");
  }

  // Composite 객체에서만 의미 있는 메서드들
  add(component) {
    throw new Error("이 객체에는 자식을 추가할 수 없습니다.");
  }

  remove(component) {
    throw new Error("이 객체에서는 자식을 제거할 수 없습니다.");
  }
}

// Leaf: 개별 파일
class File extends FileSystemComponent {
  constructor(name, size) {
    super(name);
    this.size = size;
  }

  display(indent = "") {
    console.log(`${indent}- ${this.name} (${this.size}KB)`);
  }
}

// Composite: 폴더
class Folder extends FileSystemComponent {
  constructor(name) {
    super(name);
    this.children = [];
  }

  add(component) {
    this.children.push(component);
  }

  remove(component) {
    const index = this.children.indexOf(component);
    if (index > -1) {
      this.children.splice(index, 1);
    }
  }

  display(indent = "") {
    console.log(`${indent}+ ${this.name}`);
    // 자식들에게 재귀적으로 display 호출
    this.children.forEach((child) => {
      child.display(indent + "  ");
    });
  }
}

// 클라이언트 코드
const root = new Folder("root");
const documents = new Folder("문서");
const music = new Folder("음악");

const file1 = new File("이력서.docx", 120);
const file2 = new File("프로젝트_계획.pdf", 340);
const song1 = new File("아이유 - 밤편지.mp3", 4500);

documents.add(file1);
documents.add(file2);
music.add(song1);

root.add(documents);
root.add(music);
root.add(new File("중요한_파일.txt", 50));

// 전체 파일 시스템 구조 출력
root.display();

출력 결과:

text
+ root
  + 문서
    - 이력서.docx (120KB)
    - 프로젝트_계획.pdf (340KB)
  + 음악
    - 아이유 - 밤편지.mp3 (4500KB)
  - 중요한_파일.txt (50KB)

클라이언트는 root 폴더 객체 하나만 가지고 display()를 호출했을 뿐인데, 전체 트리 구조가 재귀적으로 출력되는 것을 볼 수 있습니다. 클라이언트는 FileFolder의 내부 구조 차이를 신경 쓸 필요 없이 FileSystemComponent라는 단일 인터페이스를 통해 동일하게 상호작용할 수 있습니다.

컴포지트 패턴 중요 키워드

  • 트리 구조로 '부분-전체' 계층을 표현합니다.
  • 단일 객체(Leaf)와 복합 객체(Composite)를 동일하게 취급합니다.
  • 재귀적 구조를 통해 클라이언트 코드를 단순화합니다.
  • UI 툴킷, 파일 시스템 등 계층적 구조를 다룰 때 매우 유용합니다.
문제
객체들을 트리 구조로 구성하여 부분-전체 계층을 표현하는 패턴으로, 개별 객체(Leaf)와 복합 객체(Composite)를 동일한 방식으로 다룰 수 있게 하여 클라이언트가 단일 객체와 객체 집합을 구분 없이 사용할 수 있게 하는 디자인 패턴은?
보기
답변
정답정답 보기