AI Briefing

diff 라인을 고성능으로 만드는 험난한 여정

·2026.04.04 01:00

핵심 내용

GitHub는 대형 PR에서 1GB heap과 40만 DOM 노드를 줄이기 위해 diff 라인을 재설계했다.

1 / 2

자세히 보기

GitHub는 Files changed 탭을 React 기반으로 새로 만들며, 대형 pull request에서도 빠르고 안정적인 리뷰 경험을 유지하는 데 집중했다. 최악의 경우 JavaScript heap 1GB 초과, DOM 노드 40만 개 이상, 느린 상호작용과 높은 INP가 문제가 됐다.

핵심 해법은 하나가 아니라 여러 갈래의 최적화였다.

  • v1 diff 라인 구조 단순화: unified view는 라인당 약 10개 DOM 요소, split view는 약 15개 DOM 요소를 쓰고, React 레벨에서도 unified는 최소 8개 컴포넌트, split은 최소 13개 컴포넌트가 필요했다.
  • 컴포넌트 구조 축소: v2에서는 split/unified를 위한 전용 컴포넌트를 분리해 중첩 wrapper를 줄였고, 한 diff line이 8개 컴포넌트에서 2개 수준으로 줄었다.
  • 이벤트 핸들링 단순화: 여러 하위 컴포넌트에 흩어져 있던 이벤트 대신, 상위의 단일 handler가 data-attribute를 보고 처리하도록 바꿨다.
  • 상태 이동과 lookup 최적화: 댓글과 context menu 상태를 조건부 렌더링 자식 컴포넌트로 옮기고, useEffect 사용을 상단으로 제한했으며, Map 기반의 O(1) 조회 구조로 바꿨다.

작은 변경도 누적 효과가 컸다. 예를 들어 line number 셀에서 불필요한 <code> 태그를 제거해 10,000줄 기준 20,000개 DOM 노드를 덜 만들었다. 같은 테스트에서 v1 대비 v2는 총 컴포넌트 렌더링 ~183,504개 → ~50,004개, 메모리 ~150-250MB → ~80-120MB, INP ~450ms → ~100ms로 개선됐다.

가장 큰 PR에는 window virtualization을 도입했다. TanStack Virtual로 화면에 보이는 부분만 DOM에 유지해, p95+ pull request에서 JavaScript heap과 DOM 노드가 10배 감소했고 INP는 275–700+ ms에서 40–80 ms로 낮아졌다.

그 외에도 렌더링 리렌더링 축소, :has(...) 같은 무거운 CSS 선택자 제거, 드래그/리사이즈의 GPU transform 전환, interaction-level INP 추적과 diff-size 세분화, memory tagging을 포함한 Datadog 대시보드, 보이는 diff line만 hydrate하는 서버 렌더링 개선, progressive diff loading과 백그라운드 fetch까지 더해져 대형 PR의 응답성과 메모리 압박을 전반적으로 낮췄다.

이 한국어 요약은 AI가 자동으로 만들었습니다. 원문의 주장과 맥락은 원문에서 확인해 주세요. 저작권은 원저작자에게 있습니다.

AI 처리 방식을 확인하거나, 요약 오류와 출처 표기 문제, 삭제 요청을 문의 · 건의로 알려주세요.