observer 패턴과 pub-sub 패턴에 대해 알아보자.
const createSubject = () => {
const observers = new Map();
const addObserver = (key, observer) => {
if (!observers.has(key)) {
observers.set(key, []);
}
observers.get(key).push(observer);
};
const removeObserver = (key, observer) => {
if (observers.has(key)) {
const filtered = observers.get(key).filter((obs) => obs !== observer);
observers.set(key, filtered);
}
};
const notify = (key, data) => {
if (observers.has(key)) {
observers.get(key).forEach((observer) => observer(data));
}
};
const subscribe = (key, callback) => {
addObserver(key, callback);
return () => removeObserver(key, callback);
};
return { notify, subscribe };
};
export const subject = createSubject();
import { useState, useEffect } from "react";
import { subject } from "./Subject";
export const useCounterObserver = () => {
const [state, setState] = useState(0);
useEffect(() => {
const unsubscribe = subject.subscribe("counter", setState);
return () => unsubscribe();
}, []);
// 상태를 업데이트하고 구독자들에게 알림을 주는 함수
const increment = () => {
const newState = state + 1;
subject.notify("counter", newState); // 'counter' 키에 대해 알림
};
return [state, increment];
};
import React from "react";
import { useCounterObserver } from "./useCounterObserver";
const CounterComponent = () => {
const [count, increment] = useCounterObserver();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
};
const App = () => {
return (
<div>
<h1>React Observer Pattern with Closures</h1>
<CounterComponent />
<CounterComponent />
</div>
);
};
export default App;
const event = {
list: new Map(),
on(eventType, eventAction) {
this.list.has(eventType) || this.list.set(eventType, []);
if (this.list.get(eventType)) this.list.get(eventType).push(eventAction);
return this;
},
emit(eventType, ...args) {
this.list.get(eventType) &&
this.list.get(eventType).forEach((cb) => {
cb(...args);
});
}
};
export const Modal = () => {
const [content, setContent] = useState("no content");
const [showModal, setShowModal] = useState(false);
const setMessage = (message) => {
setContent(message);
setShowModal(true);
};
const clearMessage = () => {
setContent("");
setShowModal(false);
};
useEffect(() => {
event.on("showModal", setMessage).on("clearAllMessage", clearMessage);
}, []);
if (showModal) {
return (
<Container>
<h2>{content}</h2>
<button onClick={clearMessage}>Close Modal </button>
</Container>
);
}
return null;
export const ModalPublisher = {
message: (content) => {
event.emit("showModal", content);
},
clearAllMessage: () => {
event.emit("clearAllMessage");
}
};
function App() {
return (
<div className="App">
<Modal showModal={true} />
<h1
onClick={() => {
ModalPublisher.message("this is the content from App");
}}
>
Hello CodeSandbox
</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
| 항목 | Observer 패턴 | Pub-Sub 패턴 |
|---|---|---|
| 구성 요소 | Subject, Observer | Publisher, Subscriber, Event Channel |
| 관계 | Subject가 Observer를 알고 있어야 하며, 직접 통지함 | Publisher와 Subscriber는 서로 모름, 중간에 Event Channel이 존재 |
| 결합도 | 강한 결합 (Subject와 Observer 간) | 느슨한 결합 (Publisher와 Subscriber는 서로 독립적) |
| 알림 방식 | Subject가 직접 Observer에게 알림 | Event Channel을 통해 간접적으로 메시지를 전달 |
| 처리 방식 | 일반적으로 동기적으로 알림 | 비동기적으로 이벤트 전달 가능 |