Built-in React Hooks

김동현·2026년 3월 17일

React 내장 Hooks

Hooks를 사용하면 컴포넌트에서 다양한 React 기능들을 사용할 수 있어요. React에서 기본으로 제공하는 내장 Hooks를 그대로 사용할 수도 있고, 이것들을 조합해서 나만의 커스텀 Hook을 만들 수도 있어요. 이 페이지에서는 React에 내장된 모든 Hooks를 나열하고 있어요.


State Hooks (상태 Hooks)

State는 컴포넌트가 사용자 입력 같은 정보를 "기억"할 수 있게 해줘요. 예를 들어, 폼(form) 컴포넌트는 state를 사용해서 입력값을 저장할 수 있고, 이미지 갤러리 컴포넌트는 state를 사용해서 현재 선택된 이미지의 인덱스를 저장할 수 있어요.

컴포넌트에 state를 추가하려면, 다음 Hooks 중 하나를 사용하면 돼요:

  • useState는 직접 업데이트할 수 있는 state 변수를 선언해요.
  • useReducerreducer 함수 안에 업데이트 로직을 담은 state 변수를 선언해요.

💡 부연 설명: useState는 간단한 상태를 관리할 때 쓰고, useReducer는 상태 업데이트 로직이 복잡하거나 여러 개의 하위 값을 다뤄야 할 때 유용해요. Redux의 reducer 패턴과 비슷하다고 생각하면 이해하기 쉬워요.

