본문 바로가기
Tech Notes

React Hook은 언제, 왜 사용하는가?

by miracle-tech 2025. 9. 11.
728x90
반응형
React Hook은 언제, 왜 사용하는가? - 개발자 가이드

🎣 React Hook 완전 정복

언제, 왜 사용하는지부터 실무 활용법까지 한 번에 마스터하기

🎯 React Hook이란?

💡 핵심 개념

React Hook = 공통 JavaScript 모듈 + React 상태 관리

함수형 컴포넌트에서 상태(state)와 생명주기(lifecycle) 기능을 사용할 수 있게 해주는 특별한 함수입니다.

기존에는 클래스 컴포넌트에서만 가능했던 상태 관리를 함수형 컴포넌트에서도 할 수 있게 되면서, React 개발이 훨씬 간단해졌습니다.

⏰ 언제 사용하는가?

👤 상태 관리가 필요할 때

  • 사용자 로그인 상태
  • 폼 입력값 관리
  • API 로딩 상태
  • 테마 설정 (다크/라이트)

🔄 로직 공유가 필요할 때

  • 여러 페이지에서 동일한 기능
  • 비슷한 상태 관리 로직 반복
  • 복잡한 비즈니스 로직 재사용

⚡ 사이드 이펙트 처리

  • API 호출
  • 타이머 설정
  • DOM 조작
  • 구독(subscription) 관리

💡 왜 사용하는가?

🔄

코드 재사용성

한 번 작성한 Hook을 여러 컴포넌트에서 재사용할 수 있어 개발 효율성이 크게 향상됩니다.

🎯

로직 분리

UI 로직과 비즈니스 로직을 깔끔하게 분리하여 코드의 가독성과 유지보수성을 높입니다.

🧪

테스트 용이성

Hook 단위로 독립적인 테스트가 가능하여 안정적인 코드 작성을 도와줍니다.

🤝

상태 공유

여러 컴포넌트가 동일한 상태를 효율적으로 공유할 수 있습니다.

✅ 장점

  • 함수형 컴포넌트에서 상태 관리 가능
  • 로직 재사용으로 개발 시간 단축
  • 클래스 컴포넌트보다 간결한 코드
  • 성능 최적화가 쉬움
  • 커뮤니티에서 다양한 커스텀 Hook 제공

⚠️ 주의사항

  • Hook 규칙을 반드시 지켜야 함
  • 처음에는 학습 곡선이 있음
  • 잘못 사용하면 무한 렌더링 발생 가능
  • 의존성 배열 관리가 중요

⚖️ 일반 JS 모듈과의 차이점

📦 일반 JavaScript 모듈

