Skip to content

Commit 7027dc1

Browse files
committed
docs: 유효성검증 디자인패턴 md파일 업로드
1 parent 1bd266b commit 7027dc1

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
## Strategy Pattern(전략패턴) 회고
2+
3+
- **구현전**
4+
초기에 간단한 함수를 사용하여 이메일과 비밀번호 유효성 검사를 하였습니다. 간단했지만, 다양한 검증 로직을 필요로 하는 다른 시나리오에서는 대응하기 어려웠습니다.
5+
특히 코드 중복과 유지 관리에 어려움이 있을 것이라고 생각되었습니다.
6+
7+
- **1차 구현**
8+
첫 번째 구현에서는 'ValidationStrategy' 인터페이스를 통해 유효성 검증 로직을 캡슐화 했습니다. 또한 각 검증 로직을 독립된 클래스로 구현하여,
9+
필요에 따라 유효성 검사 전략을 교체할 수 있도록 설계하였습니다. 이 방식은 검증 로직을 유연하게 관리할 수 있게 해주었으나, 여전히
10+
이메일과 비밀번호 검증을 별도의 메서드로 처리해야 했던 개선점이 필요했습니다.
11+
12+
- **2차 구현**
13+
두 번째 구현에서는 이메일과 비밀번호 검증을 모두 포함할 수 있도록 'ValidationStrategy'인터페이스를 확장하였습니다.
14+
또한 'LooseValidation'와 'StrongValidation' 클래스를 통해 다양한 유효성 검증을 추가하였습니다.
15+
16+
디자인 패턴을 이번 프로젝트에 처음 도입하면서 많은 것을 배운 것 같습니다. 사실 디자인 패턴을 주는 이미지가 어렵고 복잡할 것 같은 생각을 많이 했습니다.
17+
하지만 실제로 패턴을 적용해보니, 그렇게 어려운 것만은 아니였고 오히려 코드의 구조를 훨씬 명확하게 이해할 수 있게 해주었습니다.
18+
우효성 검증 로직이 아직은 기대했던 대로 잘 작동되어지지만, 만약 회원가입에서 사용할 때나 일정관리 등록이나 프로필 수정 등에서는 더 복잡하게 들어갈 것으로 예상되어 집니다. 그 부분은 어떻게 구현해야 될지 아직 고민이지만, 이러한 전략패턴 도입으로 유효성 검증을 한데 모아 관리할 수 있게 되어 좋은 것 같습니다.
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
## 목적
2+
3+
Validation Strategy 유효성 검증 설계 : 이메일과 비밀번호와 같은 유효성 검증을 위한 인터페이스를 정의합니다.
4+
(Strategy Pattern(전략패턴) : 알고리즘을 객체의 일부분으로 캡슐화하여 독립적으로 알고리즘을 변경가능)
5+
6+
## 대상
7+
8+
유효성 검사가 필요한 파일
9+
10+
### `로그인 폼`
11+
12+
- **디자인 패턴 유형**
13+
- Strategy Pattern(전략패턴)
14+
- **시나리오**
15+
16+
- 이메일 및 비밀번호 유효성 검사에, 특정한 조건의 유효성 검사가 추가될 경우를 위해 디자인 패턴 적용
17+
(LooseValidation, StrongValidation)
18+
19+
```
20+
classDiagram
21+
class ValidationStrategy {
22+
+emailValidate(input: string) bool
23+
+passwordValidate(input: string) bool
24+
}
25+
class LooseValidation {
26+
+emailValidate(input: string) bool
27+
+passwordValidate(input: string) bool
28+
}
29+
class StrongValidation {
30+
+emailValidate(input: string) bool
31+
+passwordValidate(input: string) bool
32+
}
33+
class ValidateProcessor {
34+
-ValidationStrategy validator
35+
+ValidateProcessor(validator)
36+
+setValidator(validator)
37+
+isValidEmail(email: string) bool
38+
+isValidPassword(password: string) bool
39+
}
40+
41+
ValidationStrategy <|-- LooseValidation : implements
42+
ValidationStrategy <|-- StrongValidation : implements
43+
ValidateProcessor o-- ValidationStrategy : uses
44+
45+
LooseValidation ..> ValidateProcessor : uses
46+
StrongValidation ..> ValidateProcessor : uses
47+
```
48+
49+
- **전략 패턴 구현 경로**
50+
51+
- 1. 전략 인터페이스 구현 : 위 인터페이스는 #validator라는 메소드를 포함하고 있으며, 이 메소드는 문자열을 입력받아 boolean 값으로 유효성을 반환합니다.
52+
- 2. 구체적인 전략 클래스 만들기 : 각 클래스는 ValidationStrategy 인터페이스를 구현하며, 이메일과 비밀번호에 대한 구체적인 검증 로직을 제공합니다.
53+
이 클래스들은 각각 이메일과 비밀번호 검증 로직을 캡슐화하며, validate 메소드를 통해 입력된 데이터의 유효성을 검사합니다.
54+
이 방식은 검증 로직을 변경하거나 다른 유형의 검증 로직으로 쉽게 교체할 수 있게 해줍니다. 예를 들어, 비밀번호 정책이 변경되어 검증 로직을 업데이트해야 하는 경우, 해당하는 LooseValidation 클래스만 수정하면 됩니다.
55+
- 3. 비밀번호가 특정 조건 추가 StrongValidation (예: 최소 한 개의 숫자, 하나의 대문자 및 특수 문자 포함)을 충족하는지 확인하는 전략.
56+
57+
- **어떤 문제를 해결하고자 했는지**
58+
59+
- 유연성 부족: 하나의 유효성 검증이 다양한 시나리오에 맞게 우연하게 조정되지 못하는 문제 (ex 로그인 비밀번호 유효성은 느슨한 유효성을 사용하며, 회원가입 유효성은 느슨한 유효성에 보안을 위한 강력한 특정 조건 추가)
60+
- 코드 중복 : 비슷한 유효성 검증 로직이 여러 부분 반복적으로 사용되어 코드 중복이 발생하는 문제
61+
- 낮은 확장성 : 새로운 유효성 검증 로직을 추가하거나 기존 로직을 수정할 때 기존 코드를 많이 변경해야하는 문제.
62+
63+
- **왜 해당 디자인 패턴을 선택했는지**
64+
- Observer : 이벤트 발생에 따른 여러 객체의 반응을 관리할 때 사용되어지므로, 데이터 자체의 유효성 판단에는 적합하지 않다고 생각되어졌습니다.
65+
- Singleton : 전역에서 하나의 인스턴스만 보장하는 패턴이므로 제한적이여서 적합하지 않다고 생각되었습니다.
66+
- Factory Method와 Abstract Factory : 객체 생성에 초점을 맞춘 패턴으로, 유효성 검증 보다는 로직의 교체와 실행에 더 어울릴 것 같아서 제외하였습니다.
67+
- 위와 같은 여러가지 패턴들 중에 전략 패턴은 유효성과 같이 코드의 재사용성과 유지보수 확장성에 더 어울리다고 생각하여서 해당 패턴을 선택하였습니다.
68+
69+
- **코드**
70+
71+
- 구현 전
72+
73+
```
74+
export const isValidEmail = (email: string): boolean => {
75+
const regex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
76+
return regex.test(email);
77+
};
78+
79+
export const isValidPassword = (password: string) => {
80+
return password.length >= 6;
81+
};
82+
83+
```
84+
85+
- 1차 구현
86+
87+
```
88+
export interface ValidationStrategy {
89+
validate(input: string): boolean;
90+
}
91+
92+
export class isValidEmail implements ValidationStrategy {
93+
validate(email: string): boolean {
94+
return /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/.test(email);
95+
}
96+
}
97+
98+
export class isValidPassword implements ValidationStrategy {
99+
validate(password: string): boolean {
100+
return password.length >= 6;
101+
}
102+
}
103+
104+
export class isValidPasswordComplex implements ValidationStrategy {
105+
validate(password: string): boolean {
106+
const regex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/;
107+
return regex.test(password);
108+
}
109+
}
110+
```
111+
112+
- 2차 구현
113+
114+
```
115+
export interface ValidationStrategy {
116+
emailValidate(input: string): boolean;
117+
passwordValidate(input: string): boolean;
118+
}
119+
120+
export class LooseValidation implements ValidationStrategy {
121+
emailValidate(email: string): boolean {
122+
return /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/.test(email);
123+
}
124+
passwordValidate(input: string): boolean {
125+
return input.length >= 6;
126+
}
127+
}
128+
129+
export class StrongValidation implements ValidationStrategy {
130+
emailValidate(password: string): boolean {
131+
return password.length >= 6;
132+
}
133+
passwordValidate(input: string): boolean {
134+
const regex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/;
135+
return regex.test(input);
136+
}
137+
}
138+
139+
export class ValidateProcessor {
140+
#validator: ValidationStrategy;
141+
constructor(validator: ValidationStrategy) {
142+
this.#validator = validator;
143+
}
144+
145+
setValidator(validator: ValidationStrategy) {
146+
this.#validator = validator;
147+
}
148+
149+
isValidEmail(email: string) {
150+
return this.#validator.emailValidate(email);
151+
}
152+
153+
isValidPassword(password: string) {
154+
return this.#validator.passwordValidate(password);
155+
}
156+
}
157+
```

0 commit comments

Comments
 (0)