Composite 실전 가이드

Composite의 핵심 개념과 실무 활용

TypeScript중급
6시간
3개 항목
학습 진행률0 / 3 (0%)

학습 항목

1. TypeScript
초급
Composite|Pattern|디자인패턴|완벽|가이드
퀴즈튜토리얼
2. TypeScript
중급
Composite|Pattern|실무|활용|가이드
퀴즈튜토리얼
3. TypeScript
고급
Composite|Pattern|핵심|개념|완벽|정리
퀴즈튜토리얼
1 / 3

이미지 로딩 중...

Composite Pattern 디자인패턴 완벽 가이드 - 슬라이드 1/13

Composite Pattern 디자인패턴 완벽 가이드

Composite Pattern은 객체들을 트리 구조로 구성하여 개별 객체와 복합 객체를 동일하게 다루는 구조적 디자인 패턴입니다. 파일 시스템, UI 컴포넌트 등에서 널리 사용됩니다.


카테고리:TypeScript
언어:TypeScript
난이도:beginner
메인 태그:#TypeScript
서브 태그:
#CompositePattern#DesignPattern#OOP#TreeStructure

들어가며

이 글에서는 Composite Pattern 디자인패턴 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. Component_인터페이스_정의
  2. Leaf_클래스_구현
  3. Composite_클래스_구현
  4. 기본_사용_예제
  5. 중첩된_구조_만들기
  6. Remove_기능_추가
  7. Iterator_패턴과_결합
  8. 검색_기능_구현
  9. UI_컴포넌트_예제
  10. 타입_안전성_강화
  11. 성능_최적화_캐싱
  12. 실전_예제_메뉴_시스템

1. Component_인터페이스_정의

개요

Composite Pattern의 기본이 되는 Component 인터페이스를 정의합니다. 개별 객체와 복합 객체가 공통으로 사용할 메서드를 선언합니다.

코드 예제

interface Component {
  getName(): string;
  getSize(): number;
  print(indent: string): void;
}

설명

모든 파일과 폴더가 구현할 공통 인터페이스입니다. getName, getSize, print 메서드를 통해 일관된 방식으로 객체를 다룰 수 있습니다.


2. Leaf_클래스_구현

개요

Composite Pattern에서 Leaf는 자식을 가질 수 없는 단말 객체입니다. 파일 시스템에서 파일에 해당합니다.

코드 예제

class File implements Component {
  constructor(private name: string, private size: number) {}

  getName(): string { return this.name; }
  getSize(): number { return this.size; }
  print(indent: string): void {
    console.log(`${indent}📄 ${this.name} (${this.size}KB)`);
  }
}

설명

File 클래스는 더 이상 하위 요소를 가지지 않는 Leaf 노드입니다. 자신의 이름과 크기 정보만 관리합니다.


3. Composite_클래스_구현

개요

Composite는 자식 요소들을 포함할 수 있는 복합 객체입니다. 파일 시스템의 폴더에 해당하며 여러 파일과 폴더를 담을 수 있습니다.

코드 예제

class Folder implements Component {
  private children: Component[] = [];

  constructor(private name: string) {}

  add(component: Component): void {
    this.children.push(component);
  }

  getName(): string { return this.name; }
  getSize(): number {
    return this.children.reduce((sum, child) => sum + child.getSize(), 0);
  }
  print(indent: string): void {
    console.log(`${indent}📁 ${this.name}`);
    this.children.forEach(child => child.print(indent + "  "));
  }
}

설명

Folder는 자식 요소들을 배열로 관리하고, getSize는 모든 자식의 크기를 합산합니다. add 메서드로 자식을 추가할 수 있습니다.


4. 기본_사용_예제

개요

File과 Folder를 생성하고 트리 구조를 만드는 기본 사용 예제입니다. 개별 객체와 복합 객체를 동일하게 다룰 수 있습니다.

코드 예제

const root = new Folder("root");
const file1 = new File("readme.txt", 10);
const file2 = new File("app.ts", 25);

root.add(file1);
root.add(file2);

console.log(`Total size: ${root.getSize()}KB`);
root.print("");

설명

Folder와 File을 Component 타입으로 동일하게 다룰 수 있습니다. root의 getSize()는 모든 하위 파일의 크기를 자동으로 계산합니다.


5. 중첩된_구조_만들기

개요

Folder 안에 다시 Folder를 넣어 깊은 트리 구조를 만들 수 있습니다. 실제 파일 시스템처럼 복잡한 계층 구조를 표현합니다.

코드 예제

const root = new Folder("root");
const src = new Folder("src");
const docs = new Folder("docs");

src.add(new File("index.ts", 30));
src.add(new File("utils.ts", 15));
docs.add(new File("guide.md", 20));

root.add(src);
root.add(docs);
root.print("");

설명

Folder 안에 Folder를 추가하여 계층 구조를 만듭니다. print 메서드가 재귀적으로 호출되어 전체 트리를 출력합니다.


