이번 시간에는 React의
Concurrent mode
와Suspense
에 대해서 알아보는 시간을 갖도록 하겠습니다.
동시성(Concurrency)은 여러 작업이 동일한 시간 간격 내에서 서로 번갈아가며 실행되는 특성을 의미한다. 꼭 작업들이 동시에 실행되는 것은 아니며, 작은 단위로 작업들을 쪼개서 빠르게 전환하면서 실행되는 방식을 포함한다.
자바스크립트
는 싱글 스레드(Single-threaded)
기반 언어로, 한 번에 하나의 작업만 실행할 수 있다. 그러나, 우리들이 알고 있듯이 자바스크립트는 작업을 나누어 비동기로 처리하여 마치 동시에 작업들이 실행되는 것처럼 흉내낸다.
=> 동시에 실행되는 것처럼 보이지만, 실제로는 작은 작업 단위를 빠르게 전환하면서 실행
UI 업데이트의 우선순위를 더 잘 관리하고 보다 부드러운 사용자 경험을 제공하기 위한 방식이다. 기존 React 렌더링 방식인 동기식(Synchronous) 렌더링과 비교했을 때, Concurrent Mode
는 비동기적으로 렌더링을 수행하여 더 복잡한 UI 요구사항을 효과적으로 처리할 수 있도록 한다.
이전의 React는 기본적으로 단일 스레드에서 동작하며, 렌더링 작업이 크거나 복잡해지면 메인 스레드를 장시간 점유하게 된다.
=> 화면이 멈추거나(lagging), 사용자 인터랙션이 지연되는 문제가 발생.
사용자가 UI와 상호작용(스크롤, 클릭 등)할 때, React의 동기적 렌더링 모델에서는 이미 진행 중인 작업이 완료될 때까지 새 작업을 처리하지 못한다.
=> 사용자 입장에서인터페이스가 "버벅거리는" 현상을 초래하며, 사용자 경험을 저하시키는 문제가 발생.
사용자 인터페이스에서 높은 우선순위를 가진 작업(예: 클릭, 입력)이 생길 때, 기존 작업을 중단하고 높은 우선순위의 작업을 처리할 수 있는 유연성이 요구되기 시작.
동시성을 통해 사용자 경험을 향상시키고, 대규모 애플리케이션에서도 성능과 유연성을 극대화하기 위해
Concurrent Mode
가 등장
1. 작업 우선순위 관리
사용자의 입력(클릭, 스크롤 등)과 같은 긴급한 작업을 고우선으로 처리하고, 긴급하지 않은 작업은 나중으로 미룬다. 렌더링 작업을 중단했다가 다시 시작할 수 있는 "interruptible rendering"을 지원.
2.시간 분할(Time Slicing)
작업을 작은 조각으로 나누어 일정 시간 동안 실행한 후 나머지를 대기시킴으로써, 메인 스레드를 독점하지 않고 다른 작업을 수행할 수 있는 여유를 남긴다. 이로 인해 UI가 더 부드럽게 반응하도록 한다.
3. 유연한 렌더링 중단 및 재개
화면 업데이트 중 사용자의 입력이 발생하면, React는 현재 진행 중인 작업을 중단하고 사용자 상호작용을 먼저 처리한 후, 중단된 작업을 이어서 진행.
4. Suspense와의 통합
Suspense
와 함께 작동하여 비동기 데이터 로딩과 같은 작업이 포함된 UI를 매끄럽게 렌더링한다.
=> 네트워크 요청 결과가 로드되기 전에 로딩 상태를 표시하는 등의 기능을 쉽게 구현할 수 있다.
ReactDOM.createRoot()
를 사용하여 Concurrent Mode
활성화
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
// Concurrent Mode 활성화
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
Suspense
는 아직 렌더링이 준비되지 않은 컴포넌트가 있을 때 로딩 화면을 보여주고, 로딩이 완료되면 렌더링이 준비된 컴포넌트를 보여주는 기능이다. 이를fallback UI
를 제공한다고 한다.
=> UI를 비동기 데이터 로딩과 연결하여 매끄럽게 관리할 수 있게 해주는 기능
Suspense
가 동작하려면 React 18 이상에서 ReactDOM.createRoot()
를 사용해야 한다.
1. Suspense
는 Concurrent Mode
의 일부로 설계
Suspense
는 Concurrent Mode
에서 제공하는 비동기 렌더링 능력을 기반으로 동작한다.
데이터가 준비되지 않은 상태에서 렌더링을 일시적으로 중단하거나, 다른 작업을 먼저 처리하는 Concurrent Mode
의 특성을 활용.
2. 비동기 렌더링 지원
Suspense
는 데이터가 준비될 때까지 UI 업데이트를 지연시키는 역할을 하는데,
Concurrent Mode
가 활성화된 환경에서는 데이터 로딩 동안 UI를 비동기적으로 처리하여 부드럽게 동작하게 만든다.
3. 로딩 상태 처리
Suspense
는 데이터 로딩 중에 fallback UI
를 표시하며, Concurrent Mode
는 이러한 작업이 다른 렌더링 작업과 충돌하지 않도록 조율한다.
예를 들어, 네트워크 지연이 있는 경우에도 다른 UI 작업은 계속 진행될 수 있다.
4. 자원 관리 최적화
Concurrent Mode
는 작업 우선순위를 관리하여 Suspense
에서 발생하는 데이터 로딩 작업을 저우선으로 처리하고, 중요한 사용자 상호작용을 우선 처리할 수 있도록 돕는다.
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./MyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
예: 리스트 데이터를 서버에서 로드하는 동안, 다른 UI는 사용자가 계속 상호작용할 수 있도록 유지.
예: 페이지 전환 시, 새 데이터를 로드하는 동안 로딩 화면을 표시하면서도 이전 UI가 중단되지 않음.
예: 느린 네트워크 환경에서도 화면 깜박임 없이 필요한 데이터를 준비하고 렌더링.
Suspense
는Concurrent Mode
를 활용하여 비동기 작업(데이터 로딩, 코드 스플리팅 등)과 UI 렌더링을 매끄럽게 처리한다.
Concurrent Mode
는Suspense
가 비동기 상태를 효과적으로 관리할 수 있도록 우선순위 조정과 렌더링 작업 분할을 지원한다.
두 기능은 결합하여 사용자 경험을 개선하고, 대규모 애플리케이션에서도 성능을 극대화하는 데 기여합니다.