What you know
1. useEffect
- useEffect는 비동기 함수이다 (충격... 나는 그냥 비동기를 디자인을 흉내낸 일반함수인줄 알았다)
- 따라서, setTimeOut처럼, React DOM을 계산하여 형성하고, 페인트가 마무리가 되는(return부) 시점에 내부에 들어가있는 함수를 실행시킨다
- 이 말인 즉슨, 리엑트가 스크립트를 읽고 DOM 자료구조를 형성하는 과정을 "Blocking" 하지 않는다는 점이다.
- 이 점은 몹시도 유용하지만, 가끔가다가 계산에 있어 원치않는 모습을 보여주기도 한다. 예를들어
해당 코드에는 상태인 "Show"에 따라서 "This is a popup" 이 띄워지는 것을 보여준다.
useEffect는 "Show" 를 체킹하고 있다가, 변화가 일어나면 "button"의 포지션값(getBoundingClientRect()) 을 확인한 후,
"This is a popup" 문구의 위치를 버튼바닥으로부터 25px 움직이게 하는 style attribute를 삽입한다.
자, 여기서 useEffect는 비동기 함수라고 했다. 즉, DOM의 계산이 다 이루어지기 전까지는 실행되지 않는다는 소리고, 이 말인 즉슨 25px 움직이는 행위는 DOM이 작성되는 것이 완료된 후에야 실행된다는 소리다.
그렇기 때문에, "This is a popup" 문구는 우선 DOM 의 초기계산에서 버튼의 바닥부분에 위치하다가, useEffect로 인해 다시 25px 밑으로 위치가 재설저오디는 기괴한 형상을 보여준다.
그럼 이런 괴현상을 어떻게 해결해야 할까?
그것을 바로 useLayoutEffect가 해결해준다
2. useLayoutEffect
- useLayoutEffect는 반 동기적으로 실행된다.
- 여기서 반 동기적으로 실행된다고 표현한 이유는, 완전하게 동기적으로 해당 함수를 처리가 완료한 후에 return 문을 통해 실행되는 것이 아니라, useEffect처럼 비동기적으로 실행은 되지만, DOM의 형성결과과 브라우저에 전달되기 전에 우선 useLayoutEffect의 함수내용을 실행시킨 후의 결과물을 페인팅하기 때문에 그렇다.
- 즉, useLayoutEffect는 무언가 useEffect로 인해 만들어지는 특정 결과를 기준으로 DOM이 계산되길 원할 때에 유용하다.
- 위의 예시에서 useEffect를 useLayoutEffect로 수정할 경우, button의 밑바닥에서 먼저 보인 후 25px만큼 움직이는 것이 아니라 그 DOM의 계산 결과에 대해 함수부분을 또다시 처리한 그 최종 결과물을 브라우저에 전달하여 렌더링하기때문에 브라우저에서 나타나는 최종 결과물은 25px만큼 떨어져 팝업되는 "This is a popup" 이 된다.