리액트 컴포넌트는 단순히 화면을 렌더링하는 것이 아니라, 생성 → 업데이트 → 소멸이라는 생애 주기를 가진다. 이를 이해하면 상태(state)와 속성(props)의 변화에 따른 렌더링 흐름을 파악할 수 있으며, 불필요한 렌더링을 방지하여 성능을 최적화할 수 있다.
또한, 라이프사이클 메서드는 외부 API 호출, 이벤트 리스너 등록 및 해제, 타이머 설정 등의 중요한 작업을 수행하는 데 활용된다. 함수형 컴포넌트가 보편화되면서, 기존의 라이프사이클 메서드가 useEffect 등의 훅(Hook)으로 대체되고 있다. 따라서 클래스형과 함수형 컴포넌트의 라이프사이클 차이를 비교하고, 적절한 방식으로 적용하는 것이 중요하다.
리액트 컴포넌트는 출생(Mounting) → 성장(Updating) → 소멸(Unmounting) 과정을 거친다. 각 단계에서 특정 메서드가 호출되며, 이를 활용하여 필요한 작업을 수행할 수 있다.
🧩 1. Mounting (출생 단계)
컴포넌트가 생성되어 DOM에 삽입될 때 실행된다.
🔹 주요 메서드
1. constructor(props)
• 초기 state를 설정하고 메서드를 바인딩하는 데 사용된다.
• super(props) 호출이 필수이다.
2. static getDerivedStateFromProps(props, state)
• props에서 파생된 state를 설정하는 데 사용된다.
3. render()
• UI를 렌더링하는 메서드이며, 순수 함수로 작성해야 한다.
4. componentDidMount()
• 컴포넌트가 마운트된 직후 실행되며, API 호출, 타이머 설정 등의 비동기 작업을 수행하는 데 적합하다.
✅ 예제 코드
class ExampleComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
console.log('Component Mounted!');
}
render() {
return <h1>Hello, World!</h1>;
}
}
🔄 2. Updating (업데이트 단계)
컴포넌트의 props나 state가 변경될 때 실행된다.
🔹 주요 메서드
1. static getDerivedStateFromProps(props, state)
• props가 변경될 때 state를 업데이트하는 메서드이다.
2. shouldComponentUpdate(nextProps, nextState)
• 리렌더링 여부를 결정하여 불필요한 렌더링을 방지한다.
3. render()
• 변경된 props나 state를 반영하여 UI를 다시 그린다.
4. getSnapshotBeforeUpdate(prevProps, prevState)
• 업데이트 직전에 DOM의 상태를 저장하는 데 사용된다.
5. componentDidUpdate(prevProps, prevState)
• 업데이트가 완료된 후 실행되며, DOM 조작, API 호출 등의 후처리 작업에 유용하다.
✅ 예제 코드
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
shouldComponentUpdate(nextProps, nextState) {
return nextState.count !== this.state.count; // count 변경 시에만 리렌더링
}
componentDidUpdate(prevProps, prevState) {
console.log('Component Updated!');
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
🛑 3. Unmounting (소멸 단계)
컴포넌트가 DOM에서 제거될 때 실행된다.
🔹 주요 메서드
1. componentWillUnmount()
• 컴포넌트가 제거되기 직전에 호출되며, 타이머 해제, 이벤트 리스너 제거 등의 정리 작업을 수행하는 데 사용된다.
✅ 예제 코드
class Timer extends React.Component {
componentDidMount() {
this.timerID = setInterval(() => console.log('Tick'), 1000);
}
componentWillUnmount() {
clearInterval(this.timerID); // 타이머 해제
console.log('Component Unmounted!');
}
render() {
return <div>Timer is running...</div>;
}
}
⚡ 함수형 컴포넌트에서 라이프사이클 관리 (useEffect)
함수형 컴포넌트에서는 클래스형 컴포넌트의 라이프사이클 메서드를 useEffect 훅으로 대체할 수 있다.
🔹 useEffect 기본 구조
useEffect(() => {
// 실행할 코드
return () => {
// 정리(clean-up) 코드
};
}, [의존성 배열]);
• 마운트 & 업데이트 시 실행: [](빈 배열)을 제외하면 상태 변화 시에도 실행된다.
• 언마운트 시 실행: return문 안의 코드가 실행된다.
✅ 예제 코드 (타이머 컴포넌트)
import React, { useEffect, useState } from 'react';
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Component Mounted or Updated');
const timer = setInterval(() => setCount(prev => prev + 1), 1000);
return () => {
clearInterval(timer); // Cleanup
console.log('Component Unmounted');
};
}, []); // 빈 배열이면 마운트 시 1회만 실행됨
return <h1>Count: {count}</h1>;
}
리액트 컴포넌트의 라이프사이클을 이해하면 컴포넌트의 생성, 업데이트, 소멸 과정에서 발생하는 이벤트를 효과적으로 관리할 수 있다. 컴포넌트 라이프사이클을 이해하고 활용하면, 더 성능 최적화된 리액트 애플리케이션을 개발할 수 있다.