React 컴포넌트의 생명주기

piecemaker·2020년 8월 20일
0

지금 이 글을 읽는 독자분이 리액트를 사용하실 때 클래스 컴포넌트(Class Component)를 주로 사용하시는지 아니면 함수형 컴포넌트(Functional Component)를 주로 사용하시는지 모르겠다.

하지만, 우리가 리액트에서 어떤 형식의 컴포넌트를 사용하던 간에 무조건 알아야 하는 개념이 있는데, 바로 컴포넌트의 생명주기(LifeCycle)이다.

React 컴포넌트의 생명주기를 설명함에 있어서 문법을 일관성있게 유지해야 하기 때문에 클래스 컴포넌트를 중심으로 설명할 것이지만, 함수형 컴포넌트도 동일하게 동작한다는 사실을 알아주셨으면 한다.

컴포넌트 마운트 (Mount) 생명주기

리액트에서 마운트(Mount)는 우리가 정의한 컴포넌트에 해당하는 DOM 객체를 생성하고, 실제로 브라우저에 렌더링하는 일련의 과정을 의미한다.

Welcome이라는 리액트 클래스 컴포넌트를 생성한다고 가정하자. 리액트에서 클래스 컴포넌트를 정의하기 위해서는 다음과 같이 React.Component를 상속해줘야 한다.

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

우리가 이렇게 Welcome이라는 클래스 컴포넌트를 정의하고, 실제로 다음과 같이 ReactDOM.render 함수를 호출하여 Welcome 컴포넌트를 처음으로 렌더링한다고 가정하자.

ReactDOM.render(
	<Welcome name="Minsu" />,
	document.getElementById("root")
);

Welcome은 우리가 정의해 준 클래스일 뿐이다. 따라서, 실제로 사용할 때에는 리액트에서 이 클래스의 인스턴스를 생성해주는데, 인스턴스가 생성될 때에는 해당 클래스의 생성자 (constructor)가 자동으로 호출된다는 사실을 알 것이다.

Welcome 클래스의 경우 생성자를 정의한 적이 없으므로 부모 클래스인 React.Component의 생성자를 상속받아 그대로 호출 할 것이다. Welcome 클래스에서 생성자를 새로 정의했다면 새로 정의한 생성자가 호출될 것이다.

Welcome 클래스의 인스턴스를 만들었다면, 리액트는 render 함수를 호출한 후 render 함수의 리턴값을 통해 DOM 객체를 생성하고 이를 실제 화면에 렌더링 할 것이다.

이러한 일련의 과정이 끝나고 Welcome 클래스 인스턴스가 성공적으로 마운트(Mount)되면, React.Component라는 부모 클래스로부터 상속받은 생명주기 관리 함수들 중 하나인 componentDidMount 함수가 호출된다. 만약 Welcome 클래스에 componentDidMount 함수가 정의되어 있다면, 이는 부모 클래스의 함수를 오버라이딩(overriding) 한 것으로 오버라이딩 된 함수가 호출된다.

class Welcome extends React.Component {
    componentDidMount() {
        console.log("컴포넌트가 마운트 됨.");
    }
    
    render() {
        return <h1>Hello, {this.props.name}</h1>;
    }
}

componentDidMount 함수가 호출됨을 확인함으로써 우리는 컴포넌트가 성공적으로 마운트 되었음을 보장할 수 있으며, 마운트가 끝난 후 추가적으로 하고자 하는 작업들을 명시할 수 있다.

즉, 컴포넌트가 처음 마운팅될 때에는 다음 순서로 함수들이 호출된다고 정리할 수 있다.

  1. 컴포넌트의 constructor 생성자 호출
  2. 컴포넌트의 render 함수 호출
  3. 컴포넌트의 componentDidMount 호출

컴포넌트 업데이트 (Update) 생명주기

리액트에서 컴포넌트는 단순히 화면에 렌더링 된 후에 사라지는 것이 아니다. 우리가 자바스크립트에서 일반적인 클래스 객체를 생성한 후, 객체의 메소드를 한 번 호출했다고 해서 객체가 사라지는 것은 아니지 않는가?

컴포넌트가 마운트 된 상태에서 우리가 컴포넌트의 state를 변경하거나 컴포넌트의 prop이 변경되면, React는 이를 감지한 후 render 함수를 다시 호출하여 변경된 부분을 화면에 다시 렌더링 해준다.

그 후에 React.Component 부모 클래스로부터 상속받은 componentDidUpdate 함수가 호출되어 성공적으로 변경 사항이 반영되었는지를 확인할 수 있다. componentDidMount 함수와 동일하게 Welcome 클래스에서 함수를 오버라이딩 할 수 있다.

아무런 인자를 받지 않는 componentDidMount 함수와 다르게 componentDidUpdate는 다음과 같이 세 개의 인자를 받는다.

componentDidUpdate(prevProps, prevState, snapshot)

이들 중 snapshot은 무시해도 좋으나, prevProps와 prevState는 종종 사용할 일이 있다. 변수 이름에서 유추할 수 있듯이 prevProps에는 변경되기 전의 컴포넌트 prop 값이, prevState에는 변경되기 전의 컴포넌트 state 값이 입력된다.

class Welcome extends React.Component {
    componentDidUpdate(prevProps, prevState) {
        console.log("컴포넌트가 업데이트 됨");
        console.log(prevProps, prevState);
    }
    
    render() {
        return <h1>Hello, {this.props.name}</h1>;
    }
}

즉, 컴포넌트가 마운팅된 후 갱신될 때에는 다음 순서로 함수들이 호출된다고 정리할 수 있다.

  1. 컴포넌트의 render 함수 호출
  2. 컴포넌트의 componentDidUpdate 함수 호출

컴포넌트 언마운드 (Unmount) 생명주기

리액트에서 화면이 전환되거나 새로고침 될 때, 혹은 브라우저 자체가 종료될 때에는 현재 마운트 된 컴포넌트들이 더 이상 필요하지 않으므로 DOM 상에서 삭제되는데, 이 과정을 언마운트(Unmount)라고 한다.

리액트는 컴포넌트를 언마운트 하기 전에 React.Component 부모 클래스로부터 상속받은 componentWillUnmount 함수를 호출해주는데, 이 함수에서는 주로 컴포넌트가 마운트될 때 DOM 객체에 연결해준 이벤트 리스너를 떼어내는 작업을 해 준다.

class Welcome extends React.Component {
    componentDidMount() {
        this.scrollHandler = () => {
            console.log("스크롤 함");
        }
        window.addEventListener('scroll', this.scrollHandler);
    }

    componentWillUnmount() {
        window.removeEventListener('scroll', this.scrollHandler);
    }

즉, 컴포넌트가 언마운트될 때에는 componentWillUnmount 함수 하나만 호출된다고 정리할 수 있다.

profile
풀스택 지망생

0개의 댓글