React로 개발하는 사람들에게는 useEffect는 아주 익숙한 Hook이다.
페이지 뿌려줄 data를 불러오기 위해 api call해서 data set하기도 하고
useEffect(() => {
const getData = async () => {
const res = await getData();
setData(res);
};
getData();
}, []);
store에 있는 값을 체크해 페이지 이동을 하기도 하고
useEffect(() => {
if (!storeValue) {
history.goBack();
}
}, []);
처음 페이지가 떴을 때 스크롤의 위치를 셋팅하기도 한다.
useEffect(() => {
window.scrollTo({
top: 0,
behavior: "auto",
});
}, []);
그런데 useEffect를 useLayoutEffect바꿔서 사용해도 우리 눈에는 페이지가 똑같이 보이는데 무엇이 다른걸까?
우선 그 차이를 알기 위해서는 React에서 render와 paint개념을 알아야한다.
- render : DOM Tree 를 구성하기 위해 각 엘리먼트의 스타일 속성을 계산하는 과정
- paint : 실제 스크린에 Layout을 표시하고 업데이트하는 과정
render는 paint전에 DOM Tree를 구성하고 계산하는 과정. 즉, paint의 준비 단계라고 볼 수 있겠다.
그렇다면 당연히 순서는 render(준비) -> paint(화면에서 보임) 순일 것이다.
useEffect
우선 useEffect는 아래 이미지처럼
render -> paint -> useEffect 순으로 실행된다.
paint가 되고 우리 눈에 다 보이는 상태에서 useEffect가 실행된다.
예시가 gif 파일이라 자세히 봐야하는데, value가 업데이트 될 때마다 잠깐 0이었다가 다시 값이 셋팅되는 것을 확인할 수 있다.
숫자가 바로바로 바뀌는 것이 아니라 우리 눈에는 무언가 깜빡이는 것처럼 보인다.
즉, 0으로 paint된 후 useEffect로 다시 value가 업데이트되는 것이다.
UseLayoutEffect
우선 useEffect는 아래 이미지처럼
render -> UseLayoutEffect -> paint 순으로 실행된다.
useEffect와 달리 훅이 먼저 실행되고 paint되어 우리 눈에 보이게 된다.
useEffect 예시와 달리 value가 업데이트 될 때마다 숫자가 바로바로 깔끔하게 업데이트 되는 것을 확인할 수 있다.
UseLayoutEffect이 paint보다 먼저 실행되어 0이 보이기 전 값을 셋팅하기 때문이다.
예시 코드 직접 확인하기
결론
대부분의 경우 useEffect를 사용하지만 경우에 따라 구성 요소가 표시될 때 깜박이는 것을 보고 useLayoutEffect로 전환할 수 있다. 그러나 useLayoutEffect는 동기식이므로 성능이 저하될 수 있어 사용할 때 주의해야한다. 이 메서드 실행이 완료될 때까지 UI가 업데이트되지 않기 때문이다.
useEffect를 쓰되 구성 요소가 표시될 때 깜박이는 것이 유저가 불편할 정도로 눈에 띈다면 useLayoutEffect를 적용해볼 수 있겠다. 그러나 useLayoutEffect 에서 실행되는 메서드가 오래 걸리는 메서드라면 화면에 paint가 바로 일어나지 않아 스크린에서 UI를 빠르게 볼 수 없을 수 있으니 이 사항들을 고려하여 선택 사용하면 좋을 것 같다.
출처 : What is the real difference between React useEffect and useLayoutEffect?
'Developer > React' 카테고리의 다른 글
리액트에서 DOM 사이즈 줄이는 최적화 방법 (0) | 2024.01.10 |
---|---|
리액트에서 라이브러리없이 간단하게 이미지 최적화하기 (2) | 2024.01.03 |
React Clean Code 를 위한 팁 (0) | 2022.09.04 |
Cannot use JSX unless the '--jsx' flag is provided.ts(17004) 빨간줄 없애기 (0) | 2022.02.09 |
커스텀 훅 기본 형태 예제 (0) | 2022.01.01 |