🏃‍♀️React 컴포넌트 | LifeCycle (라이프 사이클, 생명주기 메서드)

    반응형

    안녕하세요

    오늘은 리액트의 클래스형 컴포넌트에서만 사용할 수 있는

    LifeCycle에대해 내용을 정리하려고 합니다

    벨로퍼트님 강의를 토대로 제가 여기저기 살을 덧붙혀서 작성을 하려고 합니다!

     

     

     


     

     

    1. React LifeCycle란?

    리액트 공식 홈페이지

    React에서 컴포넌트는 여러 종류의 "생명주기 메서드"를 가지며 이 메서드를 오버라이딩(상속하여 재정의)하여 특정 시점에 코드가 실행되도록 설정할 수 있습니다
    출처:https://ko.reactjs.org/docs/react-component.html

    💥 여러분! 이 LifeCycle은 클래스형 컴포넌트에만 해당되는 내용입니다!

    (사실 저는 헷갈리는게 어디서는 LifeCycle API라고 하고 어디서는 LifeCycle Method라고 하고.. 어디는 LifeCycle Event 라고 하고... 어떤게 확실한 명칭인가요? 😂 공식 홈에서 메서드라고 하는거보면 Method가 맞는건가요..? 아님 걍 다 같은 뜻...? 누가 알려주세요...)

    라이프 사이클은 컴포넌트가 브라우저상에 나타나고, 업데이트 되고, 사라지게 될 때 호출되는 메서드들 입니다

    그럼 함수 컴포넌트는 어떻게 해야할까요?

    함수 컴포넌트는  v16.8 업데이트 이후 Hook 기능이 생기면서 해결되었다고 합니다

    (useEffect 랑 비슷하다고 생각하면 됩니다만 작동 방식은 매우 다릅니다)

     

     

     

     

    2. 컴포넌트가 브라우저상에 나타날 때 (Mounting, 생성)

    컴포넌트가 인스턴스로 생성되어 DOM 트리에 삽입되어 브라우저상에 나타나는 것

    👉 인스턴스?

    인스턴스를 쉽게 설명하자면 비슷한 성질(?)을 가진 여러개의 객체(오브젝트)를 만들기 위해서 생성자 함수, Constructor를 만들어 찍어내듯이 사용하는데 이렇게 생성된 객체를 인스턴스라 부를 수 있습니다.
    객체지향언어에서 흔히 사용되는 클래스(Class)가 자바스크립트에서는 프로토타입(prototype)이며 생성자 함수가 사용됩니다. 다시 말하면 클래스나 프로토타입을 사용하여 만들어 낸 것이 인스턴스라고 볼 수 있습니다.
    출처:블로그

    인스턴스라는 말을 처음 들어서 검색해봤습니다

    저같은 초짜에게는 어려운 프로그래밍 용어 같은데😭

    라이프 사이클은 클래스형 컴포넌트에만 해당된다고 했죠?

    클래스로 선언된 컴포넌트들만 인스턴스를 가질 수 있다고 합니다 

    그걸 컴포넌트 인스턴스(Component Instance)라고 부른다고 합니다!!!

    함수 컴포넌트에서는 인스턴스를 갖지 않는다고 합니다

     

    • constructor

    생성자 메서드. 브라우저상에 나타날때 만들어지는 과정에서 가장 처음 실행되는 함수입니다

    constructor(props) {
        super(props);
    }

    this.state의 초기값 설정이라든가 인스턴스에 이벤트 처리 메서드를 바인딩하기 위해 사용합니다

    super(props)를 가장 먼저 호출해야합니다 

     

    • static getDerivedStateFromProps

    props로 받은 값을 state에다가 넣어주고 싶을때 사용합니다

      static getDerivedStateFromProps(nextProps, prevState) {    
                if (prevState.value !== nextProps.value) {      
                            return {        
                                 value: nextProps.value,      
                       };    
                }    
         //   변경할 사항이 없거나 아무것도 안할때는    
           return null; 
     }

    state를 갱신하기 위한 객체를 반환하거나

    null으 반환하여 아무것도 개인하지 않을 수 있습니다

    이 메서드는 컴포넌트가 처음 렌더링 되기 전에도 호출 되고

    그 이후 리렌더링 되기 전에도 매번 실행됩니다

    쓸 일이 거의 없는 메서드이며 리액트 공식 홈에도 아주 드믄 사용례라고 말하군요😁

    자세한건 리액트 공식 홈페이지 참고하시면 좋을 것 같습니다

     

    • render

    클래스형 컴포넌트에서 반드시 써야하는 메서드이죠!

    render() {
         ....
    }

    컴포넌트를 렌더링하는 메서드입니다😊

     

    • componentDidMount

    컴포넌트가 생성된 직후, 트리에 삽입된 직후에 호출됩니다

    이 메서드가 호출되는 시점에는 우리가 만든 컴포넌트가 화면에 나타난 상태입니다

    componentDidMount() {    
            console.log("componentDidMount");  
    }

    예를 들어 외부 라이브러리를 사용하여 특정 DOM에다가 차트를 그릴때,

    컴포넌트에서 필요로하는 데이터 요청(AJAX)을 하거나 DOM의 속성을 읽거나 직접 변경하는 작업을 할 때 등!

    브라우저에 나타는 시점에 무슨 작업을 하고 싶을때 사용하시면 됩니다!

     

     

     

     

    3. 컴포넌트를 업데이트 할 때 (Updating)

    컴포넌트 props 또는 state가 바뀌었을 때

    • static getDerivedStateFromProps - 위에 Mounting에서 등장했던 이 메서드도 업데이트에서 호출이 됩니다

     

    • shouldComponentUpdate

    컴포넌트가 리렌더링을 할지 말지 결정하는 메서드입니다 

    props 또는 state가 새로운 값으로 갱신되어 렌더링이 발생하기 직전에 호출됩니다

    * 예제 *

        // 특정 조건에 따라 rendering을 막아주는 함수다

      shouldComponentUpdate(nextProps, nextState) {

               // 10 만 render가 안됨

               if (nextProps.value === 10) return false;

               return true;

      }

    컴포넌트를 최적화하는 작업에서 매우 유용합니다! 목표는 오직 성능 최적화라고 합니다😁

    리액트 공식 홈에서는 이 메서드 대신 PureComponent를 사용하는 것이 좋다고 합니다

     

    • render - 위에 Mounting에서 등장했던 이 메서드도 업데이트에서 호출이 됩니다

     

    • getSnapshotBeforeUpdate

    render 메서드 호출 후 브라우저에 나타나기 바로 직전에 호출되는 메서드입니다

    예를 들어 브라우저에 그리기 전에 스크롤의 위치, DOM의 크기를 사전에 알고 싶을 때,

    업데이트 되기 직전에 DOM 함수를 return 시켜가지고

    그 return된 값을 componentDidUpdate에서 받을 수 있습니다

    발생 시점 : render() 👉 getSnapshotBeforeUpdate 👉 DOM에 변화 반영 👉 componentDidUpdate

    이 메서드는 사용할 일이 별로 없습니다

    그러나 함수 컴포넌트, Hook을 사용할 때에는 이 메서드를 대체할 수 있는 기능이 아직 없다고 합니다

    (예제가 꽤 길어서 codesandbox.io/s/484zvr87ow?file=/src/index.js 로 사용 예제 확인해보시면 되겠습니다 😊)

     

    • componentDidUpdate

    리렌더링을 완료한 후 실행되는 메서드입니다

    화면에 우리가 원하는 변화가 모두 반영되고 난 뒤 호출이 됩니다

    컴포넌트가 업데이트 되었을 시에 DOM을 조작하기 위해 사용하거나

    이전과 현재의 props를 비교하여 네트워크 요청을 보내는 작업을 할 때 유용합니다

    1
    2
    3
    4
    5
    6
    componentDidUpdate(prevProps) {
      // props 비교를 잊지 마세요
      if (this.props.userID !== prevProps.userID) {
        this.fetchData(this.props.userID);
      }
    }
    cs

    💥 이 메서드에서 setState를 사용하면 무한 렌더링이 될 수 있습니다(꼭 조건문으로 감싸야함)!

     

     

     

     

    4. 컴포넌트가 브라우저상에서 사라질때(Unmounting, 제거) 

    • componentWillUnmount

    컴포넌트가 화면에서 사라지기 직전에 호출되는 메서드

    componentWillUnmount() {
             console.log("componentWillUnmount");
    }

    주로 DOM에 직접 등록했었던 이벤트를 제거하거나

    setTimeout이 있다면 타이머를 제거, 외부 라이브러리 인스턴스를 제거하기 위해 사용합니다

     

     

     

     

    ✅ 컴포넌트 에러가 발생했을때

    • componentDidCatch

    render 함수에서 에러가 날 때, 에러가 발생할 수 있는 컴포넌트의 부모 컴포넌트에서 작업해줘야 합니다

    사용자한테는 에러 페이지를 띄우고 뒷단에서는 에러 내용을 서버에 보내는 작업을 합니다

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     state = {
        error: false,
      };
     
     componentDidCatch(error, info) {
        this.setState({
          error: true,
        });
      }
     
      render() {
        if (this.state.error) {
          return <h1>에러가 났어요</h1>;
        }
        return (
          //...
        );
      }
    cs

     

     

     

     

     

    👩‍💻 마무리

    사실 클래스형 컴포넌트를 쓰게 되는 일 자체가 이제는 별로 없게 되다보니

    이 내용을 굳이 꼼꼼하게 다룰 필요는 없다고는 합니다만...!!!

    제가 React를 공부하고 React Native를 작업해보면서

    생각보다 라이브러리 예제로 이렇게 작성된게 많았습니다

    저는 노마드 아카데미를 통해 함수 컴포넌트 위주로 작성했던터라

    constructor를 마주쳤을때 매우 당황했었어요

    그냥 진짜... 분명 같은 리액트인데 저렇게 작성된거 보면 매우 멘붕 터졌던 기억이...

    그리고 실무를 해보면서 느끼는거지만

    지금 잘 안쓴다고 굳이 알 필요가 없다 라는 말은 프로그래밍에선 없는 것 같습니다

    효율성을 위해 공부량의 차이를 둘 뿐..... 이 또한 리액트를 쓸 사람이라면

    꼭꼭꼭꼭 알아둬야할 내용이라고 생각합니다

    반응형

    댓글