React 중 과도한 생명주기 방법의 문제점 및 해결책
React 개발 과정에서 버전이 계속 업데이트됨에 따라 일부 생명주기 메서드는 더 이상 사용되지 않거나 폐기되었습니다. 이러한 메서드를 계속 사용하면 특히 동시 렌더링 모드에서 예측 불가능한 부작용이 발생할 수 있습니다. 본문에서는 React의 과도한 생명주기 메서드와 그 대안을 살펴보며 개발자들이 코드를 최적화할 수 있도록 도움을 드립니다.
React의 과도한 생명주기 메서드
1. `componentWillMount`
문제점: `componentWillMount`는 컴포넌트가 DOM에 마운트되기 전에 호출되지만, 비동기 렌더링 모드에서 여러 번 호출될 수 있어 부작용(데이터 요청 등)이 여러 번 실행될 수 있습니다.
대안:
- 생성자를 사용하여 상태 초기화
- 부작용(데이터 요청 등)을 `componentDidMount`로 이동
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { data: null };
}
componentDidMount() {
fetch('api/data')
.then(response => response.json())
.then(data => this.setState({ data }));
}
render() {
return <div>{this.state.data ? this.state.data.title : 'Loading...'}</div>;
}
}
2. `componentWillReceiveProps`
문제점: 컴포넌트가 새로운 props를 받을 때 호출되지만, 비동기 렌더링 모드에서 불일치한 동작을 유발할 수 있습니다.
대안:
- `static getDerivedStateFromProps`를 사용하여 파생 상태 처리
- `componentDidUpdate`를 사용하여 부작용 처리
class MyComponent extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.someProp !== prevState.someProp) {
return { someProp: nextProps.someProp };
}
return null;
}
componentDidUpdate(prevProps) {
if (prevProps.someProp !== this.props.someProp) {
// props 변경 처리
}
}
render() {
return <div>{this.state.someProp}</div>;
}
}
3. `componentWillUpdate`
문제점: 컴포넌트가 업데이트되기 전에 호출되지만, 비동기 렌더링 모드에서 불일치한 동작을 유발할 수 있습니다.
대안:
- `getSnapshotBeforeUpdate`와 `componentDidUpdate` 사용
class MyComponent extends React.Component {
getSnapshotBeforeUpdate(prevProps, prevState) {
// DOM 업데이트 전에 실행
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// DOM 업데이트 후에 실행
}
render() {
return <div>{this.props.someProp}</div>;
}
}
4. `componentWillUnmount`
문제점: 더 이상 사용되지 않은 메서드는 아니지만, 이 메서드에서 비동기 작업을 실행하거나 `setState`를 호출하면 메모리 누수가 발생할 수 있습니다.
주의사항:
- 이 메서드에서 비동기 작업을 수행하지 마세요
- 정리 작업(예: 타이머 취소, 이벤트 리스너 해제)에만 사용
class MyComponent extends React.Component {
componentDidMount() {
this.timer = setInterval(() => {
console.log('Timer tick');
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
render() {
return <div>Timer Component</div>;
}
}
React Hooks의 대안
React Hooks의 도입으로 클래스 컴포넌트의 생명주기 메서드는 Hooks로 대체할 수 있어 코드를 단순화할 수 있습니다.
1. `componentDidMount` 및 `componentDidUpdate`
`useEffect`를 사용한 대안:
useEffect(() => {
// 데이터 요청 또는 다른 부작용
return () => {
// 정리 로직
};
}, [dependencies]);
2. `getDerivedStateFromProps`
`useState`와 `useEffect`를 사용한 대안:
const [state, setState] = useState(initialState);
useEffect(() => {
// 파생 상태 로직
}, [props]);
3. `componentWillUnmount`
`useEffect`의 정리 함수를 사용한 대안:
useEffect(() => {
return () => {
// 정리 로직
};
}, []);
결론
React의 일부 생명주기 메서드는 더 이상 사용되지 않으며, 계속 사용하면 예측 불가능한 부작용과 성능 문제가 발생할 수 있습니다. 대안(예: `constructor`, `static getDerivedStateFromProps`, `componentDidUpdate`, Hooks)을 사용하여 개발자는 코드를 최적화하고 애플리케이션의 안정성과 성능을 향상시킬 수 있습니다.