rubric 기반 자기채점. 모범 답안: `function useInterval(callback, delay) { const onTick = useEffectEvent(callback); useEffect(() => { const id = setInterval(onTick, delay); return () => clearInterval(id); }, [delay]); }` / `function useCounter(delay) { const [count, setCount] = useState(0); useInterval(() => setCount(c => c + 1), delay); return count; }` / 캡슐화 이유: 호출처는 `const count = useCounter(1000);` 한 줄이라 useInterval 내부 구현(예: useSyncExternalStore 등)이 바뀌어도 인터페이스(인자 delay, 반환 count)가 같으므로 호출처 코드 한 글자도 바뀌지 않는다.
채점 기준:- [2점] useInterval이 callback을 useEffectEvent로 wrap하고 deps에 [delay]만 넣어 매 렌더 setInterval 재생성을 방지함
- [2점] useCounter가 useState로 count를 갖고 useInterval(() => setCount(c => c + 1), delay)로 updater 패턴 사용 (count를 deps로 노출하지 않음)
- [1점] Hook이 다른 Hook을 top-level에서 호출하는 composition 구조가 명확
- [1점] '호출처 인터페이스(인자/반환)가 동일하므로 내부 구현만 useSyncExternalStore 등으로 교체해도 callsite 변경 0' 이라는 캡슐화 보상을 명시