ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JavaScript 디자인 패턴: 실제 예시와 함께 배우기
    Javascript 2023. 11. 18. 21:07

    JavaScript 개발에 있어 디자인 패턴은 코드를 보다 효율적이고 유지보수하기 쉽게 만들어 줍니다. 일상적인 개발 과제에 적용할 수 있는 몇 가지 중요한 디자인 패턴과 그 예시를 살펴보겠습니다.

     

    1. 싱글톤 (Singleton) 패턴

    클래스의 인스턴스가 하나만 생성되도록 보장합니다.

    class Auth {
      constructor() {
        if (!Auth.instance) {
          Auth.instance = this;
        }
        return Auth.instance;
      }
    
      login(username, password) {
        // 로그인 로직
      }
    }
    
    const auth = new Auth();
    Object.freeze(auth);
    export default auth;

    로그인 시스템에서 하나의 인스턴스만 유지되어야 하는 사용자 인증 정보 관리.

     

    2. 팩토리 (Factory) 패턴

    객체 생성을 위한 인터페이스를 제공하고, 서브클래스가 생성할 객체의 클래스를 결정하게 합니다.

    class NotificationFactory {
      createNotification(type) {
        if (type === "email") return new EmailNotification();
        if (type === "sms") return new SMSNotification();
      }
    }
    
    class EmailNotification {
      send() {
        // 이메일 전송 로직
      }
    }
    
    class SMSNotification {
      send() {
        // SMS 전송 로직
      }
    }
    
    const factory = new NotificationFactory();
    const notification = factory.createNotification("email");
    notification.send();

    다양한 유형의 알림 메시지 생성.

     

    3. 옵저버 (Observer) 패턴

    객체의 상태 변화를 관찰하고, 상태 변화 시 자동으로 다른 객체들에게 알림을 줍니다.

    class User {
      constructor() {
        this.observers = [];
      }
    
      subscribe(observer) {
        this.observers.push(observer);
      }
    
      notify() {
        this.observers.forEach(observer => {
          observer.update(this);
        });
      }
    
      updateStatus(status) {
        this.status = status;
        this.notify();
      }
    }
    
    class Logger {
      update(user) {
        console.log(`사용자 상태 변경: ${user.status}`);
      }
    }
    
    const user = new User();
    const logger = new Logger();
    
    user.subscribe(logger);
    user.updateStatus('온라인');

    사용자의 상태 변화를 추적하여 관련 업데이트를 처리하는 시스템.

     

    4. 데코레이터 (Decorator) 패턴

    객체에 동적으로 새로운 책임을 추가합니다. 상속을 사용하지 않고 객체의 기능을 확장할 수 있습니다.

    class DataSource {
      writeData(data) {
        // 데이터 쓰기 로직
      }
    }
    
    class DataSourceDecorator extends DataSource {
      constructor(dataSource) {
        super();
        this.wrappee = dataSource;
      }
    
      writeData(data) {
        // 추가 기능 또는 로직
        this.wrappee.writeData(data);
      }
    }
    
    class EncryptionDecorator extends DataSourceDecorator {
      writeData(data) {
        // 데이터 암호화
        super.writeData(data);
      }
    }
    
    const source = new DataSource();
    const encryptedSource = new EncryptionDecorator(source);
    encryptedSource.writeData("secret data");

    로깅, 유효성 검사, 상태 관리 등의 추가 기능을 동적으로 객체에 부여.

     

    5. 컴포지트 (Composite) 패턴

    객체들의 그룹을 트리 구조로 구성하여 개별 객체와 복합 객체를 클라이언트가 동일하게 다룰 수 있도록 합니다.

    class Component {
      constructor(name) {
        this.name = name;
      }
    
      add(component) {}
      remove(component) {}
      display(depth) {}
    }
    
    class Leaf extends Component {
      display(depth) {
        console.log('-'.repeat(depth) + this.name);
      }
    }
    
    class Composite extends Component {
      constructor(name) {
        super(name);
        this.children = [];
      }
    
      add(component) {
        this.children.push(component);
      }
    
      remove(component) {
        this.children = this.children.filter(child => child !== component);
      }
    
      display(depth) {
        console.log('-'.repeat(depth) + this.name);
        this.children.forEach(child => child.display(depth + 2));
      }
    }
    
    const root = new Composite('root');
    const leaf1 = new Leaf('Leaf 1');
    const leaf2 = new Leaf('Leaf 2');
    const comp = new Composite('Composite');
    
    comp.add(leaf1);
    comp.add(leaf2);
    root.add(comp);
    root.display(1);

    파일 시스템의 디렉토리와 파일을 표현하는 경우.

     

    6. 전략 (Strategy) 패턴

    알고리즘을 클래스의 행동으로 정의하고 이를 동적으로 바꿔 사용할 수 있게 합니다.

    class SortStrategy {
      sort(dataset) {
        // 정렬 로직
      }
    }
    
    class BubbleSortStrategy extends SortStrategy {
      sort(dataset) {
        console.log('Bubble sort');
        // 버블 정렬 알고리즘
      }
    }
    
    class QuickSortStrategy extends SortStrategy {
      sort(dataset) {
        console.log('Quick sort');
        // 퀵 정렬 알고리즘
      }
    }
    
    class Sorter {
      constructor(strategy) {
        this.strategy = strategy;
      }
    
      sort(dataset) {
        return this.strategy.sort(dataset);
      }
    }
    
    const dataset = [1, 5, 4, 3, 2, 8];
    const sorter = new Sorter(new BubbleSortStrategy());
    sorter.sort(dataset);

    다양한 정렬 또는 검색 알고리즘 중 하나를 선택하여 사용.

     

    디자인 패턴은 복잡한 소프트웨어 설계 문제를 해결하는 데 도움을 줍니다. 위에서 살펴본 패턴 외에도 많은 디자인 패턴들이 있으며, 각각의 패턴은 특정 상황에 최적화된 솔루션을 제공합니다. 코드의 재사용성, 유지보수성 및 확장성을 높이려면 이러한 패턴들을 적절히 활용하는 것이 중요합니다.

    JavaScript 개발의 심화 단계로 나아가려면 이러한 패턴들을 이해하고 실제 프로젝트에 적용하는 능력을 기르는 것이 필수적입니다. 따라서 이 글에서 제시된 패턴들을 참고하여 자신만의 프로젝트에 적용해 보시기 바랍니다.

Designed by Tistory.