CS

전략 패턴 ( Strategy pattern )

Evan Lee ㅣ 2023. 6. 24. 04:34

전략 패턴이란? 

Strategy 패턴을 사용하면 서로 다른 알고리즘이나 동작을 상호 교환 가능한 객체로 캡슐화하여 런타임에 동적으로 전략을 선택할 수 있습니다. 전략 패턴은 상속보다 컴포지션 사용을 장려하는 동작 디자인 패턴입니다. 이를 통해 전략이라고 하는 별도의 클래스 내에 캡슐화된 상호 교환 가능한 알고리즘 구성을 정의할 수 있습니다. 이렇게 하면 전략을 사용하는 클라이언트 코드에 영향을 주지 않고 서로 다른 전략 간에 쉽게 전환할 수 있습니다.

 

전략패턴의 장점 ? 

  • 알고리즘의 캡슐화: 다양한 알고리즘이나 동작을 자체 클래스 내에 캡슐화하여 이해, 수정 및 테스트하기 쉽게 만듭니다.
  • 코드 유지 관리 간소화: 클라이언트 코드와 분리되어 있으므로 전략을 변경해도 다른 전략이나 클라이언트 코드 자체에 영향을 미치지 않습니다.
  • 코드 재사용성 촉진: 여러 프로젝트 또는 시나리오에서 전략을 사용할 수 있으므로 코드 재사용을 촉진하고 중복을 줄일 수 있습니다.
  • 런타임 유연성 향상: 런타임에 동적으로 전략을 선택하고 전환할 수 있으므로 변화하는 요구 사항에 유연하게 적응할 수 있습니다.

 

전략 패턴을 시연하기 위해 자바스크립트 정렬 알고리즘의 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Strategy: BubbleSort
class BubbleSortStrategy {
  sort(data) {
    // Sorting logic using bubble sort
    console.log("Sorting using Bubble Sort");
    // ...
    return sortedData;
  }
}
 
// Strategy: QuickSort
class QuickSortStrategy {
  sort(data) {
    // Sorting logic using quicksort
    console.log("Sorting using Quick Sort");
    // ...
    return sortedData;
  }
}
 
// Strategy: MergeSort
class MergeSortStrategy {
  sort(data) {
    // Sorting logic using mergesort
    console.log("Sorting using Merge Sort");
    // ...
    return sortedData;
  }
}
 
// Context: Sorter
class Sorter {
  constructor(strategy) {
    this.strategy = strategy;
  }
 
  setStrategy(strategy) {
    this.strategy = strategy;
  }
 
  sort(data) {
    return this.strategy.sort(data);
  }
}
 
// Usage
const data = [52819];
 
const sorter = new Sorter(new BubbleSortStrategy());
console.log(sorter.sort(data));
 
sorter.setStrategy(new QuickSortStrategy());
console.log(sorter.sort(data));
 
sorter.setStrategy(new MergeSortStrategy());
console.log(sorter.sort(data));
 
cs

위의 예에서는 세 가지 정렬 전략을 정의합니다. 각 전략은 자체 정렬 로직을 캡슐화합니다. 그런 다음 컨텍스트 역할을 하는 Sorter 클래스를 정의합니다. Sorter 클래스는 전략 객체를 받아들이고 정렬 작업을 위임합니다.

특정 전략으로 Sorter를 인스턴스화하고 sort 메서드를 호출하면 데이터를 정렬하는 데 사용할 전략을 동적으로 선택할 수 있습니다. 이를 통해 요구 사항에 따라 런타임에 다양한 정렬 알고리즘 간에 전환할 수 있습니다.

 


Express.js 라이브러리에서 보는 전략 패턴

https://expressjs.com/

 

Express - Node.js web application framework

Fast, unopinionated, minimalist web framework for Node.js $ npm install express --save

expressjs.com

 

 

전략 초기화:
Passport는 로컬, OAuth, OpenID 등 다양한 인증 전략을 제공합니다. 특정 전략을 사용하려면 애플리케이션 내에서 초기화 및 구성해야 합니다. 예를 들어 로컬 전략을 사용하려면 전략 모듈이 필요하고 필요한 옵션으로 설정해야 합니다.

1
2
3
4
const LocalStrategy = require('passport-local').Strategy;
 
passport.use(new LocalStrategy(options, verifyCallback));
 
cs

 

전략 구성:
원하는 전략을 초기화한 후 일반적으로 특정 옵션과 확인 콜백 함수를 사용하여 전략을 구성합니다. 옵션에는 사용자 이름 및 비밀번호와 같은 필드가 포함될 수 있으며, 확인 콜백은 인증 로직을 처리하고 사용자의 자격 증명을 확인합니다.

1
2
3
const verifyCallback = (username, password, done) => {
  // Verify the user's credentials and invoke the "done" callback accordingly
};
cs

 

인증 프로세스:
사용자가 인증을 시도하면 Passport는 선택한 전략에 따라 인증 프로세스를 조작합니다. 로그인 양식에서 자격 증명과 같은 필요한 정보를 수집하고 선택한 전략의 인증 콜백을 호출합니다.

1
app.post('/login', passport.authenticate('local', options));
cs

 

전략 실행:
선택한 전략의 확인 콜백은 사용자의 자격 증명을 확인하고, 필요한 경우 데이터베이스 또는 외부 서비스와 상호 작용합니다. 그런 다음 인증 결과에 따라 적절한 인수를 사용하여 완료된 콜백을 호출합니다.

1
2
3
4
5
6
7
8
9
10
11
const verifyCallback = (username, password, done) => {
  User.findOne({ username: username }, (err, user) => {
    if (err) return done(err);
 
    if (!user || !user.verifyPassword(password)) {
      return done(nullfalse, { message: 'Invalid credentials' });
    }
 
    return done(null, user);
  });
};
cs

 

인증 결과 처리하기:
인증 콜백의 done 콜백 호출에 따라 Passport는 인증 결과를 처리합니다. 인증에 성공하면 Passport는 인증된 사용자를 세션에 직렬화합니다. 인증에 실패하면 Passport는 사용자를 지정된 실패 경로로 리디렉션하거나 오류 메시지를 표시합니다.

1
2
3
4
5
6
7
8
9
passport.serializeUser((user, done) => {
  done(null, user.id);
});
 
passport.deserializeUser((id, done) => {
  User.findById(id, (err, user) => {
    done(err, user);
  });
});
cs

 


 

전략 패턴은 특히 상호 교환 가능한 여러 알고리즘이나 동작을 다룰 때 소프트웨어 개발에서 유용합니다. 이러한 알고리즘을 별도의 전략 클래스로 캡슐화함으로써 이 패턴은 유연성, 코드 재사용성, 유지보수 용이성을 촉진합니다. 자바스크립트에서 전략 패턴은 전략 클래스와 선택한 전략에 작업을 위임하는 컨텍스트 클래스를 생성하여 구현할 수 있습니다.