useEffect vs. useLayoutEffect

Keun·2022년 7월 1일
1

useEffect를 제일 많이쓰고, useLayoutEffect는 한번도 안써봄..

아니글쎄, 내가 어제, 가고싶었던 회사 면접을 봤는데...아니글쎄...나는 생각지도 못한질문을 듣게된다.

Q: useEffect와 useLayoutEffect 차이를 혹시 알고계신가요?

면접관님께서 물어보시는데...하아...순간...와 어디서 보긴했는데...

우선 내 성격상 솔직히 말씀은 드렸다..

render 와 paint 두가지가 있는데...순서가 다른 것으로 알고있습니다...

라고 말씀드리고 각각 설명하고...

Q: 어느 상황에 쓰시나요?

면접이라 긴장되는상황에 또 물어보시는데 하아...사실 써보진 않았다고 솔직히 말씀드리고...

저같으면,, 렌더링 전에 모든것을 보여주고 싶을때 useLayoutEffect...아니면 useEffect....

민오ㅓ림노리ㅗㅁㄴㅇ러ㅣㅏㅗㅇㄴ미ㅓ라ㅗㅁㅇ니ㅓㅏㅗㄹㅁㅇ니ㅏ롱ㅁ니ㅓㅏ롬이너ㅏ롬이나ㅓ롬ㄴ어ㅣㅏ로ㅓㅏㅣ

하아..모르겠다..사실 답은 맞긴하지만, 구체적이지도않고 너무 두리뭉실해서..집에 오는데 기차에서 계속 생각나갖고...

모르면 알아야지..그럼..알아야지 주니어개발자인데 몰라야지...몰라야 정상이지....가 아니고 정신차려 제발. ㅠㅠㅠ

알아야할 것: Side effect

이거 무슨 부작용같이 들리긴 하는데...찾아보니까
"React 컴포넌트가 화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들이라고 한다."

https://www.daleseo.com/react-hooks-use-effect/#:~:text=Side%20Effect%EB%9E%80%3F,Side%20Effect%EB%9D%BC%EA%B3%A0%20%EC%9D%BC%EC%BB%BD%EC%8A%B5%EB%8B%88%EB%8B%A4.

"함수가 실행되면서 함수 외부에 존재하는 값이나 상태를 변경시키는 등의 행위." -> "함수에서 전역변수의 값을 변경하거나 혹은 함수 외부에 존재하는 버튼의 텍스트를 변경하거나, 파일을 쓰거나, 쿠키저장, 네트워크를 통해 데이터 송신하는 것 등. " -> 함수 밖의 비동기처리들?을 사이드 이펙트라고하나보다.

잘 생각해보면 함수 내부에서 뿐만아니라 외부에서도 동작하기 때문에 비용이 많이 들어 보일 수가 있다. 그런데 사실이다. 비용이 많이든다. 자바스크립트는 동기적으로 풀어나가는 프로그래밍에 비동기적인 요소들을 가미한 언어이다. 어쨌든 Side effect가 있는 일이라고 해도, 프로그램을 읽기 어렵게 하고, 실행상태를 예측하기 어렵게하며, 개발비용을 증가시킨다고 보기때문에 최소화 하는 것이 중요하다고 한다. 잘 생각해보면, 우리가 프로젝트를 할 때, 예측 불가능한 부수적인 효과들이 많을경우 앞으로 만들어진 웹앱에 대해서 유지보수가 힘들어지기 때문에 이것을 줄이는 것이 좋다.

이것을 위해서 useEffect가 등장한 것이다. 나는 단순히 useEffect부분에서만 랜더링을 원할경우, 또는 상태가 변할때 랜더링을 하기 원할경우에만 쓰는 것이라고 단순하게 생각했는데 이렇게 보니까 달라보인다.

클래스형 컴포넌트에서 useEffect 훅 정리.

componentDidMount + compnentDidUpdate + componentWillUnmount = useEffect

class Example exgtends Component{
	componentDidMount(){ // 컴포넌트가 마운트 되었을 때 실행되는 코드
    }
    componentDidUpdate(){ // 컴포넌트 리렌더링이 완료되었을 때 실행되는 코드
    }
    componentWiillUnmount(){ // 컴포넌트가 언마운트 되었을 때 실행되는 코드
    }
}

