사용자 검수 전 — Hook은 함수 컴포넌트에서 State, Ref, Effect, Context 같은 React 기능을 쓰게 한다. 이름보다 먼저 “언제 재렌더가 필요한가”, “무엇과 동기화하는가”, “값과 함수를 왜 보존하는가”를 구분한다.
§ 00 · Hooks — React 기능에 접속하는 함수
Hook은 이름이 use로 시작하며 함수 컴포넌트가 State와 React의 여러 기능을 사용하게 한다. 내장 Hook을 조합해 반복되는 상태 로직을 별도 함수로 꺼내면 커스텀 Hook이 된다. 커스텀 Hook은 로직을 공유하지만 State 자체를 여러 컴포넌트가 자동 공유하게 하지는 않는다.
Hook은 컴포넌트나 다른 Hook의 최상위에서만 호출한다. 조건문, 반복문, 중첩 함수 안에서 호출하면 안 된다. React가 호출 순서로 각 Hook의 상태를 대응시키기 때문이다. 일반 JavaScript 함수에서는 Hook을 호출하지 않는다.
§ 01 · useState와 useRef — 보이는 기억, 보이지 않는 기억
useState는 값이 화면에 영향을 줄 때 쓴다. setter로 갱신하면 React가 다음 렌더를 예약한다. 이전 State로 다음 값을 계산한다면 setCount(count => count + 1)처럼 updater 함수를 쓰면 오래된 값에 기대는 실수를 줄일 수 있다.
useRef는 렌더 사이에 값을 보존하지만 ref.current를 바꿔도 재렌더를 일으키지 않는다. DOM 노드를 가리키거나 타이머 ID, 이전 값처럼 화면 계산에 직접 필요하지 않은 정보를 저장할 때 알맞다. 화면에 보여야 하는 값을 Ref에 두면 값은 바뀌어도 화면은 따라오지 않는다.
§ 02 · useEffect — 외부 시스템과 동기화한다
useEffect는 컴포넌트를 네트워크 연결, 브라우저 API, 타이머, 제3자 위젯 같은 React 바깥의 시스템과 동기화하는 Hook이다. 단순히 “렌더 뒤에 코드를 실행하는 곳”으로 외우면 State에서 계산할 수 있는 값까지 Effect로 옮겨 불필요한 재렌더와 반복 실행을 만들기 쉽다.
setup 함수는 필요하면 cleanup 함수를 반환한다. cleanup은 다시 동기화하기 전과 컴포넌트가 사라질 때 연결·구독·타이머를 정리한다. 의존성 배열에는 Effect가 읽는 반응형 값을 빠짐없이 적는다. 배열을 비워 실행 횟수를 억지로 맞추기보다 Effect가 무엇과 동기화되는지부터 다시 본다.
§ 03 · useReducer — 상태 전환을 한 함수에 모은다
useReducer는 상태 갱신 규칙이 많거나 여러 필드가 함께 바뀔 때 그 규칙을 reducer 함수에 모은다. 컴포넌트는 dispatch로 “무슨 일이 일어났는가”를 나타내는 action을 보내고, reducer는 현재 state와 action을 받아 다음 state를 계산한다.
reducer는 순수해야 하며 기존 State를 직접 변경하지 않는다. useState보다 항상 우월한 것은 아니다. 단순한 값 몇 개는 useState가 읽기 쉽고, 상태 전환의 종류가 늘어나 이벤트 핸들러 곳곳에 갱신 로직이 흩어질 때 useReducer의 장점이 커진다.
§ 04 · Context — 트리 깊숙이 공통 값을 전달한다
Context는 테마, 언어, 로그인 정보처럼 많은 하위 컴포넌트가 읽어야 하는 값을 중간 컴포넌트마다 Props로 전달하지 않고 트리 아래로 공급하는 통로다. Provider가 값을 제공하고 useContext가 가장 가까운 상위 Provider의 값을 읽고 구독한다.
Context가 모든 State를 전역으로 만드는 만능 저장소는 아니다. 값이 바뀌면 그것을 읽는 컴포넌트가 다시 렌더되므로, 자주 바뀌는 거대한 객체 하나를 무심코 넣으면 영향 범위가 커진다. 먼저 Props와 State 위치 조정으로 해결되는지 보고, 멀리 떨어진 여러 소비자가 정말 같은 값을 필요로 할 때 쓴다.
§ 05 · useCallback — 함수 자체를 보존한다
useCallback은 의존성이 바뀌지 않은 동안 같은 함수 정의를 돌려준다. memo로 감싼 자식에게 콜백을 Props로 넘기거나, 다른 Hook의 의존성으로 함수의 정체성이 중요할 때 사용할 수 있다. 함수를 실행하거나 결과를 저장하는 Hook은 아니다.
useMemo는 계산 결과를, useCallback은 함수 자체를 보존한다. memo는 Props가 같을 때 컴포넌트 재렌더를 건너뛰는 최적화다. 셋 모두 정확성을 위한 필수 문법이 아니라 측정된 성능 문제를 줄이는 도구다. 모든 함수에 useCallback을 붙이면 의존성 관리와 코드 복잡성만 늘 수 있다.
Read this note at sass.studio.