티스토리 뷰

어느 날 들어온 요건 하나. 'nextTick 시점에서 실행해주세요.'

vue를 익숙하게 써왔던 나는 vue 프로젝트에서 nextTick을 정말 요긴하게 잘 사용했었는데, 현재 react에서 진행하고 있는 프로젝트에 nextTick을 넣으려니 가만있어보자... 어떻게 표현하는 거였더라?

막히게 되었다. 그래서 정리해본 useEffect와 useLayoutEffect.

사실 실무에서는 useEffect를 압도적이게 많이 사용하긴 했는데, 둘이 어떻게 다른지 한 번 살펴보자-


먼저 nextTick이란 화면이 랜더링 될 때, js의 비동기성 특징으로 접근하고자 하는 DOM을 찾지 못하는 현상을 해결해주는 callBack 함수이다.

updateMessage: function () {
  this.message = '갱신됨'
  console.log(this.$el.textContent) // => '갱신 안됨'
  this.$nextTick(function () {
    console.log(this.$el.textContent) // => '갱신됨'
  })
}

// 출처 : https://kr.vuejs.org/v2/guide/reactivity.html#%EB%B9%84%EB%8F%99%EA%B8%B0-%EA%B0%B1%EC%8B%A0-%ED%81%90

다음과 같은 함수를 실행한다고 가정하다. 기존 문자열이 '갱신 안됨'이라는 this.message에 '갱신됨'이라는 문자를 삽입하였지만 컴포넌트는 즉시로 랜더링 되지 않아 textContent라는 element에 접근하면 여전히 '갱신 안됨'이라는 문구를 캐치한다.

이때, '갱신됨'이라는 문구를 캐치하기 위해서는 nextTick을 사용하면 되는데, 이는 데이터 변경 후, DOM이 업데이트를 마친 즉시 실행되는 함수이다. 고로 업데이트 직후이기 때문에 '갱신됨'이라는 문구를 캐치할 수 있게 된다.

더불어 nextTick은 promise를 반영함으로 ES2017에서는 async/await를 사용하여 같은 동작을 수행할 수 있다.

updateMessage: async function () {
    this.message = '갱신됨'
    console.log(this.$el.textContent) // => '갱신 안됨'
    await this.$nextTick()
    console.log(this.$el.textContent) // => '갱신됨'
}

// 출처 : https://kr.vuejs.org/v2/guide/reactivity.html#%EB%B9%84%EB%8F%99%EA%B8%B0-%EA%B0%B1%EC%8B%A0-%ED%81%90

 


그럼 이쯤에서 다시 생각해보자. 상단의 'nextTick 시점에서 실행해주세요.'라는 말은 어떤 의미일까? nextTick의 의미로 보건데 아마도 DOM이 업데이트된 직후, 업데이트 된 DOM을 찾자마자 실행해주세요.라는 의미일 것이다.

useEffect
useEffect(() => {
	// 실행할 내용
}, []);

useEffect는 하나의 컴포넌트에서 데이터가 변경되었을 때, 컴포넌트의 랜더링이 일어나고 이후 스크린에 그려진 다음 실행되게 된다. 즉, 모든 DOM이 그려지고 난 후에 실행되는 함수라고 생각하면 된다.

useLayoutEffect
useLayoutEffect(() => {
	// 실행할 내용
}, []);

이와 거의 같지만 실행 순서가 조금 다른 useLayoutEffect는 하나의 컴포넌트에서 데이터가 변경되었을 때, 컴포넌트의 랜더링이 일어나고 실행된다. useLayoutEffect가 실행된 이후, 해당 변경 내용들이 스크린에 그려지며 페이지가 완성된다.

즉, useEffect보다 useLayoutEffect가 조금 더 빨리 진행되는 셈이다. 페인팅되기 직전에 무언가 액션을 취해야 한다면 (예를 들어 화면의 깜박임 현상, 혹은 변수가 초기화되었다가 이후 변경되는 현상 등) useLayoutEffect에서 어떠한 조치를 취해주는 것이 하나의 해결 방법이 될 수 있을 것이다.

그런데 왜 실무에서 자주 사용하지 않을까?

실제로 나는 useLayoutEffect의 사용보다 useEffect의 사용을 압도적으로 많이 보았는데, 그 이유가 무엇일까?

바로 '성능' 부분이 얽혀있기 때문이다. useLayoutEffect는 동기식 함수로써, painting 되기 전 해당 함수를 진행하고 마칠 때까지 멈추게 된다. 즉, useLayoutEffect가 실행되는 동안에는 UI가 업데이트되지 않아 성능에 저하가 올 수 있기 때문이다. 일부의 경우에는 해결책이 되겠지만 너무 과한 사용은 서비스의 저하를 가지고 오니 조심해야 하는 부분이다.


이렇게 DOM에 접근할 수 있는 타이밍을 체크하여 vue처럼 직접 nextTick을 쓰지 않더라도 원하는 타이밍에 필요한 로직을 적절하게 배치하여 해결할 수 있었다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함