Skip to content

Commit 05219b0

Browse files
committed
Merge branch 'dev' of https://github.com/imaginer-dev/DateLeaf into 9-회원가입-클릭시-회원가입을-할-수-있어야-한다
2 parents 3012189 + 3abaa2c commit 05219b0

24 files changed

+7264
-8215
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# 디자인 패턴 적용에 대한 회고 - 김도영
2+
3+
기본적으로 구성된 유틸리티 함수를 Strategy 디자인 패턴을 적용해서
4+
느슨한 의존성 구조로 구현했습니다.
5+
디자인 패턴에 대해 크게 적용해본 경험이 없어서 팀원끼리 상의하고 고민해서 같이 열심히 구현해보니 설계의 중요성을 크게 느끼는 계기가 되었습니다
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# 디자인 패턴 적용 회고
2+
3+
기존에 존재하던 유틸리티 함수인 `isValidEmail` 함수와 `isValidPassword` 함수에 `Strategy` 를 적용 해 보았습니다.
4+
의존성이 강한 함수들은 아니었지만, 이 전략을 적용하며 좀 더 유연하고 다양한 `validation`을 적용할 수 있도록 구현했습니다.
5+
6+
사실 어떤 부분에 디자인 패턴을 적용할 수 있을까? 객체 지향에 해당하는 패턴인거 같아 함수형인 리액트에 적용할 일이 있나? 하고 생각했습니다.
7+
이번 기회를 통해 리액트에서는 함수형의 코드만이 아닌 객체 지향적인 설계 또한 할 수 있다는걸 알게 되었고, 객체 지향적인 설계가 가져다 주는 이점을 몸소 누릴 수 있었습니다.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
## strategy 패턴을 적용해보면서 느낀점
2+
3+
- 전략 패턴을 직접 사용해보면서 패턴의 유용성을 알 수 있었다.
4+
- 다양하게 변화 가능한 부분을 interface 를 활용하여 의존성을 줄일 수 있었다.
5+
- 앞으로 email, password 검증에 변화가 있을 때 유연하게 대응이 가능할 것 같다.
6+
- 한편으로는 앞으로 email, password 변경이 있을까. 있지 않다면 오히려 코드가 길고 복잡해진 것 같다는 생각도 들었다.
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+
```
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### 디자인 패턴 적용에 대한 회고 - 이예서
2+
3+
이론으로만 느껴졌던 디자인 패턴을 실제적으로 적용을 해보니 그 사용성을 체감할 수 있었던 것 같다.<br>
4+
`isValidEmail`, `isValidPassword` 유틸 함수에 `Strategy` 전략을 적용 해 보았다.<br>
5+
이전에 비슷한 상황에서 어떻게해야 좋은 코드를 할 수 있을까 고민했던적이 있었는데,<br>
6+
패턴을 적용하고서 보다 다양한 상황에서 적용가능하게 사용성이 좋아진것을 느꼈고<br>
7+
이번을 시작으로 디자인 패턴을 깊게 공부해보는 계기를 삼아야겠다는 생각이들었다.

0 commit comments

Comments
 (0)