훅의 핵심 API들이 자리를 잡자, 리액트 팀 내부에서는 이를 활용한 ‘커스텀 훅’을 만들어보는 문화가 자연스럽게 퍼져나갔다. 그것은 새로운 패러다임의 힘을 체감하고, 더 나은 패턴을 탐구하기 위한 일종의 놀이와도 같았다.
어느 날 팀 회의에서, 한 개발자가 푸념 섞인 목소리로 말했다.
“UI를 만들다 보면, true와 false 상태를 서로 전환하는 로직이 정말 자주 나오는 것 같아요. 모달을 열고 닫거나, 아코디언 메뉴를 펼치고 접거나 할 때요. 매번 useState를 선언하고, setIsOpen(prev => !prev) 같은 코드를 반복해서 작성하는 게 조금 번거롭네요.”
그의 말에 모두가 공감했다.
이것은 아주 작지만, 분명히 반복되는 패턴이었다.
그 순간, 댄이 자신의 노트북을 열고 즉석에서 코드를 작성하기 시작했다. 그는 이 작은 불편함을 해결하는, 가장 단순한 형태의 커스텀 훅을 만들어보기로 했다.
그는 useToggle이라는 이름의 새로운 함수를 정의했다.
import { useState, useCallback } from 'react';
// 'useToggle' 커스텀 훅 정의
function useToggle(initialValue = false) {
// 1. 내부적으로 useState를 사용하여 on/off 상태를 관리한다.
const [isOn, setIsOn] = useState(initialValue);
// 2. 상태를 전환하는 함수 'toggle'을 만든다.
// useCallback으로 감싸서, 함수가 불필요하게 재생성되는 것을 방지한다.
const toggle = useCallback(() => {
setIsOn(prevIsOn => !prevIsOn);
}, []);
// 3. 현재 상태 값과, 상태를 전환하는 함수를 배열로 반환한다.
return [isOn, toggle];
}
코드의 구조는 놀랍도록 명료했다.
useToggle 훅은 내부적으로 useState를 사용하여 참/거짓 상태를 관리했다. 그리고 그 상태를 안전하게 전환하는 toggle 함수를 useCallback으로 메모이제이션하여 함께 제공했다. 반환 값의 형태는 useState와 유사하게, [값, 업데이트_함수] 형태의 배열로 맞추어 일관성을 유지했다.
이제 이 useToggle 훅을 사용하는 컴포넌트의 코드는 극적으로 간결해졌다.
function ModalExample() {
// useToggle 훅을 호출하여, 모달의 열림 상태와 토글 함수를 가져온다.
const [isModalOpen, toggleModal] = useToggle(false);
return (
<div>
<button onClick={toggleModal}>
{isModalOpen ? 'Close Modal' : 'Open Modal'}
</button>
{isModalOpen && (
<div className="modal">
<h2>Modal Content</h2>
<button onClick={toggleModal}>Close</button>
</div>
)}
</div>
);
}
더 이상 컴포넌트 내부에 useState(false)나 setIsOpen(p => !p) 같은 코드를 직접 작성할 필요가 없었다. 토글과 관련된 모든 상태 로직은 useToggle이라는 의미 있는 이름의 함수 안에 완벽하게 캡슐화되었다.
회의실의 팀원들은 이 작은 커스텀 훅이 가진 힘에 감탄했다.
“대단하네요. 이제 토글 기능이 필요한 어떤 컴포넌트에서든 저 useToggle 한 줄만 쓰면 되는군요.”
useToggle은 커스텀 훅의 가장 기본적인 형태이자, 그 철학을 완벽하게 보여주는 예시였다.
‘반복되는 상태 로직을, 의미 있는 이름의 함수로 추출하여 재사용한다.’
이 작은 성공은 팀에게 더 큰 영감을 주었다.
그들은 useToggle처럼 작고 범용적인 훅뿐만 아니라, 특정 도메인(예: 폼 입력, 데이터 통신)의 복잡한 문제를 해결하는, 더 실용적이고 강력한 커스텀 훅을 만들어 볼 수 있다는 자신감을 얻었다.
커스텀 훅은 더 이상 추상적인 개념이 아니었다.
그것은 개발자들의 일상적인 불편함을 해결하고, 코드의 품질을 높여주는 구체적이고 실용적인 도구임이 증명되었다.
팀의 다음 목표는, 웹 개발에서 가장 흔하고도 골치 아픈 문제 중 하나인 ‘폼 입력 처리’를 위한 커스텀 훅을 만들어보는 것이었다.


