React Lifecycle

박재현·2024년 2월 20일
1

diagram: https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

Render와 Commit에 이어서 React의 Lifecycle을 살펴보려고 한다.

그림도 친절하니 잘 따라가보면서 확인해보면 되지싶다.

먼저 라이프사이클은 크게 3가지의 섹션으로 나뉘는데,

  • Mounting: Component가 생성될때 1번 실행된다(html에 올라갈때)
  • Updating: Component가 변경될때마다 실행된다
  • Unmounting: Component가 소멸되려고 할때 한번 실행된다

동시에 Lifecycle동안 지속적으로 실행되는 3개의 주기(phase)가 있는데,

  • Render phase: 변경사항을 계산하는데 사용된다. 이 단계에서 중단되면 DOM이 업데이트 되지 않는다. (당연하겠지? commit phase까지 못가니까?) 그리고 이 영역에서는 side effect가 없고 리액트에 의해서 멈출수도 있고 중단될수도 있고 재시작될수도 있는 상태다.

  • Pre-commit phase: 실제 DOM에 적용되기 이전에 VDOM(버츄얼돔)에 대한 변경사항을 읽을 수 있는 기간(이라는데 VDOM이 잘 이해가 안가서 더 찾아봐야할듯🥲)

  • Commit phase: 여기서 드디어 변경사항이 적용되고, side effect들이 triggered된다. 또 DOM하고 함께 일할수 있고 업데이트 스케쥴을 잡는다. (중요함, side effect는 commit pahse에서만 실행된다)

다음으로 각 섹션(Mounting, Updating, Unmounting)에 대해서 흐름대로 뜯어보자

Mounting 영역

Component가 html문서에 올라갈때를 마운팅이라고 볼 수 있겠쥐?

constructor(props)

생성자!

React 컴포넌트의 생성자는 해당 컴포넌트가 마운트되기 전에 호출된다.

getDerivedStateFromProps(props, state)

get은 가지고 오는거고, derived는 파생된 이라는 의미이다.
그니까 props로부터 파생된 상태들을 가지고 오는 함수다.

그리고 이 함수는 Mounting 영역과 Updating 영역에서도 사용되는 함수임(위 그림에서 보듯이)

마운팅 영역에서의 getDerivedStateFromProps는 초기상태라고 생각하면 된다.

초기에 전달해준 props나, initial state로 전달해준 값들(useState)

render()

각각의 Component에서 return에 해당하는 영역이 바로 render 영억이다.

React updates DOM and refs

리액트에서 렌더링된 내용을 바탕으로 DOM을 업데이트 해주고, html을 직접적으로 참조하고 있는 ref들이 있다면 업데이트 해준다.

componentDidMount()

컴포넌트가 마운트된 직후, 즉 트리에 삽입된 직후에 호출되고, 일반적으로는 side effect를 트리거하는데 사용된다. (useEffect, setState같은 것들이겠지) 왜냐하면 이 부분은 commit phase 이니까.

결과적으로 마운팅 영역에서는 render phase 1번, commit phase도 1번 발생한다.

Updating 영역

updating 영역이 re-rendering과 관련이 있겠쥐?

Mounting 영역의 componentDidMount가 호출된 이후 useEffect의 dependency array에 의해서 state chanaged가 야기되어서 side effect가 발생될때(그래서 이름도 useEffect임) updating 영역이 호출될 수 있겠다.

당연하게도 상태변화를 야기시키는 경로는 여러가지이기 때문에 자주 호출이 된다.

getDerivedStateFromProps(props, state)

  • New props: prop이 변경되거나 새로운 prop이 생길때마다 업데이트가 트리거 된다
  • setState(): 컴포넌트내의 state가 변경될때 업데이트가 트리거된다
  • forceUpdate(): 이전의 변경사항 없이 컴포넌트를 강제로 업데이트 트리거 시킨다

shouldComponentUpdate(nextProps, nextState)

결과적으로 New props, setState(), forceUpdate() 이 세가지 값이 합쳐져서 도합된 상태값들의 리스트가 만들어 진다.

이걸 바탕으로 현재 state 또는 props의 변화가 컴포넌트의 출력 결과에 영향을 미치는지 여부를 판단한다. (기본값은 true)

따라서 상태값들이 변경이 되면 render가 호출이되고, 상태값들이 변경되지 않았다면 render는 호출되지 않는다.

getSnapshotBeforeUpdate()

가장 마지막으로 렌더링된 결과가 DOM에 반영되기 이전에 호출되는데, update되기 이전의 snapshot을 바탕으로 비교해 re-render 되어야할 정보를 얻는다

React updates DOM and refs

re-rendering 되어야할 부분과, ref 참조관계를 업데이트

componentDidUpdate()
업데이트가 일어난 직후에 호출된다. 또 이전과 현재의 props를 비교해 네트워크 요청을 보내는 작업도 이루어 진다.

그래서 예를들어 render phase 2번 발생하고 commit phase가 1번만 있었다 라고 하면 updating 영역에서 shouldComponentUpdate 함수에서 false였다고 유추할 수 있겠다. (즉 re-render는 되지 않았을 것)

그리고 무한루프나 불필요하게 많은 렌더링이 생기는것은 componentDidUpdate에서 side effect가 실행이 되어서, 다시 update를 위해서 getDerivedStateFromProps -> shouldComponentUpdate -> render가 계속 반복이 된다😱

그럼 이 부분은 render phase이기 때문에 위에서 말한것 처럼 리액트에 의해서 느려질 수 있고, 중단될 수 있고, 재시작이 될 수 있다.

profile
기술만 좋은 S급이 아니라, 태도가 좋은 A급이 되자

0개의 댓글

관련 채용 정보