Singleton 완벽 마스터
Singleton의 핵심 개념과 실전 활용법
학습 항목
이미지 로딩 중...
JavaScript 디자인 패턴 완벽 가이드
실무에서 자주 사용되는 JavaScript 디자인 패턴들을 배워봅니다. 코드의 재사용성과 유지보수성을 높이는 검증된 해결책들을 실제 예제와 함께 학습합니다.
들어가며
이 글에서는 JavaScript 디자인 패턴 완벽 가이드에 대해 상세히 알아보겠습니다. 총 10가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- Singleton_패턴
- Factory_패턴
- Observer_패턴
- Module_패턴
- Strategy_패턴
- Decorator_패턴
- Proxy_패턴
- Command_패턴
- Chain_of_Responsibility_패턴
- Builder_패턴
1. Singleton_패턴
개요
클래스의 인스턴스가 오직 하나만 존재하도록 보장하는 패턴입니다. 전역 상태 관리나 설정 객체에 주로 사용됩니다.
코드 예제
class Database {
static instance = null;
static getInstance() {
if (!Database.instance) {
Database.instance = new Database();
}
return Database.instance;
}
}
const db1 = Database.getInstance();
const db2 = Database.getInstance();
console.log(db1 === db2); // true
설명
getInstance 메서드를 통해 항상 동일한 인스턴스를 반환하여, 애플리케이션 전체에서 하나의 데이터베이스 연결만 유지합니다.
2. Factory_패턴
개요
객체 생성 로직을 별도의 팩토리 함수로 분리하여 유연성을 높이는 패턴입니다. 조건에 따라 다른 타입의 객체를 생성할 수 있습니다.
코드 예제
class Car { drive() { return "자동차 운전"; } }
class Bike { drive() { return "자전거 타기"; } }
function VehicleFactory(type) {
if (type === 'car') return new Car();
if (type === 'bike') return new Bike();
}
const vehicle = VehicleFactory('car');
console.log(vehicle.drive()); // "자동차 운전"
설명
팩토리 함수가 타입에 따라 적절한 객체를 생성하므로, 사용자는 생성 로직을 알 필요 없이 간단하게 객체를 얻을 수 있습니다.
3. Observer_패턴
개요
객체의 상태 변화를 관찰하는 옵저버들에게 자동으로 알림을 보내는 패턴입니다. 이벤트 처리나 상태 관리에 유용합니다.
코드 예제
class Subject {
constructor() { this.observers = []; }
subscribe(fn) { this.observers.push(fn); }
notify(data) { this.observers.forEach(fn => fn(data)); }
}
const subject = new Subject();
subject.subscribe(data => console.log(`받음: ${data}`));
subject.notify("새 메시지"); // "받음: 새 메시지"
설명
옵저버들을 배열로 관리하고 상태 변경 시 notify로 모든 옵저버에게 알림을 전달하여, 느슨한 결합을 유지합니다.
4. Module_패턴
개요
클로저를 활용해 private과 public 멤버를 구분하는 패턴입니다. 캡슐화를 통해 내부 구현을 숨기고 필요한 인터페이스만 노출합니다.
코드 예제
const Counter = (function() {
let count = 0; // private
return {
increment() { return ++count; },
decrement() { return --count; },
getCount() { return count; }
};
})();
console.log(Counter.increment()); // 1
console.log(Counter.getCount()); // 1
설명
즉시 실행 함수로 클로저를 생성하여 count 변수를 외부에서 직접 접근할 수 없게 하고, 공개 메서드로만 조작 가능하게 합니다.
5. Strategy_패턴
개요
알고리즘을 객체로 캡슐화하여 런타임에 동적으로 교체할 수 있는 패턴입니다. 조건문 대신 전략 객체를 사용합니다.
코드 예제
const strategies = {
add: (a, b) => a + b,
multiply: (a, b) => a * b,
divide: (a, b) => a / b
};
function calculate(strategy, a, b) {
return strategies[strategy](a, b);
}
console.log(calculate('add', 5, 3)); // 8
console.log(calculate('multiply', 5, 3)); // 15
설명
전략 객체에 다양한 알고리즘을 정의하고, 함수가 전략 이름을 받아 해당 알고리즘을 실행하여 유연한 동작 변경이 가능합니다.
6. Decorator_패턴
개요
기존 객체에 새로운 기능을 동적으로 추가하는 패턴입니다. 상속 없이 객체의 기능을 확장할 수 있습니다.
코드 예제
function coffee() {
return { cost: 5, description: '커피' };
}
function withMilk(beverage) {
beverage.cost += 2;
beverage.description += ' + 우유';
return beverage;
}
const myCoffee = withMilk(coffee());
console.log(myCoffee); // { cost: 7, description: '커피 + 우유' }
설명
데코레이터 함수가 원본 객체를 받아 속성을 수정하고 반환함으로써, 기존 코드를 변경하지 않고 기능을 확장합니다.
7. Proxy_패턴
개요
객체에 대한 접근을 제어하는 대리자 역할을 하는 패턴입니다. 접근 제어, 캐싱, 로깅 등에 활용됩니다.
코드 예제
const target = { name: '원본', data: '중요 정보' };
const proxy = new Proxy(target, {
get(obj, prop) {
console.log(`${prop} 접근됨`);
return obj[prop];
}
});
console.log(proxy.name); // "name 접근됨" 후 "원본"
설명
Proxy 객체가 원본 객체에 대한 접근을 가로채서, 속성 접근 시 로깅과 같은 부가 작업을 수행할 수 있습니다.
8. Command_패턴
개요
요청을 객체로 캡슐화하여 실행 취소, 재실행 등의 기능을 구현할 수 있는 패턴입니다. 명령어 기록과 관리에 유용합니다.
코드 예제
class Command {
constructor(execute, undo) {
this.execute = execute;
this.undo = undo;
}
}
const addCmd = new Command(
() => console.log('추가'),
() => console.log('추가 취소')
);
addCmd.execute(); // "추가"
addCmd.undo(); // "추가 취소"
설명
명령을 객체로 만들어 execute와 undo 메서드를 정의함으로써, 작업을 실행하고 되돌리는 기능을 쉽게 구현할 수 있습니다.
9. Chain_of_Responsibility_패턴
개요
요청을 처리할 수 있는 객체들을 체인으로 연결하여 순차적으로 처리하는 패턴입니다. 미들웨어 구현에 자주 사용됩니다.
코드 예제
class Handler {
setNext(handler) {
this.next = handler;
return handler;
}
handle(request) {
if (this.next) return this.next.handle(request);
}
}
const h1 = new Handler();
const h2 = new Handler();
h1.setNext(h2);
설명
핸들러들을 체인으로 연결하고, 각 핸들러가 요청을 처리하거나 다음 핸들러로 전달하여 유연한 요청 처리 파이프라인을 구성합니다.
10. Builder_패턴
개요
복잡한 객체를 단계별로 구성하는 패턴입니다. 생성자 매개변수가 많을 때 가독성을 높이고 선택적 설정을 쉽게 합니다.
코드 예제
class UserBuilder {
setName(name) { this.name = name; return this; }
setAge(age) { this.age = age; return this; }
build() { return { name: this.name, age: this.age }; }
}
const user = new UserBuilder()
.setName('김철수')
.setAge(30)
.build();
console.log(user); // { name: '김철수', age: 30 }
설명
메서드 체이닝을 통해 객체의 속성을 단계적으로 설정하고, build 메서드로 최종 객체를 생성하여 직관적인 객체 생성이 가능합니다.
마치며
이번 글에서는 JavaScript 디자인 패턴 완벽 가이드에 대해 알아보았습니다. 총 10가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#JavaScript #DesignPatterns #Singleton #Factory #Observer