반응형

1. 발생 이슈
기존 프로젝트에서는 컴포넌트 내에서 useEffect와 axios.get을 직접 사용하는 방식으로 데이터를 페칭했습니다. 하지만 프로젝트의 규모가 커지면서 다음과 같은 관리 효율성 저하 문제가 발생했습니다.
- 코드 중복: 모든 컴포넌트에서 인증 헤더(Token) 설정, 로딩/에러 상태 관리(useState)가 반복됨.
- 컴포넌트 비대화: UI 렌더링에 집중해야 할 컴포넌트 파일에 API 호출, 데이터 가공 등의 비즈니스 로직이 섞여 가독성이 떨어짐.
- 성능 문제: 동일한 데이터를 여러 곳에서 사용할 때 중복 호출이 발생하며, 클라이언트 측 캐싱이 전혀 이루어지지 않음.
2. 원인 분석
- 관심사 분리(SoC)의 부재: UI 레이어와 네트워크 레이어가 강하게 결합(Strong Coupling)되어 있어 하나를 수정하려면 다른 하나도 같이 수정해야 하는 의존성이 발생함.
- 명령형 데이터 페칭의 한계: useEffect는 데이터 페칭 시점과 상태 변경을 일일이 개발자가 제어해야 하므로, 네트워크 지연이나 에러 발생 시 예외 처리가 누락되기 쉬운 구조임.
3. 해결 방법
계층화된 아키텍처를 도입하여 선언적(Declarative) 데이터 페칭 구조로 리팩토링했습니다.
① Network Layer (Axios Instance)
axios.create를 활용해 기본 설정을 모듈화하고, 인터셉터를 통해 공통 로직을 처리했습니다.
JavaScript
// src/api/axiosInstance.js
const api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
headers: { 'Content-Type': 'application/json' }
});
api.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
② Service Layer (API Function)
엔드포인트별로 함수를 관리하여 API 스펙 변경 시 대응력을 높였습니다.
JavaScript
// src/api/userApi.js
export const fetchUserProfile = (userId) => api.get(`/users/${userId}`).then(res => res.data);
③ Data Access Layer (Custom Hooks & React Query)
TanStack Query를 도입하여 데이터 상태(Loading, Error, Caching)를 전역적으로 관리했습니다.
JavaScript
// src/hooks/useUser.js
export const useUser = (userId) => {
return useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUserProfile(userId),
});
};
4. 결과 및 배운점
결과
- 유지보수성 향상: API 주소나 공통 에러 처리를 한 곳(axiosInstance)에서 관리할 수 있게 됨.
- 선언적 UI 구현: 컴포넌트에서는 const { data, isLoading } = useUser() 한 줄로 데이터를 가져와 사용하게 되어 코드가 매우 간결해짐.
- 사용자 경험(UX) 개선: React Query의 캐싱 시스템을 통해 불필요한 네트워크 요청을 줄이고, 페이지 전환 시 부드러운 데이터 로딩 환경을 구축함.
배운점 (Key Takeaways)
- 추상화의 중요성: 단순히 코드를 줄이는 것이 아니라, "어떤 레이어가 어떤 역할을 할 것인가"를 명확히 하는 것이 팀 단위 프로젝트에서 얼마나 중요한지 깨달음.
- 라이브러리 도입의 근거: 단순히 유행하는 기술(React Query)을 쓰는 것이 아니라, 기존 useEffect 방식이 가진 한계를 명확히 인지하고 그 대안으로서 도구를 선택하는 사고 과정을 경험함.
- 비즈니스 로직의 독립: 컴포넌트는 오직 "어떻게 보여줄 것인가"에만 집중하고, 데이터가 "어디서 어떻게 오는지"는 신경 쓰지 않게 설계하는 것이 유연한 코드의 핵심임을 배움.
반응형
'TroubleShooting' 카테고리의 다른 글
| 외부 API 연동 시 세션(loginInfo) 초기화 현상 (1) | 2026.03.06 |
|---|---|
| 음성인식 모바일 호환성 트러블슈팅 (0) | 2026.03.06 |
| 사용자 이탈 방지 로직(뒤로가기/새로고침 차단) 최적화 (0) | 2026.01.14 |
| Jenkins-SonarQube 연동 에러: "The ‘report’ parameter is missing" (HTTP 400) (0) | 2026.01.06 |