react-expertlisted
Install: claude install-skill LeeYudok/doksam-skills
# react-expert
컴포넌트 코드가 대상이다. 번들러·패키지 매니저·의존성은 `frontend-build`,
디자인 토큰·컴포넌트 선택은 `doksam-ui` 가 맡는다.
이 문서는 **일반론을 적지 않는다.** 판단이 갈리는 지점, 자주 틀리는 곳, React 19 에서
바뀐 것만 담는다.
## 1. 상태는 필요한 만큼만, 있어야 할 곳에
판단 순서:
1. **props 나 기존 상태에서 계산할 수 있는가** → 렌더 중에 계산한다. `useState` + `useEffect`
조합으로 파생값을 동기화하지 않는다. 이 패턴이 버그의 큰 축이다.
2. **여러 컴포넌트가 공유하는가** → 가장 가까운 공통 부모로 올린다. 전역 스토어는
"여러 화면이 같은 서버 상태를 본다"가 성립할 때만.
3. **URL 에 있어야 하는가** — 새로고침·공유·뒤로가기가 의미 있으면 라우터 상태다.
상세 화면·필터·탭이 여기 해당한다.
```tsx
// 나쁨 — 파생값을 상태로 두고 동기화
const [filtered, setFiltered] = useState<Room[]>([])
useEffect(() => { setFiltered(rooms.filter(r => r.name.includes(q))) }, [rooms, q])
// 좋음 — 렌더 중 계산
const filtered = useMemo(() => rooms.filter(r => r.name.includes(q)), [rooms, q])
```
`useMemo` 는 **측정 가능한 비용이 있을 때만**. 배열 몇 개 도는 것에 붙이면 코드만 늘어난다.
## 2. useEffect 는 "외부 시스템과 동기화"에만
effect 를 쓰기 전에 답한다: **이 코드가 맞물리려는 외부 시스템이 무엇인가?**
(네트워크, DOM 이벤트, 타이머, 구독) 답이 없으면 effect 가 아니다.
- **사용자 행동의 결과는 이벤트 핸들러에서 처리한다.** 상태를 바꾸고 그 변화를 effect 로
감지해 후속 작업을 하는 구조는 흐름을 끊고 중복 실행을 부른다.
- **StrictMode 에서 effect 는 두 번 실행된다.** 이건 버그가 아니라 정리(cleanup) 누락을
드러내는 장치다. 두 번 돌아 깨지면 effect 쪽을 고친다.
### 비동기 요청 취소는 필수
```tsx
useEffect(() => {
let alive = true
api.messages(dbRef, roomId).then(m => { if (alive) setMessages(m) })
return () => { alive = false }
}, [dbRef, roomId])
```
빠뜨리면 대상을 연달아 바꿀 때 **먼저 보낸 응답이 나중에 도착해 ���면을 덮는다**(경합).
`AbortController` 를 쓸 수 있으면 그쪽이 더 낫다 — 요청 자체를 끊는다.
### 의존성 배열을 거짓말로 채우지 않는다
린트가 요구하는 값을 빼서 "한 번만 실행"