안녕하세요, 리액트 개발자 여러분! 오늘 우리는 리액트 애플리케이션의 핵심을 이루는 '컴포넌트 생명주기(Lifecycle)'에 대해 깊이 파고들어 보려 합니다. 컴포넌트 생명주기는 컴포넌트가 생성되고, 업데이트되고, 소멸되는 일련의 과정이며, 이 과정을 이해하는 것은 사이드 이펙트 관리, 성능 최적화, 그리고 예측 가능한 컴포넌트 동작을 보장하는 데 매우 중요합니다. 특히, 클래스형 컴포넌트의 생명주기 메서드부터 함수형 컴포넌트의 훅(Hook)으로의 전환까지, 리액트의 변화하는 흐름 속에서 생명주기를 어떻게 효과적으로 다룰 수 있는지 함께 살펴보겠습니다.
컴포넌트 생명주기란 무엇인가요?
리액트 컴포넌트는 마치 살아있는 유기체처럼 자신만의 생명 주기를 가집니다. 이 생명 주기는 크게 세 가지 주요 단계로 나뉘며, 각 단계에서 특정 시점에 호출되는 특별한 함수들을 '생명주기 메서드'라고 부릅니다. 이러한 메서드들을 통해 개발자는 컴포넌트의 특정 생명 주기 시점에 코드를 실행하여 원하는 작업을 수행할 수 있습니다.
- 마운트(Mounting)
컴포넌트의 인스턴스가 생성되어 가상 DOM에 삽입되고 실제 DOM에 반영되는 초기 단계입니다. 이때 컴포넌트는 화면에 처음으로 나타나게 됩니다. - 업데이트(Updating)
컴포넌트의 props나 state가 변경될 때 발생합니다. 이 변경으로 인해 컴포넌트가 다시 렌더링되면서 화면에 새로운 내용이 반영됩니다. - 언마운트(Unmounting)
컴포넌트가 더 이상 필요 없어지거나 화면에서 제거될 때 발생합니다. 이 단계에서는 컴포넌트가 차지하던 리소스를 정리하는 중요한 작업이 이루어집니다.
각 생명주기 단계에는 고유한 메서드 세트가 있으며, 이 메서드들을 재정의하여 해당 단계에서 특정 작업을 수행할 수 있습니다.
주요 생명주기 메서드 (클래스형 컴포넌트)
클래스형 컴포넌트에서 주로 사용되는 몇 가지 중요한 생명주기 메서드를 살펴보겠습니다.
1. componentDidMount()
이 메서드는 컴포넌트가 DOM에 성공적으로 마운트된 직후(트리에 삽입된 후) 호출됩니다. 초기 데이터 로딩, API 호출, 구독 설정 등과 같이 컴포넌트가 화면에 나타난 후에 수행되어야 할 작업에 이상적입니다.
class ExampleComponent extends React.Component {
componentDidMount() {
// API에서 데이터 가져오기
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => this.setState({ data }));
}
render() {
return <div>{this.state.data}</div>;
}
}
위 예시에서 componentDidMount는 컴포넌트가 화면에 나타나자마자 외부 API에서 데이터를 비동기적으로 가져와 컴포넌트의 상태를 업데이트합니다.
2. componentDidUpdate(prevProps, prevState)
이 메서드는 컴포넌트의 props 또는 state가 변경되어 업데이트가 발생한 직후 호출됩니다. prevProps와 prevState 인자를 통해 이전 props와 state에 접근할 수 있으므로, 현재 props/state와 비교하여 특정 변경에만 반응하는 로직을 구현할 때 유용합니다. 예를 들어, 특정 props가 변경될 때 새로운 데이터를 가져오는 등의 작업에 활용할 수 있습니다.
class ExampleComponent extends React.Component {
state = { count: 0 };
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
console.log('Count has changed:', this.state.count);
}
}
increment = () => this.setState({ count: this.state.count + 1 });
render() {
return (
<div>
<button onClick={this.increment}>Increment</button>
<p>Count: {this.state.count}</p>
</div>
);
}
}
위 코드에서는 count 상태가 변경될 때마다 콘솔에 메시지를 출력하는 예시를 보여줍니다.
3. componentWillUnmount()
이 메서드는 컴포넌트가 DOM에서 제거되고 파괴되기 직전에 호출됩니다. 이는 컴포넌트가 사용하던 리소스를 정리하는 중요한 단계입니다. 예를 들어, setInterval로 설정한 타이머를 해제하거나, 구독을 취소하거나, 네트워크 요청을 취소하는 등의 정리 작업에 적합합니다. 리소스를 제대로 정리하지 않으면 메모리 누수나 예상치 못한 버그를 유발할 수 있습니다.
class TimerComponent extends React.Component {
timerId;
componentDidMount() {
this.timerId = setInterval(() => console.log('Tick'), 1000);
}
componentWillUnmount() {
clearInterval(this.timerId); // 타이머 정리
}
render() {
return <h1>Timer Running...</h1>;
}
}
이 예시에서는 setInterval로 설정된 타이머가 컴포넌트가 언마운트될 때 clearInterval을 통해 깨끗하게 정리됩니다.
훅(Hooks)을 사용한 함수형 컴포넌트로의 전환
리액트 16.8에서 훅(Hooks)이 도입되면서, 리액트 개발의 패러다임이 크게 변화했습니다. 많은 개발자들이 클래스형 컴포넌트의 복잡한 생명주기 메서드 대신, 더 간결한 문법과 상태 로직의 쉬운 관리를 제공하는 함수형 컴포넌트와 훅을 사용하기 시작했습니다.
특히, useEffect 훅은 클래스형 컴포넌트의 componentDidMount, componentDidUpdate, componentWillUnmount의 기능을 한데 묶어 제공합니다. 이는 사이드 이펙트(데이터 가져오기, 구독, DOM 직접 조작 등)를 처리하는 데 사용됩니다.
useEffect 훅의 활용
useEffect는 컴포넌트 렌더링 후에 특정 작업을 수행하도록 '사이드 이펙트'를 예약합니다. useEffect의 두 번째 인자인 의존성 배열(dependency array)을 통해 언제 이 이펙트가 다시 실행될지 제어할 수 있습니다.
import React, { useEffect } from 'react';
const ExampleFunctionalComponent = () => {
useEffect(() => {
const timerId = setInterval(() => console.log('Tick'), 1000);
// componentWillUnmount와 유사한 정리 함수
return () => clearInterval(timerId);
}, []); // 빈 의존성 배열은 마운트 시 한 번 실행됨을 의미
return <h1>Functional Component with Timer</h1>;
};
위 예시에서 useEffect 내부에 타이머를 설정하고 있습니다. 주목할 점은 useEffect의 콜백 함수에서 반환되는 함수입니다. 이 반환 함수는 컴포넌트가 언마운트될 때(혹은 의존성 배열이 변경되어 다음 이펙트가 실행되기 전에) 실행되어 componentWillUnmount와 유사한 정리 작업을 수행합니다. 빈 의존성 배열([])은 이 이펙트가 컴포넌트가 마운트될 때 한 번만 실행되고, 언마운트될 때 정리 함수가 호출됨을 의미합니다.
결론
리액트 컴포넌트의 생명주기를 이해하는 것은 견고하고 효율적인 애플리케이션을 구축하는 데 필수적인 역량입니다. 클래스형 컴포넌트가 전용 생명주기 메서드를 통해 각 단계에 대한 명시적인 제어를 제공했다면, 함수형 컴포넌트는 useEffect와 같은 훅을 통해 코드베이스의 가독성과 간결성을 유지하면서도 사이드 이펙트 처리를 우아하게 단순화하는 대안을 제공합니다.
중급 리액트 개발자로서 이러한 개념들을 숙달함으로써, 복잡한 상호 작용을 원활하게 처리하고 예측 가능한 동작을 하는 반응형 애플리케이션을 생성할 수 있는 능력과 이해도를 모두 향상시킬 수 있습니다. 오늘 배운 내용을 바탕으로 여러분의 리액트 개발 실력이 한 단계 더 성장하길 바랍니다!
'프로그래밍 > ReactJS' 카테고리의 다른 글
| React 개발의 핵심: useState 훅 완벽 가이드 (0) | 2025.10.09 |
|---|---|
| React 컴포넌트 마스터하기: 함수형과 클래스형, 그리고 훅의 모든 것! (0) | 2025.10.08 |
| React 클래스 컴포넌트 마스터하기: 여전히 중요할까요? (0) | 2025.10.08 |
| React 함수 컴포넌트, 왜 대세가 되었을까? 클래스 컴포넌트와의 비교를 통해 알아보는 핵심 장점 (0) | 2025.10.08 |
| React 앱 배포, 더 이상 어렵지 않아요! 당신에게 맞는 최적의 플랫폼은? (0) | 2025.10.07 |