React Hooks 도입 후 Custom Hook으로 API 호출 로직 분리하기
배경
회사 프로젝트에서 React 16.8 업데이트와 함께 Hooks를 본격적으로 도입하기로 했다. 기존에는 API 호출을 위해 withApi 같은 HOC를 사용했는데, 여러 API를 동시에 호출해야 하는 경우 HOC가 중첩되면서 코드 가독성이 떨어지는 문제가 있었다.
기존 방식의 문제점
withAuth(withUserData(withNotifications(MyComponent)))
이런 식으로 wrapper hell이 발생했고, props drilling도 심각했다.
Custom Hook 구현
가장 먼저 만든 건 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(() => {
setLoading(true);
fetch(url)
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, [url]);
return { data, loading, error };
}
사용 예시
function UserProfile({ userId }) {
const { data: user, loading, error } = useFetch(`/api/users/${userId}`);
const { data: posts } = useFetch(`/api/users/${userId}/posts`);
if (loading) return <Spinner />;
if (error) return <Error message={error.message} />;
return (
<div>
<h1>{user.name}</h1>
<PostList posts={posts} />
</div>
);
}
HOC 지옥에서 벗어나 로직이 훨씬 명확해졌다.
개선점
현재 버전은 기본적인 구현이고, 다음 스프린트에서는 캐싱과 refetch 기능을 추가할 예정이다. 팀원들 반응도 긍정적이라 점진적으로 class component를 function component로 마이그레이션하기로 했다.