생명주기란?
컴포넌트의 생성부터 소멸까지의 과정을 컴포넌트의 생명주기(Lifecycle)라고 한다.
컴포넌트는 생명주기마다 함수를 가지고 있고, 이 함수들을 이용하면 주기의 특정 시점에 원하는 동작을 하도록 만들 수 있다.
컴포넌트의 생명주기
컴포넌트의 생명주기 함수는 총 8종이 있다.
생명주기 함수는 리액트에서 자동으로 호출하며 개발자가 마음대로 호출할 수 없다.
생명주기를 그림으로 나타내면 다음과 같다.
컴포넌트는 생성부터 소멸까지 컴포넌트 생성 → 생성 완료 → 갱신 완료 → 소멸 완료의 4가지 단계를 거친다.
과정은 컴포넌트 생성 → 생성 완료(생성 과정), 생성 완료 → 갱신 완료(갱신 과정), 갱신 완료 → 소멸 완료(소멸 과정)의 3가지 과정을 거친다.
먼저 생명주기 함수가 무엇이 있는지 알아보고, 각 과정마다 호출되는 생명주기 함수를 알아보도록 하겠다.
생명주기 함수
constructor(props) 함수
constructor() 함수는 맨 처음에 생성될 때 한 번만 호출된다.
상태(state, 객체 변수)를 선언할 때 사용된다.
constructor함수를 정의할 때는 항상 super()함수를 가장 위에 호출해야 한다.
super() 함수는 프로퍼티와 생명 주기 상태를 초기화 하는 과정을 포함하기 때문이다.
render() 함수
render 함수는 리액트를 다루면 흔히 볼 수 있는 함수이다.
render() 함수는 데이터가 변경되어 새 화면을 그려야 할 때 자동으로 호출되는 함수이며, 함수가 반환하는 JSX를 화면에 그려준다.
componentDidMount() 함수
componentDidMount() 함수는 render() 함수가 JSX를 화면에 그린 이후에 호출되는 함수이다.
만약 외부 API호출 등 컴포넌트가 화면에 모두 표현된 이후 해야 하는 작업이 있다면 이 함수를 사용하면 된다.
shouldComponentUpdate(nextProps, nextState) 함수
shouldComponentUpdate() 함수는 프로퍼티를 변경하거나 setState() 함수를 호출하여 state값이 변경되면 화면을 새로 출력해야 하는지 판단하는 함수이다.
이 함수는 화면을 새로 출력할지 말지 판단하고, 데이터 변화를 비교하는 작업을 초함하기 때문에 리액트 성능에 영향을 많이 준다.
forceUpdate() 함수를 호출하여 화면을 출력하면 이 함수는 호출되지 않는다.
getSnapshotBeforeUpdate(prevProps, prevState) 함수
getSnapshotBeforeUpdate() 함수는 컴포넌트의 변경된 내용이 가상 화면에 완성된 이후 호출되는 함수이다.
화면에 출력될 요소의 크기 또는 스크롤 위치 등의 DOM 정보에 접근할 때 사용된다.
componentDidUpdate(prevProps, prevState, snapshot) 함수
componentDidUpdate() 함수는 컴포넌트가 실제 화면에 출력된 이후 호출되는 함수이다.
이 함수는 부모 컴포넌트로부터 전달된 이전 프로퍼티(prevProps) 이전 state값(prevState) getSnapshotBeforeUpdate() 함수에서 반환된 값(snapshot)을 인자로 전달받는다.
이 값들을 이용하여 스크롤 위치를 옮기거나 커서를 이동시키는 등의 DOM 정보를 변경할 때 사용된다.
componentWillUnmount() 함수
componentWillUnmount() 함수는 컴포넌트가 소멸되기 직전에 호출되는 함수이다.
컴포넌트에서 감시하고 있는 작업들을 해제할 때 필요한 함수이다.
해제 작업이 생략되면 메모리 누수 현상이 발생하여 웹 브라우저의 작동이 멈추기도 한다.
각 과정에서의 생명주기 함수
각 과정에서 생명주기 함수는 그림과 같은 순서로 호출된다.
그렇다면! 각 과정에서 정말로 이 함수들이 순서대로 호출되는지 확인을 안해 볼 수 없다.
LifeCycle.jsx
import React, { Component } from 'react';
class LifeCycle extends Component {
static getDerivedStateFromProps(){
console.log('getDerivedStateFromProps 호출');
return {};
}
constructor(props){
super(props);
//경고 메세지를 건너 뛰기 위해 state 초기값 설정
this.state = {};
console.log('constructor 호출');
}
componentDidMount() {
console.log('componentDidMount 호출');
}
componentDidUpdate() {
console.log('componentDidUpdate 호출');
}
componentWillUnmount(){
console.log('componentWillUnmount 호출');
}
getSnapshotBeforeUpdate(){
console.log('getSnapshotBeforeUpdate 호출');
return {};
}
shouldComponentUpdate(){
console.log('shouldComponentUpdate 호출');
return true;
}
render() {
console.log('render 호출');
return null
}
}
export default LifeCycle;
해당 코드를 사용하여 react 서버에서 구동 시, 해당 함수들이 순서대로 호출됨을 알 수 있다.
변경 과정은 shouldComponentUpdate() 함수의 반환값이 true인 경우 진행되므로 반환값을 true로 바꿔준다.
componentDidMount() 함수 변경
componentDidMount() {
console.log('componentDidMount 호출');
this.setState({updated: true});
}
이와 같이 변경 과정이 순서대로 잘 동작한다.
그렇다면 만약 반환값이 false라면 어떻게 작동하는지 보도록 할 것이다.
shouldComponentUpdate() 함수 변경
shouldComponentUpdate(){
console.log('shouldComponentUpdate 호출');
return false;
}
결과는 다음과 같다.
마무리
사실 본 글에 쓰인 함수의 결과값이 의도하지 않은 대로 호출되었다.
중간에 componentWillUnmount가 호출되어선 안되는데 이게 왜 호출되었는지는 따로 공부를 더 해봐야 할 것 같다.
+2023-02-14 추가
중간에 componentWillUnmount가 호출되는 이유는 StrictMode 때문이다.
StrictMode는 공식 문서에 자세하게 설명되어 있다.
https://ko.reactjs.org/docs/strict-mode.html
개발 과정에서 StrictMode를 굳이 사용하지 않을 이유는 없다.
하지만 생명주기 메소드들을 한번씩 호출되는 것을 보고 싶다면 index.js의 <React.Strictmode>를 주석처리 하거나 삭제하면 된다.
'React' 카테고리의 다른 글
[React] Redux를 사용해서 간편하게 모달(modal) 구현하기 (0) | 2024.03.13 |
---|---|
[React] 프로퍼티에 필수, 기본값 지정 / 자식 프로퍼티 사용 (0) | 2023.01.13 |
[React] 다양한 자료형 프로퍼티 사용하기 (0) | 2023.01.06 |
[React] 프로퍼티(props) 기본 (0) | 2023.01.04 |
[React] 리액트 시작하기 (0) | 2023.01.03 |