반응형
옵저버 패턴이란? 📖
객체의 상태 변화를 관찰하는 옵저버(Observer)들이 있고, 관찰 대상이 되는 객체(Subject)가 상태 변화가 있을 때 옵저버들에게 알리는 디자인 패턴입니다.
❗간단하게 설명하면
- 어떤 데이터나 상태의 변화가 일어났을 때, 실시간으로 구독자들에게 알려주는 방식
`Subject (주체)` : 상태를 보유하고 있고, 변화가 일어났을 때 옵저버들에게 알리는 역할
`Observer (옵저버)` : 주체의 상태 변화를 감지하고 그에 따라 행동
옵저버 패턴 직접 만들어보기 📖
subject.js
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();
`addObserver`는 `observers`에다 특정 key값을 두고 특정 callback을 등록(push) 시킵니다.
const observers = new Map();
const addObserver = (key, observer) => {
if(!observers.has(key)){
observers.set(key, []);
}
observers.get(key).push(observer);
}
`notify`는 특정 key값에 맞는 callback을 전부 실행시킵니다.
const notify = (key, data) => {
if(observers.has(key)){
observers.get(key).forEach((observer) => observer(data))
}
}
`subscribe`는 옵저버를 구독하는 역할을 합니다.
const subscribe = (key, callback) => {
addObserver(key, callback)
return () => removeObserver(key, callback)
}
useCounterObserver.js
import React, { useEffect, useState } 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]
}
export default useCounterObserver
화면이 렌더링 됐을 때 `counter`라는 key값으로 옵저버를 등록하고 `callback`으로 setState를 넘겨주고 있습니다.
const [state, setState] = useState(0);
useEffect(() => {
const unsubscribe = subject.subscribe('counter', setState);
return () => unsubscribe();
}, [])
`increment`는 상태를 업데이트하고 구독자들에게 알림을 주는 함수입니다.
const increment = () => {
const newState = state + 1;
subject.notify('counter', newState) // 'counter'업데이트
}
App.jsx
import './App.css'
import useCounterObserver from './useCounterObserver'
const CounterComponent = () => {
const [count, increment] = useCounterObserver();
return (
<div>
<p>count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
)
}
function App() {
return (
<div>
<h1>옵저버 패턴</h1>
<CounterComponent />
<CounterComponent />
</div>
)
}
export default App
App.jsx에서 위 코드와 같이 버튼을 눌렀을 때 `counter`라는 key값을 공유하기 때문에 `count`값이 동일하게 증가합니다.
반응형
'공부 > TIL' 카테고리의 다른 글
[TIL] 24.07.18 Swiper 슬라이드 (0) | 2024.07.18 |
---|---|
[TIL] 24.07.17 쓰로틀링(성능 측정) (0) | 2024.07.17 |
[TIL] 24.07.16 코딩 컨벤션이란? (0) | 2024.07.16 |
[TIL] 24.07.15 (0) | 2024.07.15 |
[TIL] 24.07.09 백준 10844번 js (0) | 2024.07.09 |
[TIL] 24.07.08 (0) | 2024.07.08 |
[TIL] 24.06.17 백준 1373번 js (0) | 2024.06.17 |
[TIL] 24.06.12 백준 1676번 js (2) | 2024.06.12 |