본문 바로가기
개발/Frontend

useEffect, 정말 필요할까? 🤔 - React 개선 가이드

by 가치다움 2025. 2. 2.
반응형

안녕하세요! 오늘은 React에서 가장 많이 사용되는 Hook 중 하나인 useEffect의 올바른 사용법에 대해 이야기해보려고 합니다.

들어가며 📝

useEffect는 React의 강력한 기능이지만, 때로는 불필요하게 사용되어 성능 저하나 버그를 유발할 수 있습니다.
실제로 많은 개발자들이 컴포넌트의 로직을 useEffect에 넣는 것을 당연하게 생각하곤 하는데요, 과연 그럴까요?

useEffect가 필요하지 않은 실제 사례들 🚫

1. 폼 유효성 검사

// 🔴 불필요한 useEffect 사용
function SignupForm() {
  const [email, setEmail] = useState('');
  const [isValid, setIsValid] = useState(false);

  useEffect(() => {
    setIsValid(email.includes('@') && email.includes('.'));
  }, [email]);

  // ✅ 렌더링 중에 직접 계산
  const isValid = email.includes('@') && email.includes('.');
}

2. 계산된 스타일

// 🔴 불필요한 useEffect 사용
function ProductCard({ isOnSale, price }) {
  const [cardStyle, setCardStyle] = useState({});

  useEffect(() => {
    setCardStyle({
      backgroundColor: isOnSale ? '#ffebee' : 'white',
      color: price > 100 ? 'red' : 'black',
    });
  }, [isOnSale, price]);

  // ✅ 렌더링 중에 직접 계산
  const cardStyle = {
    backgroundColor: isOnSale ? '#ffebee' : 'white',
    color: price > 100 ? 'red' : 'black',
  };
}

3. Props 기반 필터링

// 🔴 불필요한 useEffect 사용
function ProductList({ products, category }) {
  const [filteredProducts, setFilteredProducts] = useState([]);

  useEffect(() => {
    setFilteredProducts(
      products.filter(product => 
        category === 'all' ? true : product.category === category
      )
    );
  }, [products, category]);

  // ✅ 렌더링 중에 직접 계산
  const filteredProducts = products.filter(product => 
    category === 'all' ? true : product.category === category
  );
}

4. 로컬 스토리지 동기화

// 🔴 불필요한 useEffect 사용
function UserSettings({ user }) {
  const [theme, setTheme] = useState('light');

  useEffect(() => {
    localStorage.setItem('theme', theme);
  }, [theme]);

  // ✅ 이벤트 핸들러에서 처리
  const handleThemeChange = (newTheme) => {
    setTheme(newTheme);
    localStorage.setItem('theme', newTheme);
  };
}

5. API 응답 후 상태 업데이트

// 🔴 불필요한 useEffect 사용
function OrderComplete({ orderId }) {
  const [orderStatus, setOrderStatus] = useState('');
  const [showConfetti, setShowConfetti] = useState(false);

  useEffect(() => {
    if (orderStatus === 'completed') {
      setShowConfetti(true);
    }
  }, [orderStatus]);

  // ✅ API 응답 핸들러에서 직접 처리
  const handleOrderComplete = async () => {
    const status = await checkOrderStatus(orderId);
    setOrderStatus(status);
    if (status === 'completed') {
      setShowConfetti(true);
    }
  };
}

실제 useEffect가 필요한 경우 ✅

  1. 외부 시스템과의 동기화
    • WebSocket 연결
    • 브라우저 API 구독
    • 애널리틱스 이벤트 발송
// ✅ 외부 시스템 연결에는 useEffect 사용이 적절
function ChatRoom() {
  useEffect(() => {
    const connection = createConnection();
    connection.connect();
    return () => connection.disconnect();
  }, []);
}
  1. 데이터 페칭(React Query를 추천합니다!)
// 🔴 useEffect를 사용한 데이터 페칭
function SearchResults({ query }) {
  const [results, setResults] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    let ignore = false;

    async function fetchData() {
      setIsLoading(true);
      try {
        const data = await fetchResults(query);
        if (!ignore) {
          setResults(data);
        }
      } catch (err) {
        if (!ignore) {
          setError(err);
        }
      } finally {
        setIsLoading(false);
      }
    }

    fetchData();
    return () => {
      ignore = true;
    };
  }, [query]);

  if (isLoading) return <div>로딩 중...</div>;
  if (error) return <div>에러 발생!</div>;

  return <div>{/* 결과 표시 */}</div>;
}

// ✅ React Query를 사용한 데이터 페칭
function SearchResults({ query }) {
  const { data, isLoading, error } = useQuery(
    ['search', query],
    () => fetchResults(query),
    {
      enabled: !!query,
    }
  );

  if (isLoading) return <div>로딩 중...</div>;
  if (error) return <div>에러 발생!</div>;

  return <div>{/* 결과 표시 */}</div>;
}

마무리 🎯

useEffect는 분명 유용한 도구이지만, 모든 문제의 해결책은 아닙니다. 다음을 기억하세요:

  1. 렌더링 중에 계산할 수 있는 것은 useEffect 대신 직접 계산하세요.
  2. 이벤트 핸들러에서 처리할 수 있는 로직은 useEffect 밖으로 빼세요.
  3. 실제로 외부 시스템과 동기화가 필요한 경우에만 useEffect를 사용하세요.
  4. 데이터 페칭은 React Query와 같은 전문화된 라이브러리를 사용하세요.

참고 문서 📚

You Might Not Need an Effect

반응형