React와 Three.js를 같은 코드베이스에 넣으면 조용한 충돌이 시작된다. cclank/cell-architecture-studio는...
OnePageDaily·5/17/2026·15 views
React와 Three.js를 같은 코드베이스에 넣으면 조용한 충돌이 시작된다. cclank/cell-architecture-studio는 이 충돌을 정면으로 다루는 프로젝트다 — 세포 구조를 3D로 탐색하는 인터랙티브 갤러리를 TypeScript + React + Three.js 스택으로 구현했고, 생성 일주일도 지나지 않아 GitHub 트렌딩 21위, 616 stars를 기록했다. 비주얼이 화려한 데모가 이 속도로 퍼지는 경우는 드물다. 뒤에 기술적 공감대가 있을 때 숫자가 이렇게 움직인다.
충돌의 본질은 패러다임이다. React는 상태가 UI를 결정한다는 선언형 모델로 작동한다. 컴포넌트는 상태를 소비하고, 상태가 바뀌면 리렌더링이 일어나며, React가 DOM을 알아서 동기화한다. Three.js는 반대다 — 씬 그래프에 오브젝트를 직접 추가·제거하고, `requestAnimationFrame`으로 렌더 루프를 직접 돌리며, 카메라·라이트·메시를 명령형으로 조작한다. 이 두 세계를 한 컴포넌트 안에 합치면, '씬을 업데이트하는 책임'이 React의 렌더 사이클에 있는지, Three.js의 루프에 있는지 경계가 흐려진다. 경계가 흐려지면 stale reference, 이중 렌더, WebGL 컨텍스트 누수가 조용히 쌓인다.
TypeScript가 이 설계에서 단순한 타입 체크 도구 이상의 역할을 할 수 있는 이유가 여기에 있다. Three.js 씬 그래프의 오브젝트 타입(`Object3D`, `BufferGeometry`, `Material`)과 React 컴포넌트의 props 타입을 인터페이스 경계로 분리해서 선언하면, Three.js 인스턴스가 React 상태 안으로 직접 흘러들어가는 패턴을 컴파일 타임에 잡아낼 수 있다. 이 패턴은 직렬화 불가 오류와 참조 오염의 주요 원인이다. 반대로 코드베이스에 `any`가 늘어나기 시작한다면, 두 패러다임 사이의 경계가 무너지고 있다는 신호로 읽어야 한다.
세포 구조라는 도메인 선택은 이 기술 스택의 스트레스 테스트로 흥미롭다. 세포소기관들은 스케일 차이가 크고(핵과 리보솜의 크기 차이는 수십 배), 내부 위계가 명확하며, 씬에 동시에 올라가는 오브젝트 수가 많다. 이런 데이터를 실시간으로 렌더링하려면 instancing 전략, LOD(Level of Detail) 적용 여부, 씬에서 사라지는 오브젝트의 geometry와 material을 언제 dispose할지까지 설계 결정이 쌓인다. R3F(react-three-fiber)가 이 문제들을 이미 추상화해주는 대안이지만, 바닐라 Three.js를 직접 연결한 구현은 그 추상화 아래에서 실제로 무슨 일이 벌어지는지 드러낸다. 사내 렌더링 파이프라인에 Three.js를 통합하거나, 기존 React 앱에 WebGL 씬을 얹어야 하는 상황이라면, 이 구현이 제공하는 투명성은 따로 있다.