utils/loginHelper.js
export function checkLoginStatus() { // 매번 새로 API 호출 return fetch('/api/user/status'); } export function getUserInfo() { // 매번 새로 데이터 요청 return fetch('/api/user/info'); }

특징:

  • 🔴 단순히 함수들만 모아놓음
  • 🔴 상태(데이터)를 저장하지 않음
  • 🔴 매번 호출할 때마다 새로 실행
  • 🔴 메모리에 데이터를 유지하지 않음

🎣 React Hook

hooks/useAuth.js
export function useAuth() { const [user, setUser] = useState(null); // 상태 저장 const [loading, setLoading] = useState(true); // 로딩 상태 useEffect(() => { // 컴포넌트 마운트 시 한 번만 실행 checkLoginStatus(); }, []); const signOut = () => { setUser(null); // 로그아웃 로직 }; return { user, loading, signOut }; }

특징:

  • 🟢 함수 + 상태 관리 + React 생명주기
  • 🟢 여러 컴포넌트가 동일한 상태 공유
  • 🟢 상태를 메모리에 유지
  • 🟢 한 번 로그인하면 다른 페이지에서도 유지

🔧 실무 활용 예시

🔐 1. 인증 상태 관리 (useAuth)

가장 많이 사용되는 Hook 중 하나로, 로그인 상태를 전역적으로 관리합니다.

hooks/useAuth.js
function useAuth() { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); // 로그인 체크 const checkAuth = async () => { try { const response = await fetch('/api/me'); if (response.ok) { const userData = await response.json(); setUser(userData); } } catch (error) { console.error('인증 확인 실패:', error); } finally { setIsLoading(false); } }; useEffect(() => { checkAuth(); }, []); const signOut = async () => { await fetch('/api/logout', { method: 'POST' }); setUser(null); }; return { user, isLoading, signOut, isAuthenticated: !!user }; } // 사용 예시 function Header() { const { user, isLoading, signOut, isAuthenticated } = useAuth(); if (isLoading) return
로딩중...
; return (
{isAuthenticated ? (
안녕하세요, {user.name}님!
) : ( 로그인 )}
); }

📡 2. API 데이터 가져오기 (useFetch)

API 호출과 관련된 로딩, 에러, 데이터 상태를 한번에 관리합니다.

hooks/useFetch.js
function useFetch(url, options = {}) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { setLoading(true); setError(null); const response = await fetch(url, options); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); setData(result); } catch (err) { setError(err.message); } finally { setLoading(false); } }; if (url) { fetchData(); } }, [url]); const refetch = () => { if (url) { fetchData(); } }; return { data, loading, error, refetch }; } // 사용 예시 function UserList() { const { data: users, loading, error, refetch } = useFetch('/api/users'); if (loading) return
사용자 목록 로딩중...
; if (error) return
오류: {error}
; return (
    {users?.map(user => (
  • {user.name}
  • ))}
); }

💾 3. 로컬 스토리지 관리 (useLocalStorage)

브라우저 로컬 스토리지와 React 상태를 동기화합니다.

hooks/useLocalStorage.js
function useLocalStorage(key, initialValue) { // 초기값 설정 const [storedValue, setStoredValue] = useState(() => { try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (error) { console.error('로컬 스토리지 읽기 실패:', error); return initialValue; } }); // 값 저장 함수 const setValue = (value) => { try { // 함수가 전달된 경우 실행 const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); window.localStorage.setItem(key, JSON.stringify(valueToStore)); } catch (error) { console.error('로컬 스토리지 저장 실패:', error); } }; return [storedValue, setValue]; } // 사용 예시 function Settings() { const [theme, setTheme] = useLocalStorage('theme', 'light'); const [language, setLanguage] = useLocalStorage('language', 'ko'); return (

설정

); }

✨ 베스트 프랙티스

📋

Hook 규칙 준수

  • 최상위 레벨에서만 호출
  • 조건문, 반복문 내부에서 호출 금지
  • React 함수에서만 사용
🎯

의존성 배열 관리

  • useEffect의 의존성 배열 정확히 명시
  • 불필요한 리렌더링 방지
  • ESLint 플러그인 활용
🔧

커스텀 Hook 네이밍

  • 반드시 'use'로 시작
  • 명확하고 설명적인 이름 사용
  • 기능을 잘 표현하는 이름 선택

성능 최적화

  • useMemo, useCallback 적절히 활용
  • 불필요한 상태 업데이트 피하기
  • 메모리 누수 방지

🎉 결론

🎯 핵심 정리

React Hook은 상태를 가지고 있으면서 재사용 가능한 로직이 필요할 때 사용합니다.

✅ Hook 사용 권장

  • 상태 관리가 필요한 로직
  • 컴포넌트 간 상태 공유
  • 사이드 이펙트 처리
  • 복잡한 비즈니스 로직

📦 일반 JS 모듈 사용

  • 단순 유틸리티 함수
  • 상태가 없는 계산 로직
  • 데이터 변환 함수
  • 상수 값들

🚀 올바른 Hook 사용으로 더욱 깔끔하고 유지보수하기 쉬운 React 애플리케이션을 개발해보세요!

728x90