라이프사이클 (Lifecycle)
React 컴포넌트는 화면에 나타나고, 업데이트되고, 사라지는 과정을 가진다.
이 흐름을 라이프사이클(Lifecycle) 이라고 한다.
🚀New Article:React State and Lifecycle – Managing Dynamic Data(useEffect)🚀
React는 이 과정마다 특정 작업을 실행할 수 있도록 기능을 제공한다.
🔄 라이프사이클을 이해해야 하는 이유
React에서 라이프사이클을 이해하면 컴포넌트가 언제 렌더링되고, 언제 부수 효과를 실행해야 하는지 알 수 있다. 특히 다음과 같은 작업을 할 때 중요하다.
- API 요청 시점 정하기
- 불필요한 렌더링 줄이기
- 이벤트 리스너 정리하기
- 타이머 정리하기
- 메모리 누수 방지하기
- props나 state 변경에 따른 작업 처리하기
라이프사이클이란?
라이프사이클은 컴포넌트가 브라우저 화면에 나타난 뒤, 상태나 props 변화에 따라 다시 렌더링되고, 더 이상 필요하지 않을 때 화면에서 사라지는 전체 흐름을 의미한다.
예를 들어 다음과 같은 상황들이 라이프사이클과 관련된다.
- 컴포넌트가 처음 화면에 나타날 때
- state가 변경되어 화면이 다시 렌더링될 때
- props가 변경될 때
- 컴포넌트가 화면에서 사라질 때
- API 요청, 타이머, 이벤트 등록과 정리가 필요할 때
React 컴포넌트의 라이프사이클 단계
React 컴포넌트의 라이프사이클은 크게 세 단계로 나눌 수 있다.
1. Mount
Mount는 컴포넌트가 처음 화면에 나타나는 단계이다.
- 초기 데이터 요청 / 이벤트 등록 / 타이머 설정 / 외부 라이브러리 초기화
2. Update
Update는 컴포넌트가 다시 렌더링되는 단계이다.
- state가 변경될 때 / props가 변경될 때 / 부모 컴포넌트가 다시 렌더링될 때
3. UnMount
Unmount는 컴포넌트가 화면에서 사라지는 단계이다.
예를 들어 조건부 렌더링으로 컴포넌트를 숨기거나, 다른 페이지로 이동해서 기존 컴포넌트가 사라질 때 Unmount가 발생한다.
- 타이머 제거 / 이벤트 제거 / 구독 해제 / 진행 중인 작업 정리
클래스 컴포넌트의 라이프사이클 메서드
과거에는 클래스 컴포넌트에서 라이프사이클 메서드를 사용했다.
class Example extends React.Component {
componentDidMount() {
console.log("컴포넌트가 처음 화면에 나타남");
}
componentDidUpdate() {
console.log("컴포넌트가 업데이트됨");
}
componentWillUnmount() {
console.log("컴포넌트가 화면에서 사라짐");
}
render() {
return <div>Example</div>;
}
}대표적인 라이프사이클 메서드는 다음과 같다.
| 메서드 | 실행 시점 |
|---|---|
componentDidMount | 컴포넌트가 처음 화면에 나타난 후 |
componentDidUpdate | 컴포넌트가 업데이트된 후 |
componentWillUnmount | 컴포넌트가 화면에서 사라지기 전 |
함수 컴포넌트의 useEffect
함수 컴포넌트에서는 라이프사이클 메서드 대신 useEffect를 사용한다.useEffect는 렌더링 이후 특정 작업을 실행할 수 있게 해주는 Hook이다.
import { useEffect } from "react";
function Example() {
useEffect(() => {
console.log("컴포넌트가 렌더링된 후 실행");
});
return <div>Example</div>;
}useEffect로 라이프사이클 표현하기
useEffect의 의존성 배열을 어떻게 작성하느냐에 따라 실행 시점이 달라진다.
1. 렌더링될 때마다 실행
useEffect(() => {
console.log("렌더링될 때마다 실행");
});- 의존성 배열을 생략하면 컴포넌트가 렌더링될 때마다 실행된다.
- 즉, 처음 렌더링될 때도 실행되고,
state나props가 변경되어 다시 렌더링될 때도 실행된다.
2. 처음 한 번만 실행
useEffect(() => {
console.log("처음 한 번만 실행");
}, []);- 의존성 배열에 빈 배열
[]을 넣으면 컴포넌트가 처음 화면에 나타난 뒤 한 번만 실행된다. - 클래스 컴포넌트의
componentDidMount와 비슷한 역할을 한다. - 주로 초기 API 요청에 사용한다.jsx
useEffect(() => { fetchData(); }, []);
3. 특정 값이 변경될 때 실행
useEffect(() => {
console.log("count가 변경될 때 실행");
}, [count]);- 의존성 배열에 특정 값을 넣으면 그 값이 변경될 때마다
effect가 실행된다. - 클래스 컴포넌트의
componentDidUpdate와 비슷하게 사용할 수 있다.
4. 컴포넌트가 사라질 때 정리하기
useEffect 안에서 함수를 return하면 정리 함수로 사용된다.
useEffect(() => {
const timer = setInterval(() => {
console.log("타이머 실행 중");
}, 1000);
return () => {
clearInterval(timer);
console.log("타이머 정리");
};
}, []);return된 함수는 컴포넌트가 화면에서 사라질 때 실행된다.- 클래스 컴포넌트의
componentWillUnmount와 비슷한 역할을 한다.
useEffect 실행 흐름
다음 코드를 보면 라이프사이클 흐름을 더 쉽게 이해할 수 있다.
import { useEffect, useState } from "react";
function LifeCycleExample() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Mount 또는 count 변경 후 실행");
return () => {
console.log("다음 effect 실행 전 또는 Unmount 시 정리");
};
}, [count]);
return (
<div>
<p>count: {count}</p>
<button onClick={() => setCount(count + 1)}>증가</button>
</div>
);
}이 코드의 실행 흐름은 다음과 같다.
- 컴포넌트가 처음 렌더링됨
- useEffect 실행
- 버튼 클릭
- count 변경
- 컴포넌트 다시 렌더링
- 이전 effect 정리 함수 실행
- 새로운 effect 실행
- 컴포넌트가 사라지면 정리 함수 실행
여기서 중요한 점은 return 함수가 꼭 Unmount 때만 실행되는 것은 아니라는 것이다. 의존성 배열의 값이 바뀌어 effect가 다시 실행되기 전에도 이전 effect를 정리하기 위해 실행된다.