커스텀 훅과 제네릭으로 재사용 가능한 로직 만들기
웹 애플리케이션을 개발하다 보면 여러 컴포넌트에서 동일한 로직이 반복되는 상황을 자주 마주한다. 예를 들어 데이터를 불러오거나, 폼 입력값을 관리하거나, 화면 크기를 감지하는 기능들은 서비스 곳곳에서 쓰이기 마련이다. 이때 매번 같은 코드를 복사해서 붙여넣는다면 코드의 양이 방대해질 뿐만 아니라, 버그가 발생했을 때 수정해야 할 곳도 기하급수적으로 늘어난다. 이러한 문제를 해결하기 위해 등장한 개념이 바로 React 커스텀 훅이다.
React 커스텀 훅을 활용하면 복잡한 상태 관리와 부수 효과(Side Effect) 로직을 한데 모아 깔끔하게 독립시킬 수 있다. 이렇게 분리된 로직은 마치 레고 블록처럼 필요한 곳에 언제든 끼워 넣을 수 있는 강력한 재사용성을 가진다. 단순히 코드를 줄이는 것을 넘어 가독성과 유지보수 편의성까지 극대화할 수 있는 커스텀 훅의 개념과 이를 더 강력하게 만들어줄 최적화 및 확장법을 살펴보자.
중복된 로직을 깔끔하게 정리하는 React 커스텀 훅
React에서 커스텀 훅은 이름이 'use'로 시작하는 자바스크립트 함수에 불과하다. 하지만 내부에 useState나 useEffect 같은 React의 기본 훅을 포함할 수 있다는 강력한 차별점을 지닌다. 기존에는 컴포넌트 내부에 복잡하게 얽혀 있던 상태 변경 로직들을 이 특수한 함수 안으로 완전히 격리할 수 있는 것이다.
예를 들어 마우스 커서의 현재 위치를 추적하는 기능이 필요하다고 가정해보자. 컴포넌트 내부에서 상태를 만들고 이벤트 리스너를 등록하고 지우는 과정을 직접 작성하면 코드가 매우 지저분해진다. 하지만 이 과정을 하나의 독립된 함수로 분리하여 훅으로 만들면, 다른 컴포넌트에서는 단 한 줄의 함수 호출만으로 마우스 위치 데이터를 실시간으로 가져와 사용할 수 있게 된다. 마치 복잡한 주방 기구를 매번 새로 조립하는 대신 잘 만들어진 전동 믹서기를 가져다 쓰는 것과 같다.
useCallback과 useMemo로 성능 최적화 더하기
커스텀 훅을 설계할 때 흔히 놓치는 부분 중 하나가 바로 성능 최적화다. 컴포넌트가 렌더링될 때마다 커스텀 훅 내부의 상태와 함수들도 매번 새로 생성되기 때문이다. 만약 커스텀 훅이 반환하는 함수를 자식 컴포넌트의 props로 전달하고 있다면, 아무런 변화가 없음에도 자식 컴포넌트까지 불필요하게 리렌더링되는 성능 저하 현상이 발생할 수 있다.
이러한 비효율을 방지하기 위해 사용하는 치트키가 바로 useCallback과 useMemo다. useCallback은 훅 내부에서 정의된 함수를 메모리에 저장해두고 동일한 함수 인스턴스를 재사용할 수 있게 도와준다. 또한 useMemo를 사용하면 복잡한 연산 결과를 캐싱하여 렌더링 성능을 보존할 수 있다. 이 두 가지 도구를 적절히 결합하면 커스텀 훅은 단순한 로직 재사용을 넘어, 고성능 애플리케이션을 지탱하는 단단한 기초가 된다.
제네릭 훅으로 유연성과 안정성 극대화하기
커스텀 훅의 진정한 강점은 데이터의 형태에 구애받지 않는 범용성에 있다. 특정 API나 고정된 데이터 구조에만 종속된 훅은 다른 페이지나 기능에서 재사용하기 어렵다. 이때 타입스크립트의 제네릭(Generic) 개념을 접목한 제네릭 훅을 작성하면 강력한 유연성과 안정성을 동시에 확보할 수 있다.
제네릭 훅은 쉽게 말해 '타입을 매개변수처럼 전달받는 훅'이다. 예컨대 서버에서 데이터를 패칭하는 훅을 만들 때 반환 데이터 타입을 제네릭으로 열어두면, 사용자 정보를 가져올 때도, 상품 목록을 가져올 때도 동일한 훅 하나로 완벽하게 대응할 수 있다. 각 컴포넌트에서는 정확히 원하는 데이터 타입으로 자동 추론되어 자동 완성과 컴파일 시점의 타입 검사 혜택을 온전히 누리게 된다. 이는 안전한 상자에 어떤 물건이든 맞춰 넣을 수 있도록 가변형 틀을 제공하는 것과 유사하다.
결과적으로 React 커스텀 훅에 메모이제이션 최적화를 적용하고 제네릭을 얹는 과정은 코드의 생산성을 몇 단계 위로 끌어올리는 지름길이다. 불필요한 반복 코드가 사라지고 안전하게 제어되는 화면은 개발자 경험과 사용자 경험 모두를 만족시키는 훌륭한 결과물로 이어진다. 지금 작성하고 있는 컴포넌트 코드 중 중복되거나 비대해진 로직이 있다면 이를 훅으로 분리하는 리팩터링을 시작해보길 권장한다.