Learning
레슨 4 / 9·20분

useEffect와 사이드 이펙트

useEffect란?

useEffect는 컴포넌트가 렌더링된 후 실행되는 사이드 이펙트(데이터 fetching, DOM 조작, 구독 등)를 처리하는 Hook입니다. 의존성 배열로 실행 시점을 제어합니다.

tsx
import { useState, useEffect } from 'react';

function Timer() {
  const [seconds, setSeconds] = useState(0);

  // 마운트 시 타이머 시작, 언마운트 시 정리
  useEffect(() => {
    const id = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);

    // 클린업 함수 — 컴포넌트 제거 시 실행
    return () => clearInterval(id);
  }, []); // 빈 배열 = 마운트 시 1회만 실행

  return <p>경과 시간: {seconds}초</p>;
}

의존성 배열

  • useEffect(fn) — 매 렌더링마다 실행 (거의 사용 안 함)
  • useEffect(fn, []) — 마운트 시 1회만 실행
  • useEffect(fn, [a, b]) — a 또는 b가 변경될 때 실행
tsx
function UserProfile({ userId }: { userId: string }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  // userId가 변경될 때마다 데이터 다시 가져오기
  useEffect(() => {
    setLoading(true);
    fetch("/api/users/" + userId)
      .then(res => res.json())
      .then(data => {
        setUser(data);
        setLoading(false);
      });
  }, [userId]); // userId 변경 시 재실행

  if (loading) return <p>로딩 중...</p>;
  if (!user) return <p>사용자를 찾을 수 없습니다.</p>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  );
}

클린업 함수

useEffect에서 반환하는 함수는 클린업(정리) 함수입니다. 이벤트 리스너 해제, 타이머 정리, 구독 취소 등에 사용됩니다. 컴포넌트가 언마운트되거나 의존성이 변경되기 전에 실행됩니다.

tsx
function WindowSize() {
  const [size, setSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    const handleResize = () => {
      setSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };

    window.addEventListener("resize", handleResize);

    // 클린업: 이벤트 리스너 제거
    return () => {
      window.removeEventListener("resize", handleResize);
    };
  }, []);

  return (
    <p>
      창 크기: {size.width} x {size.height}
    </p>
  );
}
💡

React 18의 Strict Mode에서는 개발 환경에서 useEffect가 두 번 실행됩니다. 이는 클린업 함수가 올바르게 작동하는지 검증하기 위한 의도적 동작이며, 프로덕션에서는 한 번만 실행됩니다.