Dseok의 실전 예제로 웹개발 한방에 끝내기

웹개발, 혼자 하려니 막막하고 힘드시죠? 저 또한 그렇습니다. 힘든 웹개발... 실전 예제를 통해 함께 공부해요!!!!😁📕

React.js

[Dseok의 코딩스터디] React의 useEffect 한방에 끝내기 | 개념부터 실전 예제 10가지

Dseok 2025. 3. 4. 09:04
반응형
SMALL

리액트 코딩1

useEffect란?

 

React는 UI를 구축하기 위한 라이브러리로, 컴포넌트의 상태(state)와 속성(props)에 따라 화면을 렌더링합니다. 그러나 **데이터 가져오기, 수동으로 DOM을 조작하기, 구독 설정 등과 같은 부수 효과(side effects)**를 처리해야 할 때가 있습니다. 이러한 부수 효과를 관리하기 위해 React는 함수형 컴포넌트에서 useEffect Hook을 제공합니다.

 

useEffect컴포넌트가 렌더링될 때마다 특정 작업을 수행할 수 있도록 도와줍니다. 클래스형 컴포넌트의 생명주기 메서드인 componentDidMount, componentDidUpdate, componentWillUnmount를 대체하며, 함수형 컴포넌트에서도 이러한 생명주기 메서드의 기능을 구현할 수 있게 해줍니다.

 

useEffect의 기본 사용법

 

useEffect의 기본적인 사용법은 다음과 같습니다.

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    // 수행할 작업
    console.log('컴포넌트가 렌더링되었습니다.');

    // 정리 함수 반환 (선택 사항)
    return () => {
      console.log('컴포넌트가 언마운트됩니다.');
    };
  }, []); // 의존성 배열

  return <div>안녕하세요, 리액트!</div>;
}

위 코드에서 useEffect는 첫 번째 인자로 함수를 받습니다. 이 함수는 컴포넌트가 렌더링된 후 실행되며, 선택적으로 정리(clean-up) 함수를 반환할 수 있습니다. 두 번째 인자로는 의존성 배열(dependency array)을 받는데, 이 배열에 지정된 값이 변경될 때마다 useEffect가 다시 실행됩니다. 만약 빈 배열 []을 전달하면, 컴포넌트가 처음 마운트될 때만 실행되고 이후에는 실행되지 않습니다.

 

useEffect의 다양한 사용 패턴

 

useEffect는 의존성 배열의 구성에 따라 다양한 패턴으로 사용할 수 있습니다.

 

1. 마운트 시 한 번만 실행

useEffect(() => {
  // 컴포넌트가 마운트될 때 실행
  console.log('컴포넌트가 마운트되었습니다.');
}, []);

의존성 배열이 빈 배열인 경우, 컴포넌트가 처음 마운트될 때만 실행됩니다.

 

2. 특정 값이 변경될 때마다 실행

useEffect(() => {
  // 컴포넌트가 렌더링될 때마다 실행
  console.log('컴포넌트가 렌더링되었습니다.');
});

의존성 배열에 count를 넣으면, count 값이 변경될 때마다 useEffect가 실행됩니다.

 

3. 모든 렌더링마다 실행

useEffect(() => {
  // 컴포넌트가 렌더링될 때마다 실행
  console.log('컴포넌트가 렌더링되었습니다.');
});

의존성 배열을 생략하면, 컴포넌트가 렌더링될 때마다 useEffect가 실행됩니다.

 

4. 정리(clean-up) 함수 사용

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

  // 컴포넌트가 언마운트될 때 또는 의존성이 변경될 때 타이머 정리
  return () => {
    clearInterval(timer);
    console.log('타이머가 정리되었습니다.');
  };
}, []);

useEffect 내부에서 정리 함수를 반환하면, 컴포넌트가 언마운트되거나 의존성 값이 변경될 때 해당 함수가 실행되어 리소스를 정리합니다.

 

useEffect와 useState를 함께 사용한 실전 예제 10선

 

이제 useEffectuseState를 함께 사용하여 실제로 어떻게 활용할 수 있는지 10가지 예제를 살펴보겠습니다.

 

1. API 데이터 가져오기

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

function DataFetcher() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(result => setData(result))
      .catch(error => console.error('데이터 가져오기 오류:', error));
  }, []);

  return (
    <ul>
      {data.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}

설명:

useState를 사용하여 data라는 상태를 정의하고, 초기값을 빈 배열로 설정합니다.

useEffect는 컴포넌트가 마운트될 때 한 번 실행되어 API로부터 데이터를 가져옵니다.

데이터를 성공적으로 가져오면 setData를 통해 상태를 업데이트하고, 이를 리스트 형태로 렌더링합니다.

 

2. 윈도우 크기 감지

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

function WindowSize() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => {
      setWidth(window.innerWidth);
    };

    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  return <h1>현재 창 너비: {width}px</h1>;
}

설명

 

1) useState를 사용하여 width 상태를 정의

const [width, setWidth] = useState(window.innerWidth);

width현재 창의 너비를 저장하는 상태 변수입니다.

window.innerWidth를 초기값으로 설정하여 컴포넌트가 처음 렌더링될 때 현재 브라우저 창의 너비를 반영합니다.

 

2) useEffect를 활용하여 창 크기가 변경될 때 상태 업데이트

useEffect 내부에서 window.addEventListener('resize', handleResize);를 등록합니다.

