본문 바로가기

모던 자바스크립트 디자인 패턴: 생성, 구조, 행동 패턴 소개

에온르 2024. 6. 25.
반응형

이 강의에서는 자바스크립트를 사용하여 소프트웨어 설계에서 자주 사용되는 디자인 패턴을 탐구해볼 것입니다. 생성, 구조, 그리고 행동 패턴을 중심으로 학습하면서, 각 패턴의 개념을 이해하고 자바스크립트 코드로 어떻게 구현할 수 있는지 배워보겠습니다!

source : calibraint.com

디자인 패턴의 중요성

디자인 패턴은 검증된 솔루션을 통해 일반적인 문제를 해결합니다. 이는 코드의 재사용성을 높이고, 유지 관리를 용이하게 하며, 프로젝트의 구조를 향상시키는 데 도움을 줍니다.


생성 패턴

생성 패턴은 객체 생성 메커니즘을 캡슐화하는 패턴으로, 객체를 생성하는 방식과 객체의 표현 방식을 독립적으로 만드는 데 중점을 둡니다.

싱글톤 패턴

싱글톤 패턴은 클래스에 대한 단일 인스턴스만을 생성하고, 이에 대한 전역 접근점을 제공합니다.

let instance;

class Singleton {
    constructor() {
        if (!instance) {
            instance = this;
        }
        return instance;
    }
}

const obj1 = new Singleton();
const obj2 = new Singleton();

console.log(obj1 === obj2);  // true

구조 패턴

구조 패턴은 객체와 클래스를 조합하여 더 큰 구조를 만듭니다. 이는 인터페이스의 복잡성을 줄이고, 서로 다른 인터페이스를 함께 사용할 수 있도록 합니다.

어댑터 패턴

어댑터 패턴은 호환되지 않는 인터페이스 때문에 함께 사용할 수 없는 클래스들을 연결하는 데 사용됩니다.

class OldCalculator {
    constructor() {
        this.operations = function(value1, value2, operation) {
            switch (operation) {
                case 'add': return value1 + value2;
                case 'sub': return value1 - value2;
                default: return NaN;
            }
        };
    }
}

class NewCalculator {
    constructor() {
        this.add = function(value1, value2) {
            return value1 + value2;
        };
        this.sub = function(value1, value2) {
            return value1 - value2;
        };
    }
}

class CalcAdapter {
    constructor() {
        const newCalc = new NewCalculator();

        this.operations = function(value1, value2, operation) {
            switch (operation) {
                case 'add': return newCalc.add(value1, value2);
                case 'sub': return newCalc.sub(value1, value2);
                default: return NaN;
            }
        };
    }
}

행동 패턴

행동 패턴은 객체 간의 통신을 쉽고 유연하게 설계하는 데 중점을 둡니다.

옵서버 패턴

옵서버 패턴은 객체의 상태 변화를 관찰하고, 상태 변화에 따라 하나 이상의 객체에게 자동으로 알림을 보냅니다.

class Subject {
    constructor() {
        this.observers = [];
    }

    subscribe(observer) {
        this.observers.push(observer);
    }

    unsubscribe(observer) {
        this.observers = this.observers.filter(obs => obs !== observer);
    }

    notify(data) {
        this.observers.forEach(observer => observer.update(data));
    }
}

class Observer {
    update(data) {
        console.log(`Received data: ${data}`);
    }
}

실습으로는 자바스크립트에서 자주 사용되는 "팩토리 패턴"을 예로 들어 설명하겠습니다. 이 패턴은 객체 생성을 위한 인터페이스를 제공하며, 호출 코드에서는 새로 생성되는 객체의 정확한 클래스나 생성자 함수를 몰라도 객체를 생성할 수 있게 해줍니다.

팩토리 패턴 예제

팩토리 패턴은 특히 객체 생성 과정이 복잡하거나, 객체 생성을 여러 곳에서 처리해야 할 때 유용합니다. 이 패턴을 사용하면 객체 생성을 한 곳에서 관리할 수 있으므로 코드 유지 관리가 쉬워집니다.

개념 설명

팩토리 패턴은 생성할 객체의 타입을 기반으로 인터페이스를 제공하며, 이를 통해 객체의 인스턴스를 반환합니다. 사용자는 이 인터페이스를 통해 객체를 요청하고, 팩토리는 요청에 맞는 객체를 생성하여 반환합니다.

코드 예제

다음은 간단한 차량 객체를 생성하는 팩토리 예제입니다. 클라이언트는 차량 타입을 지정하고, 팩토리는 해당 타입의 차량 객체를 생성하여 반환합니다.

// Constructor functions for different types of vehicles
function Car(options) {
    this.doors = options.doors || 4;
    this.state = options.state || 'brand new';
    this.color = options.color || 'silver';
}

function Truck(options) {
    this.wheelSize = options.wheelSize || 'large';
    this.state = options.state || 'used';
    this.color = options.color || 'blue';
}

// Define a skeleton vehicle factory
function VehicleFactory() {}

// Define the prototypes and utilities for this factory
VehicleFactory.prototype.vehicleClass = Car; // Default VehicleClass is Car

VehicleFactory.prototype.createVehicle = function (options) {
    switch(options.vehicleType) {
        case 'car':
            this.vehicleClass = Car;
            break;
        case 'truck':
            this.vehicleClass = Truck;
            break;
    }
    return new this.vehicleClass(options);
};

// Create an instance of our factory that makes cars
const carFactory = new VehicleFactory();
const car = carFactory.createVehicle({
    vehicleType: 'car',
    color: 'yellow',
    doors: 6
});

console.log(car instanceof Car);  // true
console.log(car);  // Car { doors: 6, state: 'brand new', color: 'yellow' }

// Use to create a truck
const truck = carFactory.createVehicle({
    vehicleType: 'truck',
    wheelSize: 'medium',
    color: 'red'
});

console.log(truck instanceof Truck);  // true
console.log(truck);  // Truck { wheelSize: 'medium', state: 'used', color: 'red' }

이 예제에서 VehicleFactory는 차량 객체의 생성을 처리합니다. Car와 Truck 생성자 함수를 사용하여, 요구 사항에 맞는 객체 인스턴스를 생성하고 반환합니다. 이러한 패턴을 사용하면 다양한 객체 타입을 유연하게 생성할 수 있으며, 객체 생성 로직을 한 곳에서 관리할 수 있어 코드의 일관성과 재사용성을 높일 수 있습니다.


결론

자바스크립트에서 디자인 패턴을 이해하고 사용하는 것은 효과적인 소프트웨어 설계를 위한 핵심적인 요소입니다. 이 강의를 통해 주요 디자인 패턴을 학습하고, 실제 프로젝트에 어떻게 적용할 수 있는지 이해할 수 있게 될 것입니다. 각 패턴은 특정 문제를 해결하는 데 최적화되어 있으며, 이를 적절히 활용하면 보다 견고하고 유지보수가 용이한 애플리케이션을 개발할 수 있습니다.

반응형

댓글