frontend/react

[React] React.js 강좌 4. 컴포넌트 생명주기 (Lifecycle Methods)

mirabo01 2025. 11. 11. 09:55

1. 생명주기(Lifecycle)란?

리액트에서 컴포넌트는 생성되고, 업데이트되고, 사라지는 흐름을 가지고 있습니다.
이 과정을 **컴포넌트의 생명주기(Lifecycle)**라고 부릅니다.

쉽게 말하면, 리액트 컴포넌트도 사람처럼
“태어남 → 변화함 → 사라짐”의 과정을 겪는다는 뜻입니다.

이 생명주기를 이해하면 다음과 같은 일들을 더 효율적으로 처리할 수 있습니다.

  • API 데이터를 컴포넌트가 처음 렌더링될 때 불러오기
  • 특정 상태가 바뀔 때만 실행되는 로직 제어
  • 컴포넌트가 사라질 때 정리(clean-up) 작업 수행

2. 클래스형 컴포넌트의 생명주기 메서드

리액트 초창기에는 클래스형 컴포넌트에서 생명주기 메서드를 사용했습니다.
아래 코드는 기본적인 구조를 보여줍니다.

import React, { Component } from 'react';

class Example extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    console.log('1️⃣ constructor 실행');
  }

  componentDidMount() {
    console.log('3️⃣ componentDidMount - 컴포넌트가 화면에 나타남');
  }

  componentDidUpdate() {
    console.log('4️⃣ componentDidUpdate - 상태나 props가 변경됨');
  }

  componentWillUnmount() {
    console.log('5️⃣ componentWillUnmount - 컴포넌트가 사라짐');
  }

  render() {
    console.log('2️⃣ render 실행');
    return (
      <div>
        <p>현재 카운트: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          +1
        </button>
      </div>
    );
  }
}

export default Example;

위 코드를 실행하면 콘솔에는 다음 순서로 출력됩니다.

1️⃣ constructor 실행  
2️⃣ render 실행  
3️⃣ componentDidMount - 컴포넌트가 화면에 나타남  

버튼을 눌러 상태가 바뀌면:

2️⃣ render 실행  
4️⃣ componentDidUpdate - 상태나 props가 변경됨  

그리고 컴포넌트가 화면에서 사라질 때:

5️⃣ componentWillUnmount - 컴포넌트가 사라짐

이렇게 리액트는 컴포넌트의 생명주기에 따라 자동으로 특정 메서드를 호출합니다.


3. 주요 생명주기 메서드 정리

단계 메서드 설명

마운트(Mount) constructor, componentDidMount 컴포넌트가 처음 생성되어 DOM에 부착될 때
업데이트(Update) componentDidUpdate props나 state가 바뀌어 다시 렌더링될 때
언마운트(Unmount) componentWillUnmount 컴포넌트가 화면에서 제거될 때

이 흐름을 이해하면 “언제 데이터를 가져오고”, “언제 정리할지”를 명확히 제어할 수 있습니다.


4. 함수형 컴포넌트에서의 생명주기 – useEffect

리액트 16.8 이후부터는 Hooks를 통해 함수형 컴포넌트에서도 생명주기를 제어할 수 있습니다.
이때 사용하는 것이 바로 useEffect 훅입니다.

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

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

  // 마운트 및 업데이트 시 실행
  useEffect(() => {
    console.log('렌더링 이후 실행됨');
  });

  return (
    <div>
      <p>현재 카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

export default Counter;

useEffect는 기본적으로 렌더링 후마다 실행됩니다.
하지만 두 번째 인자로 **의존성 배열(dependency array)**을 전달하면
언제 실행할지를 세밀하게 제어할 수 있습니다.


5. useEffect의 세 가지 사용 패턴

① 마운트될 때 한 번만 실행

useEffect(() => {
  console.log('처음 한 번만 실행');
}, []);

의존성 배열이 []이면 처음 렌더링될 때 한 번만 실행됩니다.
보통 API 호출이나 초기 설정에 사용됩니다.


② 특정 값이 바뀔 때만 실행

useEffect(() => {
  console.log('count가 바뀔 때만 실행');
}, [count]);

이 경우 count 값이 변경될 때만 실행됩니다.
이를 통해 불필요한 렌더링 로직을 방지할 수 있습니다.


③ 언마운트 시 정리(clean-up)

useEffect(() => {
  const timer = setInterval(() => {
    console.log('1초마다 실행');
  }, 1000);

  return () => {
    clearInterval(timer);
    console.log('컴포넌트가 사라질 때 정리');
  };
}, []);

useEffect에서 return을 사용하면
컴포넌트가 사라질 때(clean-up) 실행할 코드를 정의할 수 있습니다.
이는 componentWillUnmount와 동일한 역할을 합니다.


6. 클래스형 vs 함수형 생명주기 비교

기능 클래스형 함수형(Hooks)

마운트 시 componentDidMount() useEffect(() => {...}, [])
업데이트 시 componentDidUpdate() useEffect(() => {...}, [state])
언마운트 시 componentWillUnmount() useEffect(() => { return () => {...} })

지금은 함수형 컴포넌트가 주류이기 때문에
대부분의 프로젝트에서는 useEffect 하나로 생명주기를 모두 제어합니다.


7. 마무리 정리

  • 리액트 컴포넌트는 “생성 → 업데이트 → 소멸”의 흐름을 가진다.
  • 클래스형에서는 componentDidMount, componentDidUpdate, componentWillUnmount로 제어한다.
  • 함수형에서는 useEffect 훅 하나로 생명주기를 모두 처리할 수 있다.
  • 클린업(clean-up)을 적절히 사용하면 메모리 누수를 방지할 수 있다.

다음 글에서는 리액트에서 자주 사용하는 **이벤트 처리(Event Handling)**와
this 바인딩의 원리에 대해 알아보겠습니다.