전략 패턴이란?
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 = [5, 2, 8, 1, 9];
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 라이브러리에서 보는 전략 패턴
전략 초기화:
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(null, false, { 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 |
전략 패턴은 특히 상호 교환 가능한 여러 알고리즘이나 동작을 다룰 때 소프트웨어 개발에서 유용합니다. 이러한 알고리즘을 별도의 전략 클래스로 캡슐화함으로써 이 패턴은 유연성, 코드 재사용성, 유지보수 용이성을 촉진합니다. 자바스크립트에서 전략 패턴은 전략 클래스와 선택한 전략에 작업을 위임하는 컨텍스트 클래스를 생성하여 구현할 수 있습니다.
'CS' 카테고리의 다른 글
이터레이터 패턴 ( Iterator Pattern ) (0) | 2023.06.29 |
---|---|
프록시 패턴 ( Proxy Pattern ) (0) | 2023.06.25 |
옵저버 패턴 ( Observer Pattern ) (0) | 2023.06.24 |
팩토리 패턴 ( Factory Pattern ) (0) | 2023.06.24 |
싱글톤 패턴 ( Singleton Pattern ) (1) | 2023.06.14 |