React Hooks 도입 후 Custom Hook으로 API 호출 로직 정리하기
배경
프로젝트에 React Hooks를 본격적으로 도입하기로 했다. 기존 클래스 컴포넌트에서 componentDidMount마다 반복되던 API 호출 패턴이 있었는데, 이를 Custom Hook으로 추상화하면 코드 재사용성이 높아질 것 같았다.
기존 패턴의 문제점
각 컴포넌트마다 loading, error, data 상태를 선언하고, try-catch로 에러 처리하는 보일러플레이트가 반복됐다. 컴포넌트가 늘어날수록 유지보수 부담이 커졌다.
useFetch Hook 구현
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let isMounted = true;
fetch(url)
.then(res => res.json())
.then(data => {
if (isMounted) {
setData(data);
setLoading(false);
}
})
.catch(err => {
if (isMounted) {
setError(err);
setLoading(false);
}
});
return () => {
isMounted = false;
};
}, [url]);
return { data, loading, error };
}
사용 예시
function UserList() {
const { data, loading, error } = useFetch('/api/users');
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
개선 효과
코드량이 30% 정도 줄었고, API 호출 로직이 한곳에 모여 있어 에러 처리 방식을 변경할 때도 Hook만 수정하면 됐다. cleanup 함수로 언마운트 시 메모리 누수도 방지했다.
남은 과제
POST 요청이나 인증 토큰 처리는 아직 각 컴포넌트에서 직접 하고 있다. 이 부분도 Hook으로 추상화할 방법을 고민 중이다.