여기서 componentDidMount + componentDidUpdate -> useEffect내에서 함수역할, componentWillUnmount -> 함수 형태로 return 하는 연할.

useEffect(()=>{

	//컴포넌트가 마운트 or 리렌더링이 완료되었을 때 실행되는 코드

    return () => {
    
    //컴포넌트가 언마운트 되었을 때 실행되는 코드
    
    }

}, [state, props, variables]); // 해당 사이드 이펙트 함수의 의존성 배열, 해당 의존성 배열의 요소 값이 변경 되면 useEffect 실행.

React 에서 Side-Effect처리

function UserProfile({name}){
	const message = `${name}님 환영합니다!`; // 함수 반환 값 생성
    
    //Bad!
    document.title = `${name}의 개인정보`; // 함수 외부와 상호작용하는 Side-effect 코드
    
    return <div>{message}</div>
}

여기서 document.title 이것은 함수내에서 생성하는 값이 아닌, 함수의 밖에서 가져온 값이다. 이런 코드가 이ㅏㅆ을 경우에 컴포넌트가 렌더링 될 때마다 프로그램을 지연시키게 될 것이라고 한다. 따라서 이것을 useEffect를 통해서 분리할 수 있도록 지원한다.

function UserProfile({ name }) {
  const message = `${name}님 환영합니다!`;

  //Side-Effect 코드를 UseEffect로 분리
  useEffect(() => {
    document.title = `${name}의 개인정보`; 
  }, [name]);
  return <div>{message}</div>;
}

이렇게하면 코드가 최적화 되고, 컴포넌트 실행속도를 개선 가능하다고 한다.

여기서 잠깐.

이제 뭔지 알았다.

그렇다면, useEffect와 useLayoutEffect의 차이는?

이제 게임 시작이다. 둘이 차이점은 무엇인가. 이름도 비슷비슷하고. 뭔데저거?

Render: DOM Tree를 구성하기 위해 각 엘리먼트의 스타일 속성을 계산하는 과정.
Paint: 실제 스크린에 Layout 을 표시하고 업데이트 하는 과정.

  • Render: DOM Tree를 구성하기 위해 각 엘리먼트의 스타일 속성을 계산하는 과정.
  • Paint: 실제 스크린에 Layout 을 표시하고 업데이트 하는 과정.
    useEffect - 컴포넌트들이 render와 paint된 후 실행. (비동기)
    useLayoutEffect - 컴포넌트들이 render된 후 실행되며, 그 후에 paint가 된다. (동기)
    useEffect는 DOM이 화면에 그려진 이후에 호출된다. useLayoutEffect는 DOM이 화면에 그려지기 전에 호출된다. 따라서 렌더링할 상태가 이펙트 내에서 초기화되어야 할 경우, useLayoutEffect를 활용해야합니다.

친구한테 물어보니 이걸 보내줬다. 무엇인진 대충 알겠으나...흠...

https://pubudu2013101.medium.com/what-is-the-real-difference-between-react-useeffect-and-uselayouteffect-51723096dc19

useEffect

https://pubudu2013101.medium.com/what-is-the-real-difference-between-react-useeffect-and-uselayouteffect-51723096dc19

useLayoutEffect

https://pubudu2013101.medium.com/what-is-the-real-difference-between-react-useeffect-and-uselayouteffect-51723096dc19

구체적인 예가 필요할것같다...

https://guiyomi.tistory.com/m/120

여기 들어가보면 화면의 flickering (깜빡거림) 에대한 예를 제시하고 알려주신다.

useEffect와 같은 경우에는 render 된 후에 paint 와 layout이 다 실행 되고나서 useEffect가 동작한다. 그렇기 때문에, 깜빡거린다.

반면에 깜빡 거림을 없애고 싶다면, paint 일어나기전에 발생하는 useLayoutEffect를 사용하면 된다. 먼저 동작하고 그다음에 paint하고 layout을 그리기 때문이다.

그렇지만.

useLayoutEffect는 동기적으로 실행되고 내부의 코드가 모두 실행된 후 painting 작업을 거친다. 따라서, 로직이 복잡할 경우 사용자가 레이아웃을 보는데까지 시간이 오래걸린다. 그러므로 공식문서에서도 그렇고 왠만하면 useEffect만을 사용하는 것을 권장한다고 한다.

0개의 댓글