React Component 생명 주기 함수 (useEffect)

이상호·2025년 4월 10일

컴포넌트의 생명 주기부터 알아보자

생명주기(Life Cycle)

React 컴포넌트는 태어나서(생성), 살아가고(렌더링), 죽는(소멸) 과정을 거치는데, 이걸 생명주기라고 부른다. Mounting(탄생), Updating(삶), Unmounting(죽음) 세 단계로 나뉜다.

  1. Mounting : 컴포넌트가 처음 화면에 렌더링되는 순간이다.
  • 이때 컴포넌트는 필요한 설정을 하고, 데이터를 불러오는 등 초기작업을 수행한다.
  1. Updating : 컴포넌트가 화면에 렌더링된 후 데이터가 변경되거나, 사용자와의 상호작용이 발생할 때 마다 컴포넌트가 업데이트되는 과정이다.
  • 사용자가 버튼을 클릭하거나. 새로운 데이터가 들어오면 컴포넌트는 발생한 이벤트에 따라 컴포넌트를 업데이트한다.
  1. Unmountiong : 컴포넌트가 화면에서 사라지는 순간이다.
  • 컴포넌트가 사라지기 전 필요한 정리작업을 수행할 수 있다.

  • class component

  • 함수 component

클래스 컴포넌트에서는 componentDidMount, componentDidUpdate, componentWillUnmount 같은 생명주기 메서드를 사용할 수 있고, 함수 컴포넌트에서는 useEffect Hook을 사용하여 비슷한 작업을 수행할 수 있다.


useEffect()

class Component의 생명 주기 메서드는 생략하고 useEffect hook에 대해서 알아보자

useEffect()가 무엇이냐?

useEffect()는 React한테 "야, 이 컴포넌트 렌더링될 때마다(혹은 조건 따라) 내가 시키는 특별한 작업 좀 해!" 라고 하는 Hook이다. 컴포넌트 화면에 나오고 나서 "이제 뭐 하지?" 하면, useEffect가 "이거 해!" 하는 거다.

쉽게 말하면, useEffect는 화면에 보이는 거 말고, 컴포넌트 생명 주기에 맞춰 해야 하는 부수 효과(side effects) 처리하는 담당자다. 데이터 가져오기, 타이머 설정, 외부 API 호출 같은 거.

useEffect를 쓰는 방법은 다음과 같다.

import { useEffect } from 'react';  

useEffect(() => {
  // 부수 효과를 수행하는 코드
}, [의존성 배열]);

useEffect()는 두 개 인자를 받는다. 첫 번째는 실행할 함수, 두 번째는 의존성 배열이다. 이 배열에 따라 useEffect 실행 시점이 정해진다!

위에서 말했듯이 useEffect()는 3가지의 함수를 처리하는 경우를 혼자 처리할 수 있다.
그럼 어떻게 혼자 처리할 수 있을까?

useEffect를 어떻게 작성하냐에 따라서 특정 시점에 useEffect를 호출할 수 있다.

예제를 살펴보면서 경우를 하나씩 알아보자.

import './App.css';
import { useEffect, useState } from 'react';


function App() {
  const [showCounter, setShowCounter] = useState(false);
  return (
    <>
      {showCounter && <Counter />}
      <br />
      <button className="show-btn" onClick={() => setShowCounter(!showCounter)}>
        Show?
      </button>
    </>
  );
}

function Counter() {
  const [counter, setCounter] = useState(1);
  const [counter2, setCounter2] = useState(100);


  useEffect(() => {
    console.log('컴포넌트가 마운트됨!');
  }, []);


  useEffect(() => {
    console.log('리렌더링됨!');
  });

 
  useEffect(() => {
    console.log('counter2 값이 변경됨');
  }, [counter2]);

  
  useEffect(() => {
    return () => {
      console.log('컴포넌트가 언마운트됨!');
    };
  }, []);

  return (
    <section>
      <div>
        <div>counter : {counter}</div>
        <button onClick={() => setCounter(counter + 1)}>증가</button>
      </div>
      <div>
        <div>counter : {counter2}</div>
        <button onClick={() => setCounter2(counter2 - 1)}>감소</button>
      </div>
    </section>
  );
}

export default App;
  // 1. 컴포넌트가 최초 렌더링 되는 경우에 실행되는 useEffect 함수를 구현(마운트)
  useEffect(() => {
    console.log('컴포넌트가 마운트됨!');
  }, []);

두 번째 인자에 빈 배열 [] 넣으면, 처음 화면에 그려질 때 딱 한 번만 실행돼. 초기 설정할 때 좋다.

  // 2. 컴포넌트가 리렌더링 되는 경우에 실행되는 useEffect 함수를 구현 (업데이트)
  useEffect(() => {
    console.log('리렌더링됨!');
  });

두 번째 인자를 비워두면, 처음 렌더링될 때랑 이후에 다시 렌더링될 때마다 계속 실행된다.

  // 3. counter2 값이 변경되는 경우에 실행되는 useEffect 함수를 구현 (특정 값 업데이트)
  useEffect(() => {
    console.log('counter2 값이 변경됨');
  }, [counter2]);

두 번째 인자에 [counter2] 넣으면, counter2 값 바뀔 때만 실행된다. 특정 값 변화에 반응해야 할 때 쓴다.

  // 4. 클린업 함수를 작성 (언마운트)
  useEffect(() => {
    return () => {
      console.log('컴포넌트가 언마운트됨!');
    };
  }, []);

useEffect 안에서 함수 return 하면 그게 클린업 함수다. 컴포넌트 사라지기 직전에 호출돼서, 남은 작업을 정리해 준다. 두 번째 인자에 빈 배열 [] 넣어서 언마운트될 때 딱 한 번 실행한다.

핵심 요약!!

  1. 컴포넌트 생명 주기는 컴포넌트가 처음 렌더링되는 Mounting, 업데이트되는 Updating, 그리고 화면에서 사라지는 Unmounting의 세 단계로 이루어진다!

  2. 함수 컴포넌트에서는 useEffect Hook을 통해 이러한 생명 주기와 관련된 부수 효과를 처리할 수 있다. useEffect의 두 번째 인자인 의존성 배열을 어떻게 설정하느냐에 따라 실행 시점이 결정된다!

  3. useEffect 활용

  • Mounting 시: useEffect(() => { /* ... */ }, []); - 빈 배열을 의존성으로 전달하여 처음 렌더링될 때 한 번만 실행한다.
  • Updating 시: useEffect(() => { /* ... */ }); - 두 번째 인자를 생략하여 매 렌더링마다 실행한다.
  • 특정 값 업데이트 시: useEffect(() => { /* ... */ }, [특정값]); - 특정 값이 변경될 때만 실행한다.
  • Unmounting 시: useEffect(() => { return () => { /* ... */ }; }, []); - 클린업 함수를 반환하여 컴포넌트가 사라질 때 정리 작업을 수행한다.
profile
안녕하십니까

0개의 댓글