6. Remove_기능_추가

개요

Composite 객체에서 자식 요소를 제거하는 기능을 추가합니다. 실제 애플리케이션에서 필요한 필수 기능입니다.

코드 예제

class Folder implements Component {
  private children: Component[] = [];

  add(component: Component): void {
    this.children.push(component);
  }

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

설명

remove 메서드로 특정 자식 요소를 제거할 수 있습니다. indexOf로 위치를 찾고 splice로 배열에서 제거합니다.


7. Iterator_패턴과_결합

개요

Composite Pattern과 Iterator 패턴을 결합하여 모든 자식 요소를 순회하는 기능을 추가합니다.

코드 예제

class Folder implements Component {
  private children: Component[] = [];

  *getChildren(): Generator<Component> {
    for (const child of this.children) {
      yield child;
    }
  }
}

// 사용 예
for (const child of folder.getChildren()) {
  console.log(child.getName());
}

설명

Generator 함수를 사용해 자식 요소를 순회할 수 있게 합니다. for...of 루프로 간편하게 모든 자식에 접근할 수 있습니다.


8. 검색_기능_구현

개요

트리 구조에서 특정 이름의 요소를 찾는 검색 기능을 구현합니다. 재귀적으로 모든 자식을 탐색합니다.

코드 예제

class Folder implements Component {
  find(name: string): Component | null {
    if (this.name === name) return this;

    for (const child of this.children) {
      if (child.getName() === name) return child;
      if (child instanceof Folder) {
        const found = child.find(name);
        if (found) return found;
      }
    }
    return null;
  }
}

설명

find 메서드는 자신의 이름을 먼저 확인하고, 자식들을 순회하며 재귀적으로 검색합니다. Folder인 경우 하위 트리도 탐색합니다.


9. UI_컴포넌트_예제

개요

Composite Pattern을 UI 컴포넌트에 적용한 예제입니다. 버튼, 패널 등을 동일한 인터페이스로 다룰 수 있습니다.

코드 예제

class Button implements Component {
  constructor(private label: string) {}
  getName() { return this.label; }
  render() { console.log(`<button>${this.label}</button>`); }
}

class Panel implements Component {
  private children: Component[] = [];
  add(c: Component) { this.children.push(c); }
  render() { this.children.forEach(c => c.render()); }
}

설명

Button은 Leaf, Panel은 Composite 역할을 합니다. Panel 안에 여러 Button이나 다른 Panel을 넣어 복잡한 UI를 구성할 수 있습니다.


10. 타입_안전성_강화

개요

TypeScript의 타입 시스템을 활용하여 Composite Pattern의 타입 안전성을 강화합니다.

코드 예제

abstract class Component {
  abstract getName(): string;
  abstract getSize(): number;

  isComposite(): this is Folder {
    return this instanceof Folder;
  }
}

// 사용
if (component.isComposite()) {
  component.add(newFile); // 타입 안전
}

설명

추상 클래스와 타입 가드를 사용하여 컴파일 타임에 타입 오류를 방지합니다. isComposite로 안전하게 타입을 좁힐 수 있습니다.


11. 성능_최적화_캐싱

개요

getSize 같은 연산 비용이 큰 메서드의 결과를 캐싱하여 성능을 최적화합니다.

코드 예제

class Folder implements Component {
  private children: Component[] = [];
  private cachedSize: number | null = null;

  add(component: Component): void {
    this.children.push(component);
    this.cachedSize = null; // 캐시 무효화
  }

  getSize(): number {
    if (this.cachedSize === null) {
      this.cachedSize = this.children.reduce((sum, c) => sum + c.getSize(), 0);
    }
    return this.cachedSize;
  }
}

설명

자식이 변경될 때만 캐시를 무효화하고, 그 외에는 저장된 값을 반환합니다. 대규모 트리 구조에서 성능이 크게 향상됩니다.


12. 실전_예제_메뉴_시스템

개요

레스토랑 메뉴 시스템을 Composite Pattern으로 구현한 실전 예제입니다. 메뉴와 서브메뉴를 계층적으로 관리합니다.

코드 예제

class MenuItem implements Component {
  constructor(private name: string, private price: number) {}
  getName() { return this.name; }
  getPrice() { return this.price; }
}

class Menu implements Component {
  private items: Component[] = [];
  constructor(private name: string) {}
  add(item: Component) { this.items.push(item); }
  getPrice() { return this.items.reduce((sum, i) => sum + i.getPrice(), 0); }
}

설명

MenuItem은 개별 메뉴, Menu는 메뉴 카테고리입니다. 전체 메뉴의 가격을 자동으로 계산할 수 있고, 세트 메뉴도 쉽게 구성할 수 있습니다.


마치며

이번 글에서는 Composite Pattern 디자인패턴 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#TypeScript #CompositePattern #DesignPattern #OOP #TreeStructure

#TypeScript#CompositePattern#DesignPattern#OOP#TreeStructure