좋은 Action 하나 생기면 감싸고 싶어짐. 모든 action 로그. 확인 단계 추가. 성공에 follow-up 돌리기. 패턴 셋이 대부분 커버.
패턴 1 — 횡단 관심사로 action 래핑
모든 save action 을 분석 서비스에 로그하고 싶음. 어떤 action 도 감싸고 side effect 추가하는 higher-order action 작성:
function withLogging<S>(name: string, action: (s: S, fd: FormData) => Promise<S>) {
return async (s: S, fd: FormData): Promise<S> => {
logEvent(`action.start.${name}`);
try {
const result = await action(s, fd);
logEvent(`action.success.${name}`);
return result;
} catch (e) {
logEvent(`action.failure.${name}`);
throw e;
}
};
}
const loggedSaveDraft = withLogging('saveDraft', saveDraft);
패턴 2 — 단일 제출에 action 체인
가끔 제출 하나가 action 둘 트리거 (draft 저장, 그 다음 이메일 보냄). Action 함수 안에서 composition:
async function saveAndNotify(_prev, fd) {
const draft = await saveDraft(fd);
await sendNotification(draft.id);
return draft;
}
React 시점에선 Action 하나로 유지 — pending state 가 체인 전체 걸침.
패턴 3 — 재사용 가능한 action 로직을 hook 으로 추출
같은 action 연결 (유효성, 로깅, optimistic 업데이트) 이 컴포넌트들에 반복되면 커스텀 hook 으로 감쌈. Hook 이 action 과 관련 state 노출.
Action 은 함수; 함수는 합성됨. 특별한 프레임워크 필요 없음. 명확성 위해 평범한 async 함수 리팩토링한다면 Action 도 같은 방식으로. 로깅, 재시도, rate limiting, optimistic-update 셋업 — 다 그냥 함수 합성.