본문 바로가기
Design Pattern/생성 패턴(Creational Patterns)

프로토타입(Prototype) - 생성 패턴(Creational Patterns)

by 김 민 준 2024. 5. 15.

프로토타입 패턴은 개체를 생성하는 디자인 패턴이다. 새로운 개체를 만들기 위해 기존의 개체를 복제하는 방법을 사용하는데 특히 개체 생성 과정이 복잡하거나 자원을 많이 소모할 때 유용하게 사용할 수 있다.

기존에 만들어진 개체를 사용하여 새로운 개체를 생성하는 게 핵심인데 복제한 개체의 프로토타입(원본)을 가지고 있고, 이 원본 개체를 복제함으로써 새로운 개체를 빠르고 효율적으로 생성할 수 있다. 

 

프로토타입 개체 정의 : 복제될 개체의 원분이 되는 프로토타입 개체를 정의한다. 이 개체는 모든 상태와 데이터를 가지고 있어야 하며, 자신을 복제할 수 있는 메커니즘을 제공해야 한다. 

 

복제(클로닝) 메서드 : 프로토타입 개체는 자신의 복사본을 만들어 반환할 수 있는 clone() 메서드 같은 복제 메커니즘을 제공한다. 이 메서드는 자신의 정확한 복사본을 생성하여 반환한다.

 

새 개체 생성 : 필요할 때마다 이 clone() 메서드를 호출하여 새로운 개체를 생성한다. 특히 개체 생성 과정이 복잡하거나 시간이 많이 소요될 때 원본 개체를 다시 사용하기에 효율적이다.

 

프로토타입 패턴의 장점으로는 복잡한 개체 생성 절차를 간소화한다. 이미 초기화된 개체의 상태를 복제하기 때문에 복잡하지 않다. 그리고 성능이 향상하는데 개체를 처음부터 만들어서 사용하는 게 아니기 때문에 복제가 빠르고 비용이 적게 든다. 또한 동적으로 시스템 확장이 가능하기에 새로운 개체 타입을 손쉽게 추가하고 복제할 수 있다. 

 

프로토타입 패턴의 단점으로는 단순히 모든 필드를 복사하는 것만으로 충분하지 않은 상황에서 발생할 수 있다. 또한 복제된 개체가 시스템 내 다른 컴포넌트와의 어떤 영향이 있을지 모르는 상황일 수 있기에 초기화 문제등이 발생할 수 있다.

 

이해하는데 도움 되는 간단한 예시를 생각해 보자 

 

카페의 나라 대한민국에 살고 있기에 카페에서 커피를 주문하는 상황으로 이해해 보자.

카페에서 커피를 주문하려고 한다. 많은 종류의 커피가 있고 각 커피는 준비하는 방식이나 재료가 조금씩 다를 수 있다. 

이때 커피 메뉴의 각 항목을 개체로 생각할 수 있으며, 각 개체는 커피를 만드는데 필요한 정보를 포함하고 있다.

 

카페에서 프로토타입 패턴을 도입하면, 메뉴의 각 커피 종류에 대한 프로토타입 개체를 만들어두고, 실제 주문이 들어올 때 이 프로토타입을 복제하여 사용자 요청에 맞는 커피를 빠르고 일관되게 제공할 수 있을 것이다. 

 

소스코도로 살펴보자

 

class Coffee {
    constructor(type, ingredients) {
        this.type = type;
        this.ingredients = ingredients;
    }

    clone() {
        // 새 개체를 반환하고, 원본 객체의 필드를 복사
        return new Coffee(this.type, [...this.ingredients]);
    }

    serve(customer) {
        console.log(`Serving ${this.type} to ${customer} with ${this.ingredients.join(", ")}`);
    }
}

// 프로토타입 객체 생성
const espressoPrototype = new Coffee("Espresso", ["Espresso"]);
const lattePrototype = new Coffee("Latte", ["Espresso", "Milk"]);

// 주문 처리
function takeOrder(type, customer) {
    let coffee;
    if (type === "Espresso") {
        coffee = espressoPrototype.clone();  // 에스프레소 프로토타입 복제
    } else if (type === "Latte") {
        coffee = lattePrototype.clone();  // 라떼 프로토타입 복제
    }
    coffee.serve(customer);
}

// 주문 예시
takeOrder("Espresso", "Alice");
takeOrder("Latte", "Bob");

 

소스코드에서의 Coffee 클래스는 커피를 나타내는데 커피 종류 Type와 재료 ingredients를 속성으로 가진다 

이를 clone 메서드를 활용하여 현재 개체를 복제하여 새로운 개체를 생성한다. 

에스프로세와 라테에 대해 프로토타입 개체를 생성하고 이를 주문 시 복제하여 사용한다.