리액트/기초

💡 useEffect 실무 활용 예시

lamarcK 2025. 4. 7. 22:56

useEffect는 다양한 상황에서 활용되지만, 실무에서 특히 자주 사용되는 대표적인 예시 몇 가지를 소개한다.


1. 📊 컴포넌트 마운트 시 초기 데이터 로딩

  • 상황: 페이지나 특정 컴포넌트가 처음 화면에 나타날 때, 서버로부터 필요한 초기 데이터 목록(예: 상품 목록, 게시글 목록, 초기 설정값 등)을 가져와야 하는 경우.
  • 구현:
    • useEffect의 콜백 함수 내에서 데이터 요청 함수(API 호출)를 실행한다.
    • **의존성 배열은 빈 배열([])**로 설정하여, 컴포넌트가 최초 렌더링(마운트) 될 때 한 번만 실행되도록 한다.
    • 가져온 데이터는 useState를 사용하여 상태에 저장하고 화면에 표시한다.
  • 예시 개념:
    JavaScript
     
    const [items, setItems] = useState([]);
    const [isLoading, setIsLoading] = useState(true);
    
    useEffect(() => {
      // 데이터 가져오는 비동기 함수 (async/await 사용 예시)
      const fetchItems = async () => {
        setIsLoading(true); // 로딩 시작
        try {
          const response = await fetch('/api/items'); // API 호출
          const data = await response.json();
          setItems(data); // 상태 업데이트
        } catch (error) {
          console.error("데이터 로딩 실패:", error);
          // 에러 처리 로직
        } finally {
          setIsLoading(false); // 로딩 종료
        }
      };
    
      fetchItems(); // 함수 실행
    
    }, []); // 빈 배열: 마운트 시 1회만 실행
    
  • 목적: 컴포넌트가 준비되는 시점에 필요한 데이터를 효율적으로 불러온다.

2. 👤 특정 값 변경 시 데이터 다시 로딩

  • 상황: 사용자의 프로필 페이지처럼, 특정 ID 값(props로 전달받거나 URL 파라미터에서 가져온 값)에 따라 다른 데이터를 서버에서 가져와 보여줘야 하는 경우.
  • 구현:
    • useEffect의 콜백 함수 내에서 해당 ID를 인자로 사용하여 데이터 요청 함수를 호출한다.
    • 의존성 배열에 해당 ID 값 ([userId])을 넣어준다. 이렇게 하면 userId 값이 변경될 때마다 이펙트 함수가 다시 실행되어 새로운 사용자의 데이터를 불러온다.
    • ID 값이 유효할 때만 API를 호출하도록 조건문을 추가하는 것이 좋다.
  • 예시 개념:
    JavaScript
     
    const [userData, setUserData] = useState(null);
    const { userId } = useParams(); // URL 파라미터에서 userId 가져오기 (react-router-dom 예시)
    
    useEffect(() => {
      const fetchUserData = async (id) => {
        if (!id) return; // userId가 없으면 실행 중단
        // 로딩 상태 관리 추가...
        try {
          const response = await fetch(`/api/users/${id}`);
          const data = await response.json();
          setUserData(data);
        } catch (error) {
          console.error("사용자 데이터 로딩 실패:", error);
        }
      };
    
      fetchUserData(userId); // 함수 실행
    
    }, [userId]); // userId가 변경될 때마다 이펙트 재실행
    
  • 목적: 동적인 값(ID, 검색어 등)의 변경에 반응하여 관련된 데이터를 업데이트한다.

3. 🖥️ 브라우저 API 연동 (예: 이벤트 리스너)

  • 상황: window 객체의 resize(창 크기 변경)나 scroll(스크롤 위치 변경) 이벤트를 감지하여 특정 동작(예: 레이아웃 변경, 스크롤 위치에 따른 효과 적용)을 수행해야 하는 경우.
  • 구현:
    • useEffect의 콜백 함수 내에서 window.addEventListener를 사용하여 이벤트 리스너를 등록한다.
    • **의존성 배열은 빈 배열([])**로 설정하여 마운트 시 한 번만 등록한다.
    • 정리(cleanup) 함수를 반드시 반환하여, 컴포넌트가 언마운트될 때 window.removeEventListener를 통해 등록했던 리스너를 제거해준다. (메모리 누수 방지)
  • 예시 개념:
    JavaScript
     
    const [windowWidth, setWindowWidth] = useState(window.innerWidth);
    
    useEffect(() => {
      const handleResize = () => {
        setWindowWidth(window.innerWidth); // 창 너비 상태 업데이트
      };
    
      window.addEventListener('resize', handleResize); // 리스너 등록
    
      // 정리 함수: 컴포넌트 언마운트 시 리스너 제거
      return () => {
        window.removeEventListener('resize', handleResize);
      };
    }, []); // 빈 배열: 마운트 시 1회만 등록, 언마운트 시 1회만 제거
    
  • 목적: 리액트 외부 환경(브라우저 API)과 상호작용하고, 컴포넌트 생명주기에 맞춰 리소스를 안전하게 관리한다.

4. ⏰ 타이머 설정 및 해제

  • 상황: 일정 시간 간격으로 특정 작업을 수행(예: 데이터 폴링, 슬라이드 쇼 자동 넘김)하거나, 일정 시간 후에 특정 동작을 수행(예: 알림 메시지 자동 닫기)해야 하는 경우.
  • 구현:
    • useEffect의 콜백 함수 내에서 setInterval이나 setTimeout을 사용하여 타이머를 설정한다.
    • 의존성 배열은 타이머를 언제 재시작할지에 따라 설정한다 (보통 []로 한 번만 실행).
    • 정리(cleanup) 함수에서 clearInterval이나 clearTimeout을 호출하여, 컴포넌트 언마운트 시 타이머를 반드시 해제한다.
  • 예시 개념: (1초마다 카운트 증가)
    JavaScript
     
    const [count, setCount] = useState(0);
    
    useEffect(() => {
      const intervalId = setInterval(() => {
        setCount(prevCount => prevCount + 1); // 이전 상태 기반 업데이트 권장
      }, 1000); // 1초 간격
    
      // 정리 함수: 언마운트 시 인터벌 해제
      return () => {
        clearInterval(intervalId);
      };
    }, []); // 빈 배열: 마운트 시 1회만 인터벌 설정
    
  • 목적: 시간 기반의 작업을 컴포넌트 생명주기와 동기화하여 관리한다.

이 외에도 useEffect는 외부 라이브러리 연동, 로컬 스토리지 접근 등 다양한 사이드 이펙트를 처리하는 데 필수적으로 사용되는 강력한 도구다. 중요한 것은 의존성 배열을 올바르게 설정하고, 필요한 경우 정리 함수를 통해 리소스를 관리하는 것이다.

소스 및 관련 콘텐츠