오늘 나는 커스텀 훅을 진정으로 이해했다 (그리고 직접 만들어봤다)

발행: (2026년 1월 10일 오후 09:43 GMT+9)
5 min read
원문: Dev.to

Source: Dev.to

Overview

오늘은 달랐습니다. 새로운 React 기능을 배운 것이 아니라, 코드 구조에 대한 사고 방식을 한 단계 끌어올렸기 때문이죠. 저는 단순히 컴포넌트를 작성한 것이 아니라, 직접 커스텀 훅을 만들기 시작했고, 그 순간 모든 것이 바뀌었습니다.

프로젝트를 진행하면서 다음과 같은 패턴을 발견했습니다:

  • 한 컴포넌트에 키보드 로직
  • 다른 컴포넌트에 LocalStorage 로직
  • 또 다른 곳에 영화‑조회 로직

useEffect가 여기저기서 많이 사용되고, 동일한 패턴이 반복되며, 모든 것이 UI에 강하게 결합돼 있었습니다. 그때 깨달았습니다. 이 로직은 UI에 속하지 않고 별도의 추상화에 들어가야 한다는 것을. 바로 그때 커스텀 훅을 진정으로 이해하게 되었습니다.

커스텀 훅은 동작을 UI와 분리하는 방법입니다. 이를 통해 다음을 할 수 있습니다:

  • 로직 재사용
  • 부수 효과 격리
  • 컴포넌트 단순화
  • 파일이 아니라 기능 단위로 사고

useKey — 키보드 동작 캡슐화

다음과 같은 훅을 만들었습니다:

  • 특정 키를 감지
  • 해당 키가 눌렸을 때 액션 실행
  • 자동으로 정리(cleanup) 수행

핵심 아이디어는 컴포넌트가 이벤트 리스너가 어떻게 동작하는지 알 필요가 없도록 하는 것입니다. 이제 컴포넌트는 비즈니스 로직처럼 읽히고, 배관 작업은 사라집니다.

useLocalStorage — 자동으로 지속되는 상태

이 훅을 통해 강력한 사실을 배웠습니다: 훅은 상태처럼 보이지만, 상태보다 더 똑똑할 수 있다는 점입니다.

훅의 흐름:

  1. localStorage에서 초기값을 읽음
  2. React 상태와 동기화 유지
  3. 변화가 있을 때마다 자동 저장

따라서 저장 로직을 곳곳에 작성할 필요 없이 “지속 가능한 상태를 주세요” 라고 선언하면 됩니다. 이는 큰 아키텍처적 업그레이드입니다.

useMovies — 모든 것이 맞물린 순간

이것이 진짜 전환점이었습니다. 다음 책임들을 하나의 훅으로 옮겼습니다:

  • 데이터 가져오기(fetch)
  • 로딩 상태 관리
  • 오류 처리
  • AbortController 사용
  • 데이터 정리
  • 비즈니스 규칙

이제 컴포넌트는 어떻게 데이터를 가져오는지, 어떻게 오류를 처리하는지, 어떻게 레이스 컨디션을 방지하는지 알 필요가 없습니다. 오직 “영화 목록, 로딩, 오류를 주세요” 라는 것만 알면 됩니다. 이런 명확한 관심사의 분리는 컴포넌트를 훨씬 간단하게 만들어 줍니다.

Takeaways

  • 커스텀 훅은 앱을 위한 자체 React API 입니다.
    useEffect, useState, fetch, addEventListener, localStorage 등을 반복해서 쓰는 대신 useMovies, useKey, useLocalStorage와 같은 훅을 작성합니다.
  • 사고 방식이 “어떻게 구현하지?” 에서 “이 동작을 위해 어떤 훅이 필요할까?” 로 바뀝니다.
  • Components = UI only
  • Hooks = behavior, side effects, logic
  • 로직이 재사용 가능하다고 느껴지면 → 훅을 만들어야 합니다.
  • 컴포넌트가 무겁게 느껴진다면 → 훅을 추출합니다.

오늘은 커스텀 훅을 이해한 것에 그치지 않았습니다. 새로운 사고 방식으로 구현하기 시작한 날이었습니다. 이제 컴포넌트는 작아졌고, 가장 중요한 것은 저는 이제 단순히 React를 사용하는 것이 아니라, 그 위에 직접 구축하고 있다는 점입니다.

Back to Blog

관련 글

더 보기 »

🚨 React 재렌더링 방법: 레퍼런스가 중요!

변형 메서드는 참조를 변경하지 않습니다. 이러한 메서드들은 메모리 내 동일한 배열/객체를 수정하므로 React 상태에 직접 사용하면 재렌더링이 트리거되지 않을 수 있습니다.