pile·
프론트엔드·vercel-blogVercel Blog·

React 18이 애플리케이션 성능을 개선하는 방법

React 18이 도입한 동시 렌더링이 웹 성능 지표(Total Blocking Time, INP)를 개선하는 원리를 다룬다. 기존 동기식 렌더링은 모두-아니면-무(all-or-nothing) 방식으로 메인 스레드를 차단했는데, React 18은 렌더링을 5ms 단위로 쪼개 더 긴급한 작업을 먼저 처리할 수 있게 했다.

핵심 포인트
  • Long Task(50ms 초과)는 메인 스레드를 차단해 INP를 높이고 사용자 반응성을 떨어뜨린다.
  • useTransition으로 상태 업데이트를 낮은 우선순위로 표시하면 React가 5ms마다 스케줄러를 확인하며 긴급한 작업을 먼저 처리한다.
  • React Server Components는 클라이언트 번들에서 서버 전용 코드를 제거하고 DB에 직접 접근해 별도 API 레이어를 없앤다.
  • Suspense로 로딩 중인 컴포넌트 대신 다른 트리를 렌더하다가 완료 후 교체해 체감 성능을 높인다.
  • cache() 함수는 같은 렌더 패스 내 중복 호출을 메모이제이션하고, fetch()도 자동 캐싱을 지원한다.
상세 정리
  • 성능 지표 맥락: FCP와 TTI 사이의 Total Blocking Time(TBT)과 인터랙션부터 화면 업데이트까지의 INP(Interaction to Next Paint)가 핵심 지표다.
  • 기존 문제: 동기식 렌더링은 시작 후 완료까지 메인 스레드를 점유한다. 50ms가 넘으면 Long Task로 분류되어 그 동안 사용자 입력이 차단된다.
  • useTransition 동작 원리: startTransition으로 래핑된 업데이트는 중단 가능으로 표시되고, React 스케줄러가 5ms마다 더 높은 우선순위 작업(사용자 입력 등)을 확인해 먼저 처리한다.
  • useTransition 실증: 도시 필터링 데모에서 총 차단 시간이 4425.40ms에서 대폭 감소했다. 사용자 입력이 즉시 반응하고 필터링은 백그라운드에서 진행된다.
  • RSC 원리: "use client" 지시어로 클라이언트에서만 실행할 컴포넌트를 명시한다. 나머지는 서버에서 실행되어 클라이언트 번들에 포함되지 않는다.
  • RSC 데이터 접근: 서버 컴포넌트는 DB에 직접 쿼리 가능하다. 직렬화된 컴포넌트 트리를 클라이언트로 전송하기 때문에 별도 API 엔드포인트가 불필요하다.
  • Suspense 확장: 특정 컴포넌트가 데이터 로딩 중일 때 React가 해당 컴포넌트 대신 다른 트리를 렌더하다가, 로딩이 완료되면 교체한다. 사용자에게 점진적으로 콘텐츠를 보여줄 수 있다.
  • cache() 함수: 동일 렌더 패스 내에서 같은 함수 인수로 호출된 결과를 메모이제이션한다. 여러 컴포넌트가 같은 데이터를 요청해도 실제 실행은 1회다.
  • fetch() 자동 캐싱: React 통합 환경에서 fetch() 호출은 자동으로 캐시되어 같은 URL 중복 요청을 제거한다.
  • 전체 그림: 동시 렌더링(Transitions) + 서버 렌더링 최적화(RSC) + 선언적 로딩 상태(Suspense) + 데이터 캐싱이 합쳐져 성능을 높인다.
왜 읽나React 18 concurrent 기능을 실제 성능 지표와 연결해 이해하려는 프론트엔드 개발자에게 동작 원리부터 최적화 패턴까지 체계적인 레퍼런스.
vercel-blog
Vercel Blog 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    항공 프론트엔드 구축기 (7/10): 창구를 하나만 두었습니다

    여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.

    요약 이어보기
    #react#typescript#webview+2