콘텐츠로 이동
import { logger, persist, devtools, undoRedo } from '@hurum/core'

Middleware는 Store 생명주기 이벤트를 관찰해요. Middleware는 읽기 전용으로, 상태를 수정하거나 Event를 발행해서는 안 돼요.

type Middleware = {
name: string
onEvent?: (event: EventInstance, state: Record<string, unknown>) => void
onStateChange?: (prev: Record<string, unknown>, next: Record<string, unknown>) => void
onIntentStart?: (intent: IntentDescriptor, payload: unknown) => void
onIntentEnd?: (intent: IntentDescriptor, payload: unknown) => void
onError?: (error: Error, context: { intent: IntentDescriptor; payload?: unknown; command?: Command }) => void
}
호출 시점
onEventEvent가 Store에 적용된 후. Event와 새 상태를 받아요.
onStateChange상태 변경 후. 이전 및 다음 상태를 받아요.
onIntentStartIntent 실행이 시작될 때.
onIntentEndIntent가 완료될 때 (성공 또는 실패).
onErrorExecutor가 오류를 던질 때. 오류와 컨텍스트 (Intent, 페이로드, Command)를 받아요.
const analytics: Middleware = {
name: 'analytics',
onIntentStart: (intent, payload) => {
trackEvent('intent_started', { mode: intent.mode })
},
onError: (error) => {
reportError(error)
},
}
const MyStore = Store({ state: { ... } })
.middleware(analytics)

Middleware 객체를 직접 제공하는 대신 사용할 수 있는 대안이에요. 팩토리 패턴은 middleware에 설정 옵션이 필요할 때 유용해요.

interface MiddlewareFactory {
create(): Middleware
readonly name: string
}

.middleware()MiddlewareMiddlewareFactory 모두 받을 수 있어요.


콘솔 로깅 middleware예요. Event, 상태 변경, Intent 생명주기, 오류를 로깅해요.

function logger(options?: LoggerOptions): Middleware
옵션타입설명
filter(event: EventInstance) => boolean필터를 통과하는 Event만 로깅해요.
import { logger } from '@hurum/core'
const MyStore = Store({ state: { count: 0 } })
.middleware(logger({ filter: (e) => !e.type.startsWith('Timer/') }))

영속성 middleware예요. 상태 변경 시마다 스토리지에 상태를 저장해요. middleware와 하이드레이션 함수가 포함된 핸들을 반환해요.

function persist(options: PersistOptions): PersistHandle

PersistOptions

옵션타입기본값설명
keystring스토리지 키. 필수.
storagePick<Storage, 'getItem' | 'setItem'>localStorage스토리지 백엔드.
serialize(state) => stringJSON.stringify커스텀 직렬화기.
deserialize(raw: string) => Record<string, unknown>JSON.parse커스텀 역직렬화기.
pickstring[]이 상태 키만 영속화해요.

PersistHandle

속성타입설명
middlewareMiddleware등록할 middleware 인스턴스.
getPersistedState() => Record<string, unknown> | null스토리지에서 마지막 영속화된 상태를 읽어요.
import { persist } from '@hurum/core'
const storage = persist({ key: 'my-store', pick: ['todos', 'settings'] })
const MyStore = Store({ state: { todos: [], settings: {} } })
.middleware(storage.middleware)
// Hydrate from storage on startup
const store = MyStore.create({
initialState: storage.getPersistedState() ?? undefined,
})

Redux DevTools Extension 연동이에요. 검사를 위해 Event와 상태를 브라우저 확장 프로그램에 전송해요.

function devtools(options?: DevToolsOptions): DevToolsHandle

DevToolsOptions

옵션타입기본값설명
namestring'Hurum Store'DevTools 패널에 표시할 이름.

DevToolsHandle

속성타입설명
middlewareMiddleware등록할 middleware 인스턴스.
connect(store: { getState: () => Record<string, unknown> }) => voidDevTools 연결을 초기화하려면 Store.create() 이후에 호출하세요.
import { devtools } from '@hurum/core'
const dt = devtools({ name: 'Cart' })
const CartStore = Store({ state: { items: [] } })
.middleware(dt.middleware)
const store = CartStore.create()
dt.connect(store)

실행 취소/다시 실행 middleware예요. 앱 내 시간 여행을 위해 상태 이력을 추적해요.

function undoRedo(options?: UndoRedoOptions): UndoRedoHandle

UndoRedoOptions

옵션타입기본값설명
maxHistorynumber50유지할 상태 스냅샷의 최대 개수.

UndoRedoHandle

속성타입설명
middlewareMiddleware등록할 middleware 인스턴스.
undo() => Record<string, unknown> | null이전 상태를 복원해요. 시작 지점이면 null을 반환해요.
redo() => Record<string, unknown> | null다음 상태를 복원해요. 끝 지점이면 null을 반환해요.
canUndo() => boolean실행 취소 작업이 가능한지 여부.
canRedo() => boolean다시 실행 작업이 가능한지 여부.
getHistory() => readonly Record<string, unknown>[]전체 상태 이력.
getPosition() => number이력에서의 현재 위치.
import { undoRedo } from '@hurum/core'
const history = undoRedo({ maxHistory: 30 })
const EditorStore = Store({ state: { content: '' } })
.middleware(history.middleware)
const store = EditorStore.create()
// Later, in response to user actions:
const prevState = history.undo()
const nextState = history.redo()

  • Middleware 훅은 등록 순서대로 동기적으로 호출돼요.
  • Middleware는 순수하게 관찰만 해요. Middleware에서 상태를 변경하거나 Event를 발행하는 것은 지원되지 않으며 정의되지 않은 동작을 유발해요.
  • 여러 middleware 인스턴스를 .middleware(a, b, c) 또는 체이닝 .middleware(a).middleware(b)로 등록할 수 있어요.
  • 핸들을 반환하는 내장 middleware (persist, devtools, undoRedo)는 middleware 인스턴스와 제어 API를 분리해요. .middleware 속성을 등록하고 핸들로 상호작용하세요.