여러 단계의 비동기 UI 업데이트를 setLoading → setProgress → setLoading(false)로 흩뿌리지 않고 async generator의 yield 시퀀스로 시간 순서대로 표현. 원본 트릭은 @ericclemmons.
언제 — generator는 시간이 코드의 한 방향(↓)으로만 흐르는 모델이다. 그 모양에 맞는 시나리오:
- 멀티 단계 loading 메시지 (아래
loadingFlow) - progressive search — tier별로 점진적 결과 yield, tier 경계가 자연스러운 cancellation point, debounce 불필요
- optimistic mutation —
{ phase: 'optimistic' | 'reconciled' | 'rolledBack', data }전이를 4개 콜백 대신 한 함수로
절차
type FlowEvent<P extends string, D> = { phase: P; data: D }
async function* loadingFlow(
signal: AbortSignal,
): AsyncGenerator<FlowEvent<'starting' | 'slow' | 'done', string>> {
yield { phase: 'starting', data: 'Starting…' }
await wait(1000, signal)
yield { phase: 'slow', data: 'Taking longer than usual' }
await wait(2000, signal)
yield { phase: 'done', data: 'Got it 🎉' }
}
확인 — 감싸는 레이어(hook이든 actor든)에서 여섯을 다 채웠는가. 원본 데모는 전부 비어 있다:
- cancellation: generator에
AbortSignal주입 →await대상(wait,fetch)이 signal-aware해야 진짜 취소됨 - 재진입: 새 실행 시 직전 iterator abort
- error path: generator 내부 throw → 상태 노출
- unmount/teardown: cleanup으로 in-flight iterator abort
- stale closure: 최신 클로저 참조 (hook은 ref, actor는 input)
- typed:
phase/data모두 좁힘
바깥 클릭 감지를 useEffect 없이 ref callback 하나로 만든다.
언제: React 19 이상일 때. 18 이하는 아래 함정을 보고 useEffect 쪽을 쓴다.
절차
function useClickOutside(handler) {
const handlerRef = useRef(handler)
handlerRef.current = handler // stale closure 방지
return useCallback((node) => {
const handleClick = (e) => {
if (!node.contains(e.target)) handlerRef.current()
}
document.addEventListener('mousedown', handleClick)
return () => document.removeEventListener('mousedown', handleClick)
}, [])
}
// 사용
function Modal({ onClose }) {
const ref = useClickOutside(onClose)
return <div ref={ref}>...</div>
}
확인: 모달을 여러 번 열고 닫은 뒤 바깥을 클릭한다. 핸들러가 한 번만 불리면 cleanup이 돌고 있는 것이다 — 안 돌면 옛 리스너가 쌓여 여러 번 불린다.
함정
- ref callback은 DOM 노드 참조만 전달한다. 안에서 등록한 리스너 같은 사이드이펙트는 자동 해제되지 않는다.
- React 18 이하에서는 이 패턴이 안 된다. unmount 시
callback(null)은 오지만 동일 함수 참조가 없어removeEventListener를 못 부른다 → 리스너를 별도 ref에 저장해야 한다. cleanup return을 공식 지원하는 건 React 19부터다.
참고
에이전트 코딩 환경 — 워크트리·포트·자격증명
병렬 에이전트를 돌릴 때 워크트리 위치·포트·gitignore 파일·토큰 범위를 결정적으로 고정하는 레시피.
언제 — 워크트리를 여럿 띄웠는데 서로의 서버를 죽이거나, 의존성 검증이 거짓 통과하거나, 새 워크트리에서 첫 명령이 실패할 때.
에이전트 신뢰 구축 — 검증 경로부터 자동 머지까지
사람이 검증자 자리에서 내려오는 순서. 진단 → 검증 스킬 → 스킬 승격 → 하드 제약 → 병렬화 → 자동 머지.