// ImageGallery 컴포넌트 예시
function ImageGallery() {
  const [index, setIndex] = useState(0);
  // ...

Context Hooks (컨텍스트 Hooks)

Context는 컴포넌트가 props로 전달하지 않고도 멀리 떨어진 부모 컴포넌트로부터 정보를 받을 수 있게 해줘요. 예를 들어, 앱의 최상위 컴포넌트가 현재 UI 테마를 그 아래에 있는 모든 컴포넌트에 전달할 수 있는데, 아무리 깊이 중첩되어 있어도 상관없어요.

💡 부연 설명: 보통 props를 통해 데이터를 전달하면, 중간에 있는 컴포넌트들이 해당 데이터를 사용하지 않더라도 계속 넘겨줘야 하는 "props drilling" 문제가 생기는데, Context를 사용하면 이 문제를 깔끔하게 해결할 수 있어요.

  • useContext는 context를 읽고 구독(subscribe)해요.
// Button 컴포넌트 예시
function Button() {
  const theme = useContext(ThemeContext);
  // ...

Ref Hooks (레프 Hooks)

Refs는 컴포넌트가 렌더링에 사용되지 않는 정보를 보관할 수 있게 해줘요. 예를 들어 DOM 노드라든가 타임아웃 ID 같은 것들이요. state와 달리, ref를 업데이트해도 컴포넌트가 다시 렌더링되지 않아요. Refs는 React 패러다임에서 벗어나는 일종의 "탈출구(escape hatch)"예요. 브라우저 내장 API 같은 React가 아닌 시스템과 작업해야 할 때 유용해요.

💡 부연 설명: ref는 .current 프로퍼티를 가진 객체인데, 이 값을 자유롭게 읽고 쓸 수 있어요. state를 변경하면 리렌더링이 발생하지만, ref를 변경하면 리렌더링이 일어나지 않기 때문에, 렌더링과 무관한 값을 저장할 때 딱 좋아요.

  • useRef는 ref를 선언해요. 어떤 값이든 담을 수 있지만, 대부분 DOM 노드를 담는 데 사용돼요.
  • useImperativeHandle은 컴포넌트가 노출하는 ref를 커스터마이즈할 수 있게 해줘요. 이건 거의 사용되지 않아요.
// Form 컴포넌트 예시
function Form() {
  const inputRef = useRef(null);
  // ...

Effect Hooks (이펙트 Hooks)

Effects는 컴포넌트가 외부 시스템에 연결하고 동기화할 수 있게 해줘요. 여기에는 네트워크, 브라우저 DOM, 애니메이션, 다른 UI 라이브러리로 작성된 위젯, 그리고 기타 React가 아닌 코드를 다루는 것이 포함돼요.

  • useEffect는 컴포넌트를 외부 시스템에 연결해요.
// ChatRoom 컴포넌트 예시
function ChatRoom({ roomId }) {
  useEffect(() => {
    const connection = createConnection(roomId);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]);
  // ...

Effects는 React 패러다임에서 벗어나는 "탈출구(escape hatch)"예요. 애플리케이션의 데이터 흐름을 조율하는 데 Effects를 사용하지 마세요. 만약 외부 시스템과 상호작용하는 게 아니라면, Effect가 필요 없을 수도 있어요.

💡 부연 설명: 초보자들이 흔히 하는 실수 중 하나가 데이터 페칭이나 state 동기화 같은 걸 전부 useEffect로 처리하는 건데요, 꼭 필요한 경우가 아니면 Effect 없이 해결할 수 있는 방법을 먼저 고려해보는 게 좋아요.

useEffect에는 실행 타이밍이 다른, 잘 사용되지 않는 두 가지 변형이 있어요:

  • useLayoutEffect는 브라우저가 화면을 다시 그리기(repaint) 전에 실행돼요. 여기서 레이아웃을 측정할 수 있어요.
  • useInsertionEffect는 React가 DOM에 변경을 가하기 전에 실행돼요. 라이브러리에서 동적 CSS를 삽입하는 데 사용할 수 있어요.

또한 이벤트를 Effects로부터 분리할 수도 있어요:

  • useEffectEvent는 어떤 Effect Hook에서든 발생시킬 수 있는 비반응형(non-reactive) 이벤트를 만들어요.

Performance Hooks (성능 Hooks)

리렌더링 성능을 최적화하는 일반적인 방법은 불필요한 작업을 건너뛰는 거예요. 예를 들어, React에게 캐시된 계산 결과를 재사용하라고 알려주거나, 이전 렌더링 이후 데이터가 변경되지 않았다면 리렌더링을 건너뛰라고 알려줄 수 있어요.

계산과 불필요한 리렌더링을 건너뛰려면, 다음 Hooks 중 하나를 사용하세요:

  • useMemo는 비용이 많이 드는 계산의 결과를 캐시할 수 있게 해줘요.
  • useCallback은 최적화된 컴포넌트에 전달하기 전에 함수 정의를 캐시할 수 있게 해줘요.

💡 부연 설명: useMemo을 메모이제이션하고, useCallback함수를 메모이제이션한다고 생각하면 쉬워요. 둘 다 의존성 배열(dependency array)에 있는 값이 변경되지 않으면 이전에 캐시한 결과를 그대로 반환해요.

// TodoList 컴포넌트 예시
function TodoList({ todos, tab, theme }) {
  const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
  // ...
}

때로는 화면이 실제로 업데이트되어야 하기 때문에 리렌더링을 건너뛸 수 없는 경우도 있어요. 그런 경우에는, 반드시 동기적이어야 하는 차단(blocking) 업데이트(예: 입력 필드에 타이핑하는 것)와 사용자 인터페이스를 차단할 필요가 없는 비차단(non-blocking) 업데이트(예: 차트 업데이트)를 분리해서 성능을 향상시킬 수 있어요.

렌더링의 우선순위를 정하려면, 다음 Hooks 중 하나를 사용하세요:

  • useTransition은 state 전환을 비차단(non-blocking)으로 표시하고, 다른 업데이트가 이를 중단할 수 있도록 해줘요.
  • useDeferredValue는 UI의 중요하지 않은 부분의 업데이트를 지연시키고, 다른 부분이 먼저 업데이트되도록 해줘요.

💡 부연 설명: useTransitionuseDeferredValue는 React 18에서 도입된 동시성(Concurrent) 기능이에요. 무거운 렌더링 작업이 있을 때 사용자 경험을 매끄럽게 유지하는 데 아주 유용해요. 예를 들어 검색어를 입력할 때 입력 자체는 즉시 반영하면서, 검색 결과 목록의 렌더링은 뒤로 미루는 식으로 활용할 수 있어요.


Other Hooks (기타 Hooks)

이 Hooks들은 주로 라이브러리 작성자에게 유용하고, 일반적인 애플리케이션 코드에서는 잘 사용되지 않아요.

  • useDebugValue는 React DevTools에서 여러분의 커스텀 Hook에 표시되는 라벨을 커스터마이즈할 수 있게 해줘요.
  • useId는 컴포넌트가 고유한 ID를 자기 자신과 연결할 수 있게 해줘요. 보통 접근성(accessibility) API와 함께 사용돼요.
  • useSyncExternalStore는 컴포넌트가 외부 스토어를 구독할 수 있게 해줘요.
  • useActionState는 액션의 state를 관리할 수 있게 해줘요.

나만의 Hooks (커스텀 Hooks)

JavaScript 함수로 나만의 커스텀 Hooks를 정의할 수도 있어요.

💡 부연 설명: 커스텀 Hook은 use로 시작하는 함수 이름을 가져야 해요 (예: useWindowSize, useFetch). 이렇게 하면 React가 해당 함수 안에서 Hook 규칙이 지켜지고 있는지 자동으로 검사할 수 있어요. 여러 컴포넌트에서 반복되는 로직이 있다면, 커스텀 Hook으로 추출해서 재사용하는 게 아주 좋은 패턴이에요!

profile
프론트에_가까운_풀스택_개발자

0개의 댓글