React 중 과도한 생명주기 방법의 문제점 및 해결책

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)을 사용하여 개발자는 코드를 최적화하고 애플리케이션의 안정성과 성능을 향상시킬 수 있습니다.

태그: React 생명주기 메서드 Hooks 컴포넌트 최적화 React 개발

5월 29일 12:37에 게시됨