[React] 변화의 물결, 동시성 렌더링
Table of contents
이 포스트는 React 버전 18.3.1을 기준으로 합니다.
동시성 렌더링은 18 버전부터 정식 도입된 새로운 메커니즘입니다. 이는 아직 불완전하지만, 많은 가능성을 보여주었습니다. Suspense
, useDeferredValue
등이 그 결과물이지요. 하지만 그와 동시에 이전에 없던 많은 문제를 불러왔습니다. 이번 포스트에서는 이것이 어떻게 동작하고, 또 어느 부분이 문제가 되는지 알아보도록 하겠습니다.
어떻게 동작하는가
동시성 적용에 가장 중요한 과제는 작업을 어떻게 분할하느냐일 것입니다. React 개발팀은 유휴 시간을 통해 이 문제를 해결했습니다. 동시성 렌더링은 일반 작업보다 우선순위가 낮은 것으로 평가됩니다. 그래서 곧바로 처리하지 않고 유휴 시간 동안에 이루어지도록 한 것이죠.
동시성 렌더링의 이러한 성격은 시간이 조금 소요되는 작업을 위한 것임을 알 수 있습니다. 즉, 결과가 곧바로 반영되어야 하는 작업은 이것이 필요치 않습니다. 오히려 불필요한 대기 시간을 만들어낼 뿐이지요.
이러한 성격을 나타내듯 동시성 렌더링은 반드시 커밋으로 이어지지 않습니다. 렌더링은 여러 번 반복될 수 있고, 불필요한 렌더링은 커밋되지 않고 폐기될 수 있습니다. 문제는 여기서 발생합니다.
무엇이 이를 위험하게 만드는가
렌더링이 커밋되지 않으면 무슨 문제가 생길까요? React에는 부작용 처리를 위한 별도의 기능이 존재합니다. useEffect
가 대표적인데요. useEffect
에 전달된 콜백은 반드시 커밋 이후 호출(정확히는 페인팅 이후)됩니다.
const state = useMemo(factoryWithSideEffect, deps);
useEffect(() => () => dispose(state), deps);
위 코드에서는 의존성 변경 외의 다른 이유로
useMemo
의 캐시가 무효화되지 않음을 가정합니다. 실제로는 그렇지 않으므로 애초에 잘못된 방법입니다. 자세한 내용은 React 공식 문서를 통해 확인할 수 있습니다.상태 보존의 강력한 보장을 원하는 경우, [React] 당신은 상태를 필요로 하지 않을 것입니다. #2 - 보존(with. useRef) 편을 읽어보세요!
factoryWithSideEffect
는 이름에서도 알 수 있듯이 동작에 부작용을 포함합니다. 따라서 useEffect
를 통해 정리 함수가 호출되도록 하고 있습니다. 기존에는 통할 법한 방법이지만 동시성 기능을 함께 사용한다면 매우 부적절한 방법입니다. 상술했듯이 렌더링은 반드시 커밋으로 이어지지 않습니다. 따라서 factoryWithSideEffect
는 매우 여러 번 호출될 수 있는 데 반해 정리 함수는 단 한 번도 호출되지 않을 수 있습니다.
한 가지 더 유의할 점은 훅의 상태 유지 기능에 관한 것입니다. useState
나 useRef
등의 상태 유지는 마운트 후에 효력을 가집니다. 즉, 마운트되지 않은 상황에서 폐기된 렌더링에 대해 상태를 유지하지 않습니다.
이 외에도 일부 기능은 동시성에 특히 취약할 수 있습니다. 대표적으로 useMemo
는 마운트 후 상황일지라도 폐기된 렌더링에 대해 캐시를 유지하지 않습니다. 전체 목록은 React 공식 문서 중 StrictMode
에서 두 번 호출되는 함수 목록과 동일합니다.
첨언하자면 동시성 렌더링 상황을 시뮬레이션하는 기능인
StrictMode
에서는 마운트 시 첫 번째 렌더링은 폐기되고, 두 번째 렌더링만 두 번 커밋됩니다. 한 번의 렌더링을 두 번 커밋하는 상황이므로 버그인 것으로 보이지만 확실한 정보를 확인하지 못했습니다. 따라서 조금 비정상적으로 보일지라도 의도한 동작일 수 있습니다. 만약 의도한 동작일 경우, 프로덕션 환경에서도 발생할 수 있다는 의미가 됩니다. 현재로써는 렌더링과 커밋의 관계를 N:M(N >= 1, M >= 0)으로 상정해야 합니다.
읽어주셔서 감사합니다!
묻고 답하기
개인적인 판단에 의해 적절하다고 여겨지는 경우, 모두가 볼 수 있도록 이곳에 문답이 추가됩니다. 그렇지 않더라도 질문에 대한 답변은 별도로 이루어집니다.
Subscribe to my newsletter
Read articles from 고라니드로 directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by