리액트 강좌: useEffect에 대한 모든 것

리액트는 현대 웹 애플리케이션을 구축하기 위한 가장 인기 있는 JavaScript 라이브러리 중 하나입니다. 그중에서도 useEffect 훅은 컴포넌트의 생명 주기를 제어하고, 사이드 이펙트를 관리하는 데 매우 중요한 역할을 합니다. 이 글에서는 useEffect의 기본 개념, 사용법, 다양한 사례를 상세히 다루겠습니다.

1. useEffect란 무엇인가?

useEffect는 React 라이브러리에서 제공하는 훅 중 하나로, 함수형 컴포넌트에서 사이드 이펙트를 발생시키기 위해 사용됩니다. 사이드 이펙트란 데이터 가져오기, 수동 DOM 조작, 타이머 설정 또는 다른 외부 시스템과의 상호작용 등을 포함합니다.

리액트의 컴포넌트는 상태(state)와 속성(props)만을 작성하도록 설계되었지만, 때때로 컴포넌트가 렌더링될 때 다른 작업을 수행해야 할 필요가 있습니다. 이러한 작업을 수행하기 위해 useEffect 훅을 사용합니다.

2. useEffect의 기본 사용법

useEffect는 다음과 같은 구문으로 사용할 수 있습니다:

useEffect(() => {
  // 사이드 이펙트 코드
}, [의존성 배열]);

위 구문에서 첫 번째 매개변수는 사이드 이펙트를 수행하는 함수이며, 두 번째 매개변수는 의존성 배열입니다. 의존성 배열에는 해당 훅이 의존하는 상태나 props가 들어갑니다.

2.1. 간단한 예제

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

function ExampleComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = \`Count: \${count}\`;
  }, [count]);

  return (
    

현재 카운트: {count}

); }

위 예제에서는 count가 변경될 때마다 문서 제목이 업데이트됩니다. count가 의존성 배열에 포함되어 있기 때문에, setCount 함수가 호출되어 count가 업데이트될 경우에만 사이드 이펙트가 실행됩니다.

3. useEffect의 실행 타이밍

useEffect는 컴포넌트가 렌더링된 후에 실행됩니다. 정리하자면 다음과 같습니다:

  • 컴포넌트가 처음 렌더링될 때 유효성 검사 후 실행
  • 의존성 배열에 명시된 값이 변경될 때 다시 실행

예를 들어, 의존성 배열이 비어 있는 경우:

useEffect(() => {
  // 최초 렌더링 후에만 실행
}, []);

3.1. 클린업 함수

useEffect는 클린업 함수를 반환할 수 있습니다. 이 클린업 함수는 컴포넌트가 언마운트될 때 또는 다음 효과가 실행되기 전에 호출됩니다. 이는 메모리 누수를 방지하는 데 매우 유용합니다.

useEffect(() => {
  const timer = setTimeout(() => {
    console.log('타이머 실행!');
  }, 1000);

  return () => {
    clearTimeout(timer); // 컴포넌트 언마운트 시 타이머 클리어
  };
}, []);

4. useEffect에 대한 고급 사용법

이제 기본 사용법을 익혔으니, useEffect의 고급 개념으로 넘어가 보겠습니다. 개체 관리를 위한 세부 매개변수 전달, 조건부 실행 등의 방법을 알아보겠습니다.

4.1. 조건부 실행

때때로 특정 조건이 충족될 때만 useEffect를 실행하고 싶을 수 있습니다. 조건문을 사용해 이를 구현할 수 있습니다:

useEffect(() => {
  if (count > 0) {
    console.log('Count is positive');
  }
}, [count]);

4.2. 여러 개의 useEffect 사용하기

하나의 컴포넌트에서 여러 개의 useEffect를 사용하여 각 효과를 독립적으로 관리할 수 있습니다. 각 효과는 자체 의존성 배열을 가질 수 있습니다.

useEffect(() => {
  // 데이터 가져오기
}, [url]);

useEffect(() => {
  // 클리어 타이머
  return () => {
    clearInterval(timerId);
  };
}, []);

5. useEffect 사례 연구

이제 실제 사용 사례를 통해 useEffect의 유용성을 살펴보겠습니다.

5.1. API 데이터 fetching

리액트 애플리케이션에서 API 데이터를 fetching하는 가장 일반적인 경우에서 useEffect를 사용합니다:

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

function DataFetchingComponent() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then((response) => response.json())
      .then((data) => {
        setData(data);
        setLoading(false);
      });
  }, []);

  if (loading) return 

로딩 중...

; return (
    {data.map(item =>
  • {item.name}
  • )}
); }

5.2. 실시간 데이터 업데이트

WebSocket이나 서버 전송 이벤트(SSE)를 통해 실시간 데이터를 업데이트할 때 useEffect를 사용할 수 있습니다:

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

function RealTimeComponent() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = new WebSocket('ws://your-websocket-url');

    socket.onmessage = (event) => {
      const newMessage = JSON.parse(event.data);
      setMessages(prevMessages => [...prevMessages, newMessage]);
    };

    return () => {
      socket.close();
    };
  }, []);

  return (
    
{messages.map((msg, index) => (
{msg.content}
))}
); }

6. useEffect vs 클래스 컴포넌트의 생명주기 메소드

함수형 컴포넌트의 useEffect는 클래스 컴포넌트에서 사용하는 생명주기 메소드(componentDidMount, componentDidUpdate, componentWillUnmount)의 역할을 수행합니다.

예를 들어, componentDidMountcomponentWillUnmount를 구현할 수 있는 useEffect의 사용은 다음과 같습니다:

useEffect(() => {
  // 컴포넌트가 마운트될 때 실행
  fetchData();

  return () => {
    // 컴포넌트가 언마운트될 때 실행
    cleanup();
  };
}, []);

7. 최적화 및 성능 고려 사항

useEffect를 사용할 때는 성능에 미치는 영향을 고려해야 합니다. 다음은 성능을 최적화하기 위한 몇 가지 팁입니다:

  • 의존성 배열을 올바르게 설정하세요. 불필요한 재렌더링을 방지할 수 있습니다.
  • 예를 들어, 특정 상태가 변경될 때만 효과를 실행해야 한다면 이를 명확히 하십시오.
  • 지속하는 메모리 리소스를 해제하기 위해 클린업 함수를 적절히 사용하십시오.

8. 자주 묻는 질문(FAQ)

8.1. useEffect는 언제 호출되나요?

useEffect는 컴포넌트가 마운트되거나 의존성이 업데이트될 때 호출됩니다.

8.2. useEffect를 여러 번 사용할 수 있나요?

네, 한 컴포넌트에서 여러 개의 useEffect를 사용할 수 있습니다. 각 useEffect는 독립적이며, 다른 역활을 수행할 수 있습니다.

8.3. useEffect의 의존성 배열을 비워두면 어떻게 되나요?

의존성 배열을 빈 배열로 설정하면, 컴포넌트가 처음 마운트될 때만 실행되고 이후에는 실행되지 않습니다.

8.4. useEffect 내부에서 setState를 호출해도 괜찮나요?

예, 상태를 업데이트하기 위해 setState를 호출할 수 있으며, 이로 인해 컴포넌트가 재렌더링됩니다. 다만, 무한 루프를 피하기 위해 적절히 의존성을 관리해 주세요.

9. 마치며

이번 강좌에서는 리액트의 useEffect 훅에 대해 자세히 알아보았습니다. useEffect는 사이드 이펙트를 관리하는 데 필수적인 도구로, 리액트 애플리케이션에서 흔히 사용됩니다. 처음에는 어렵게 느껴질 수 있지만, 계속해서 사용하다 보면 자연스럽게 익숙해질 것입니다.

이 글을 통해 useEffect의 강력한 기능과 활용 방법에 대해 이해하고, 자신의 프로젝트에 실제로 적용해 보시길 바랍니다. 앞서 언급한 예제와 같은 다양한 사용 사례를 실습하면서 추가적인 경험을 쌓아보세요!