CS 컴싸

디자인패턴: 4. 전략 패턴 (Strategy Pattern)

피곤한 Sue 2024. 3. 25. 18:49

다른 말로는 정책 패턴이라고도 하며 알고리즘 부분을 캡슐화하여 교체가 용이하게 만드는 패턴이다. 예를 들어 네이버페이, 카카오페이 등 다양한 방법으로 결제가 가능한 기능을 구현할 경우 결제 방식의 '전략'만 바꿔서 두 가지 방식으로 결제하도록 하는 패턴이다. 

 

먼저 이해를 돕기 위해 전략패턴을 사용하지 않는 결제 시스템을 만들어보자.

  function payment (type, amount) {

    let result = '';

    if (type === 'kakaopay') {
      result =  amount + '원을 카카오페이를 통해 결제 하였습니다';
    } else if (type === 'naverpay') {
      result =  amount + '원을 네이버페이를 통해 결제 하였습니다';
    } else if ( type === 'toss') {
      result =  amount + '원을 토스를 통해 결제 하였습니다';
    } else {
      result = 'Type을 제대로 지정해주세요';
    }
    return result;
  }
console.log(payment('naverpay', 10000)); //10000원을 네이버페이를 통해 결제 하였습니다

 

이런식의 코드를 짰다고 하면, 결제방식이 늘어날때마다 else if 를 추가 하는 방식으로 메서드 payment를 수정해야 할것이다. 그렇다면 이번엔 전략 패턴을 사용한 결제 코드를 만들어보자.

 

class Pay {
  constructor(type) {
    this.type = type;
  }
  payment (amount) {
    this.type.payment(amount);
  }
}

class KaKaoPay {
  constructor() {}  

  payment(amount) {
    const result = amount + '원을 카카오페이를 통해 결제 하였습니다';
    return result;
  }
}

class NaverPay {
  constructor() {}  

  payment(amount) {
    const result = amount + '원을 네이버페이를 통해 결제 하였습니다';
    return result;
  }
}

class Toss {
  constructor() {}  
  payment(amount) {
    const result = amount + '원을 토스를 통해 결제 하였습니다';
    return result;
  }
}

const pay = new Pay(new NaverPay());
console.log(pay.type.payment(10000)); //10000원을 네이버페이를 통해 결제 하였습니다

 

이렇게 전략패턴을 이용하면 다른 결제방식이 추가 되었다 하더라도 클래스 Pay를 수정하지 않고 새로운 클래스를 추가하는 것 만으로도 대응이 가능하다.  추가나 수정이 손 쉽게 가능하다는 것 말고도 재사용성이 높아지기 때문에 비용이 절감된다. 또한 각 결제 수단이 캡슐화 되어 있기 때문에 테스트도 용이하다. 하지만 클래스의 수가 늘어나기 때문에 코드가 복잡해질수 있는 단점이 있다. 

 

< passport의 전략 패턴 >

passport 는 전략패턴을 사용한 라이브러리이다.  

https://www.passportjs.org/

 

Passport.js

Simple, unobtrusive authentication for Node.js

www.passportjs.org

 

Node.js에서 인증 모듈을 구현할 때 쓰는 미들웨어 라이브러리로, 여러 가지 '전략'을 기반으로 인증할 수 있게 한다. 

더보기

미들웨어(Middleware) 란? 서로 다른 애플리케이션이 서로 통신하는 데 사용되는 소프트웨어이다. 미들웨어는 단일 시스템에 원활하게 통합할 수 있도록 다양한 기술, 도구, 데이터베이스 간에 다리 역할을  한다. 그런 다음 이 단일 시스템은 사용자에게 통합된 서비스를 제공한다. 예를 들어 Windows 프런트엔드 애플리케이션은 Linux 백엔드 서버에서 데이터를 송수신하지만, 애플리케이션 사용자는 그 차이를 인식하지 못한다.                                 - https://aws.amazon.com/ko/what-is/middleware/에서 발췌

  • LocalStrategy : ID와 비밀번호를 기반으로 인증
  • OAuth : 페이스북, 네이버 등 다른 서비스를 기반으로 인증
var passport = require('passport')
    , LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy( // '전략'을 use 메서드의 매개변수로 넣어서 로직을 수행한다
    function(username, password, done) {
        User.findOne({ username: username }, function (err, user) {
          if (err) { return done(err); }
            if (!user) {
                return done(null, false, { message: 'Incorrect username.' });
            }
            if (!user.validPassword(password)) {
                return done(null, false, { message: 'Incorrect password.' });
            }
            return done(null, user);
        });
    }
));

 

위의 코드에서는 LocalStrategy '전략'으로 인증을 진행하고 있다.