handleResize 함수는 창 크기가 변경될 때마다 setWidth(window.innerWidth);를 호출하여 width 값을 최신 상태로 유지합니다.

 

3) 컴포넌트가 언마운트될 때 window.removeEventListener로 이벤트 리스너 제거

리소스 낭비를 방지하기 위해 useEffect에서 이벤트 리스너를 정리하는 클린업(clean-up) 함수를 사용합니다.

return () => { window.removeEventListener('resize', handleResize); }

이는 컴포넌트가 제거되거나 리렌더링될 때 불필요한 이벤트 리스너가 남아 있지 않도록 정리하는 역할을 합니다.

 

4) width 상태를 화면에 출력

return <h1>현재 창 너비: {width}px</h1>;

실시간으로 화면의 가로 크기를 보여주는 UI를 렌더링합니다.

 

3. 다크 모드 구현하기

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

function DarkModeToggle() {
  const [darkMode, setDarkMode] = useState(false);

  useEffect(() => {
    document.body.style.backgroundColor = darkMode ? 'black' : 'white';
    document.body.style.color = darkMode ? 'white' : 'black';
  }, [darkMode]);

  return (
    <button onClick={() => setDarkMode(!darkMode)}>
      {darkMode ? '라이트 모드' : '다크 모드'}
    </button>
  );
}

useEffect를 이용해 darkMode 상태가 변경될 때마다 배경색과 글자색을 변경하는 예제입니다.

 

4. 로컬 스토리지 활용 (로그인 상태 저장)

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

function LoginStatus() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  useEffect(() => {
    const storedStatus = localStorage.getItem('isLoggedIn');
    if (storedStatus === 'true') setIsLoggedIn(true);
  }, []);

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

  return (
    <div>
      <h1>{isLoggedIn ? '로그인됨' : '로그아웃됨'}</h1>
      <button onClick={() => setIsLoggedIn(!isLoggedIn)}>
        {isLoggedIn ? '로그아웃' : '로그인'}
      </button>
    </div>
  );
}

로컬 스토리지에 로그인 상태를 저장하여 페이지를 새로고침해도 상태가 유지됩니다.

 

5. 타이머 기능 만들기

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

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

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds((prev) => prev + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

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

useEffect를 이용해 타이머 기능을 구현하는 예제입니다.

 

6. 마우스 위치 추적하기

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

function MouseTracker() {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    const updatePosition = (e) => setPosition({ x: e.clientX, y: e.clientY });

    window.addEventListener('mousemove', updatePosition);

    return () => window.removeEventListener('mousemove', updatePosition);
  }, []);

  return <h1>마우스 위치: X: {position.x}, Y: {position.y}</h1>;
}

useEffect마우스 위치를 추적하여 실시간으로 화면에 표시합니다.

 

7. API 호출 및 데이터 로딩 상태 표시

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

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

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then((res) => res.json())
      .then((json) => {
        setData(json);
        setLoading(false);
      })
      .catch((err) => console.error(err));
  }, []);

  if (loading) return <h2>로딩 중...</h2>;

  return (
    <ul>
      {data.slice(0, 5).map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

useEffect에서 API 데이터를 불러올 때 로딩 상태를 추가하여 사용자 경험을 개선합니다.

 

8. 채팅 앱에서 실시간 메시지 수신

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

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

  useEffect(() => {
    const eventSource = new EventSource('https://example.com/chat');

    eventSource.onmessage = (event) => {
      setMessages((prev) => [...prev, JSON.parse(event.data)]);
    };

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

  return (
    <ul>
      {messages.map((msg, index) => (
        <li key={index}>{msg.text}</li>
      ))}
    </ul>
  );
}

실시간 채팅 데이터를 수신하는 예제로, EventSource를 사용하여 WebSocket과 유사한 방식으로 데이터를 받습니다.

 

9. 탭 닫기 방지 기능

import React, { useEffect } from 'react';

function PreventExit() {
  useEffect(() => {
    const handleBeforeUnload = (event) => {
      event.preventDefault();
      event.returnValue = '';
    };

    window.addEventListener('beforeunload', handleBeforeUnload);

    return () => window.removeEventListener('beforeunload', handleBeforeUnload);
  }, []);

  return <h1>이 페이지를 떠나면 데이터가 저장되지 않습니다.</h1>;
}

useEffect를 활용해 브라우저 탭을 닫으려 할 때 경고 메시지를 표시합니다.

 

10. 스크롤 감지하여 버튼 숨기기

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

function ScrollToTop() {
  const [showButton, setShowButton] = useState(false);

  useEffect(() => {
    const handleScroll = () => {
      if (window.scrollY > 200) setShowButton(true);
      else setShowButton(false);
    };

    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    <div>
      {showButton && <button onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}>위로 가기</button>}
    </div>
  );
}

useEffect스크롤 위치를 감지하여 버튼을 표시/숨김 처리합니다.

 

🎯 마무리 – useEffect 완벽 활용!

 

이제 useEffect의 개념과 다양한 실전 예제를 배웠습니다.

이 Hook을 활용하면 API 호출, 타이머, 이벤트 리스너, UI 상태 관리 등 다양한 기능을 쉽게 구현할 수 있습니다.

앞으로 React 프로젝트에서 적극 활용해보세요! 🚀

 

이 글이 도움이 되셨다면 좋아요 & 댓글 부탁드립니다! 😊

리액트 코딩2

반응형
LIST