[CS 스터디] 디자인 패턴 기초 - 싱글톤, 팩토리, 전략

⭐ 아엔 Aen·2026년 1월 5일

데브코스

목록 보기
116/131

CS 공부 - 디자인 패턴

라이브러리 vs 프레임워크

라이브러리

공통으로 사용될 수 있는 특정한 기능들을 모듈화한 것

예시: 가위로 종이를 자를 때, 내가 직접 컨트롤하여 자르는 것처럼 개발자가 주도권을 가짐

프레임워크

공통으로 사용될 수 있는 특정한 기능들을 모듈화한 것으로, 라이브러리보다 엄격함

  • 폴더명, 파일명 등에 대한 규칙 존재

예시: 비행기를 타고 이동할 때, 비행기가 컨트롤하고 나는 가만히 앉아있는 것처럼 프레임워크가 주도권을 가짐


1. 싱글톤 패턴 (Singleton Pattern)

개념

하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴

장점

  • 인스턴스를 공유하여 사용하므로 생성 비용 절약

단점

  • 의존성이 높아짐
  • TDD 시 문제 발생: 단위 테스트는 독립적이어야 하는데, 싱글톤은 하나의 인스턴스를 공유하므로 독립적인 테스트가 어려움

예시 코드

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도 변경되어야 함


2. 팩토리 패턴 (Factory Pattern)

개념

  • 객체 생성 부분을 추상화한 패턴
  • 상위 클래스가 뼈대를 결정하고, 하위 클래스가 구체적인 내용을 결정

장점

  • 느슨한 결합: 상위 클래스는 인스턴스 생성 방식을 알 필요 없음
  • 유지보수성 향상: 객체 생성 로직이 분리되어 한 곳만 수정하면 됨

예시 코드

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');

💡 핵심: 조건에 따라 다른 객체를 만들어주는 "공장"


3. 전략 패턴 (Strategy Pattern)

개념

정책 패턴(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원 결제

💡 핵심: 같은 목적이지만 다른 방법을 상황에 따라 교체 가능


3-1. Passport의 전략 패턴

개념

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 등)을 전략으로 등록하고, 상황에 따라 선택하여 실행

profile
Dive Head First | Work Super Hard | Attract Great People

0개의 댓글