Skip to content

Commit

Permalink
8, 9
Browse files Browse the repository at this point in the history
  • Loading branch information
Seojunhwan committed Nov 19, 2024
1 parent f081052 commit d7876c0
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 0 deletions.
195 changes: 195 additions & 0 deletions 챕터_8/서준환.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# 자바스크립트 MV* 패턴

## 8.1 MVC 패턴

### M 모델

모델은 애플리케이션의 데이터를 관리

모델이 변경되었을 때 뷰에 변경사항을 알려주는 역할을 한다.

> 뷰는 모델에 직접적으로 접근하지 않는다.
### V 뷰

뷰는 모델에 대한 시각적인 표현

### C 컨트롤러

모델과 뷰를 연결하는 역할

모델과 뷰 사이의 중재자 역할을 한다.


#### 만약 리액트에서 구현한다면?

```tsx
const userAPI = {
getUser: async (id: number): Promise<User> => {
return { id, name: "John", email: "john@example.com" };
},
updateUser: async (id: number, name: string): Promise<User> => {
return { id, name, email: "john@example.com" };
}
};

class UserModelMVC {
private user: User | null = null;
private listeners: Set<() => void> = new Set();

subscribe(listener: () => void) {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}

private notify() {
this.listeners.forEach(listener => listener());
}

async fetchUser(id: number) {
this.user = await userAPI.getUser(id);
this.notify();
}

async updateName(name: string) {
if (this.user) {
this.user = await userAPI.updateUser(this.user.id, name);
this.notify();
}
}

getUser() { return this.user; }
}

// MVC View
const UserViewMVC = () => {
const [user, setUser] = useState<User | null>(null);
const model = useMemo(() => new UserModelMVC(), []);

useEffect(() => {
const unsubscribe = model.subscribe(() => {
setUser(model.getUser());
});
model.fetchUser(1);
return unsubscribe;
}, [model]);

if (!user) return <div>Loading...</div>;

return (
<div>
<h2>MVC Pattern</h2>
<input
value={user.name}
onChange={e => model.updateName(e.target.value)}
/>
<div>{user.email}</div>
</div>
);
};
```

이렇게 되지 않을까?

### 8.6 MVP 패턴

### M 모델

동일

### V 뷰

동일

### P 프레젠터

모델과 뷰를 연결하는 역할, 뷰에서 이벤트 호출은 프레젠터에서 처리

#### 만약 리액트에서 구현한다면?

```tsx
class UserModelMVP {
private user: User | null = null;

async fetchUser(id: number) {
this.user = await userAPI.getUser(id);
return this.user;
}

async updateName(name: string) {
if (this.user) {
this.user = await userAPI.updateUser(this.user.id, name);
return this.user;
}
return null;
}
}

class UserPresenter {
constructor(
private model: UserModelMVP,
private setUser: (user: User) => void
) {}

async loadUser(id: number) {
const user = await this.model.fetchUser(id);
if (user) this.setUser(user);
}

async updateName(name: string) {
const user = await this.model.updateName(name);
if (user) this.setUser(user);
}
}

// MVP View
const UserViewMVP = () => {
const [user, setUser] = useState<User | null>(null);
const presenterRef = useRef<UserPresenter>();

useEffect(() => {
const model = new UserModelMVP();
presenterRef.current = new UserPresenter(model, setUser);
presenterRef.current.loadUser(1);
}, []);

if (!user) return <div>Loading...</div>;

return (
<div>
<h2>MVP Pattern</h2>
<input
value={user.name}
onChange={e => presenterRef.current?.updateName(e.target.value)}
/>
<div>{user.email}</div>
</div>
);
};
```

### 중간 정리

MVC, MVP 너무 비슷하다라는 느낌을 받았고, 실제 코드를 작성할 때도 뭔가 명확하게 나누기 어렵지 않나 라는 생각이 들었다.

## 8.8 MVVM 패턴

되게 이해가 잘 안되어서 claude 녀석의 답변을 첨부합니다,,

MVVM은 간단히 말해서 "데이터의 자동 동기화"가 핵심입니다. 실생활에서 은행 ATM을 예로 들어보겠습니다:

Model (통장): 실제 계좌의 잔액 정보를 가지고 있음
ViewModel (은행 직원): 통장의 정보를 화면에 표시할 수 있는 형태로 변환하고 관리
View (ATM 화면): 사용자에게 정보를 보여주고 입력받음

여기서 ViewModel(은행 직원)은:

Model(통장)의 잔액이 변경되면 자동으로 View(화면)에 반영
사용자가 View(화면)에서 입력한 내용을 Model(통장)에 반영
필요한 경우 데이터 형식을 변환 (예: 숫자 → 통화 형식)

> 이게 맞는 것인지 이따가 여러분들 의견좀 듣겠습니다,,
## 8.10 MV* 패턴과 리액트

> 되게 이해가 안 가는게 P.201_L4) MVC로 분류되지 않습니다, ... P.202_L2) 전통적인 MVC 형태로 동작합니다. <- 이게 대체 뭔말인지 .,,,
21 changes: 21 additions & 0 deletions 챕터_9/서준환.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 9 비동기 프로그래밍 패턴

자주 놓칠 수 있는 부분인 것만 작성하겠습니다 , ,

## 9.3 프로미스 패턴

### 9.3.3 프로미스 병렬 처리

사실 프론트엔드에서 사용할 일이 자주 있진 않은데, 백엔드 코드 작성할 땐 종종 있는 것 같아서요.\
혹은 SSR할 때?,.,

여튼 다들 아시겠지만 Promise.all 을 사용하면 병렬처리가 되는데 깜빡할 수도 있으니 , ,

### 9.3.7 프로미스 재시도

요것도 auth 처리할 때 자주 사용하는 것 같네요!

## 궁금한 것

- 여러분들은 9.4.3 비동기 에러 처리할 때 어떤 방식으로 하시나요?
- 책에 보여진 패턴(메서드) 중 어떤 것들을 사용해 보셨나요? ex) race, allSettled, any, withResolvers 등등,,

0 comments on commit d7876c0

Please sign in to comment.