공통으로 사용될 수 있는 특정한 기능들을 모듈화한 것
예시: 가위로 종이를 자를 때, 내가 직접 컨트롤하여 자르는 것처럼 개발자가 주도권을 가짐
공통으로 사용될 수 있는 특정한 기능들을 모듈화한 것으로, 라이브러리보다 엄격함
예시: 비행기를 타고 이동할 때, 비행기가 컨트롤하고 나는 가만히 앉아있는 것처럼 프레임워크가 주도권을 가짐
하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴
class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
Singleton.instance = this;
this.data = [];
}
}
const a = new Singleton();
const b = new Singleton();
console.log(a === b); // true
의존성 주입(DI, Dependency Injection)을 통해 모듈 간 결합을 느슨하게 만들 수 있음
💡 의존성(종속성): A가 B에 의존성이 있다 = B의 변경 시 A도 변경되어야 함
class UserFactory {
createUser(type) {
if (type === 'admin') {
return { role: 'admin', permissions: ['read', 'write', 'delete'] };
}
if (type === 'guest') {
return { role: 'guest', permissions: ['read'] };
}
return { role: 'user', permissions: ['read', 'write'] };
}
}
const factory = new UserFactory();
const admin = factory.createUser('admin');
const guest = factory.createUser('guest');
💡 핵심: 조건에 따라 다른 객체를 만들어주는 "공장"
정책 패턴(Policy Pattern)이라고도 하며, 객체의 행위를 직접 수정하지 않고 캡슐화된 알고리즘을 교체하여 동작을 변경하는 패턴
💡 컨텍스트(Context): 작업 완료에 필요한 모든 관련 정보 (상황, 맥락, 문맥)
class PaymentContext {
constructor(strategy) {
this.strategy = strategy;
}
pay(amount) {
return this.strategy.pay(amount);
}
}
const cardStrategy = {
pay: (amount) => `카드로 ${amount}원 결제`
};
const cashStrategy = {
pay: (amount) => `현금으로 ${amount}원 결제`
};
// 사용
const payment = new PaymentContext(cardStrategy);
console.log(payment.pay(10000)); // 카드로 10000원 결제
payment.strategy = cashStrategy; // 전략 변경
console.log(payment.pay(5000)); // 현금으로 5000원 결제
💡 핵심: 같은 목적이지만 다른 방법을 상황에 따라 교체 가능
Passport는 Node.js의 인증 미들웨어 라이브러리로, 여러 전략을 기반으로 인증 구현
class Passport {
constructor() {
this.strategies = {};
}
use(name, strategy) {
this.strategies[name] = strategy;
}
authenticate(name, userData) {
const strategy = this.strategies[name];
if (!strategy) {
throw new Error(`Strategy ${name} not found`);
}
return strategy.verify(userData);
}
}
// 전략 정의
const localStrategy = {
verify: (userData) => {
const { email, password } = userData;
if (email === 'user@example.com' && password === '1234') {
return { success: true, user: { id: 1, email } };
}
return { success: false, message: '로그인 실패' };
}
};
const googleStrategy = {
verify: (userData) => {
const { token } = userData;
if (token === 'valid-google-token') {
return { success: true, user: { id: 2, email: 'google@example.com' } };
}
return { success: false, message: 'Google 인증 실패' };
}
};
// 사용
const passport = new Passport();
passport.use('local', localStrategy);
passport.use('google', googleStrategy);
// 로컬 로그인
const result1 = passport.authenticate('local', {
email: 'user@example.com',
password: '1234'
});
console.log(result1); // { success: true, user: {...} }
// Google 로그인
const result2 = passport.authenticate('google', {
token: 'valid-google-token'
});
console.log(result2); // { success: true, user: {...} }
💡 핵심: 여러 인증 방식(local, google, kakao 등)을 전략으로 등록하고, 상황에 따라 선택하여 실행