Community

Claude Code 소스를 까봤더니, 사실상 React 앱이었습니다.

.tsx 파일이 가득했고, UI layer 전체가 React 컴포넌트와 hook으로 짜여 있었어요. 터미널에서 돌아가는 CLI인데 왜 React를 골랐을지 궁금해서, 자세히 분석해 보았습니다. 먼저 짚어야 할 게 하나 있습니다. React는 DOM 라이브러리가 아닙니다. 우리가 보통 "React"라고 부르는 건 사실 두 부분의 합입니다. - reconciler: JSX를 받아서 tree diff를 계산하는 엔진 - renderer: 그 diff 결과를 실제 출력 매체로 옮기는 어댑터 react-dom은 브라우저 DOM에 그리는 renderer입니다. react-native는 iOS/Android 네이티브 view에 그리는 renderer입니다. Ink는 터미널 character grid에 그리는 renderer입니다. 같은 이 react-dom에선 이 되고, react-native에선 UIView가 되고, Ink에선 터미널 character 영역으로 계산됩니다. JSX, hooks, component composition은 그대로 작동합니다. Claude Code는 react-dom 대신 Ink를 renderer로 골랐을 뿐이었습니다. 그렇다면 왜 굳이 React+Ink였을까요? LLM 응답은 SSE chunk로 100ms마다 나눠 옵니다. 그런데 화면에는 응답 텍스트만 있는 게 아닙니다. - spinner는 100ms마다 회전 - 토큰 카운터는 chunk마다 누적 - 응답은 같은 위치에 매번 덮어쓰기 - 입력창은 별도로 항상 활성 명령형으로 짜면 커서 이동, 줄 지우기, 다시 그리기를 직접 관리해야 합니다. 그 사이에 spinner가 같은 줄을 또 그리면 race condition이 생깁니다. 선언형으로 짜면 한 줄입니다. setText(prev => prev + delta) state 한 줄 바꾸면 reconciler가 이전 tree와 새 tree를 diff하고, 변경된 노드만 다시 그립니다. spinner는 spinner대로, 카운터는 카운터대로, 충돌 없이 자기 state만 갱신합니다. streaming UI에 declarative가 더 잘 맞아서 React를 고른 것이었습니다. 여기까지 따라가면서 깨달은 게 있습니다. 그저 React를 "useState 쓰는 웹 UI 라이브러리"로만 알고 있었다면, Ink라는 시도는 할 수 없었을 겁니다. 터미널 앱은 당연히 blessed나 readline으로 짜는 거라고 생각했을 테니까요. React의 본질이 reconciler + renderer로 분리된 추상화 엔진이라는 걸 이해하면, react-native가 모바일에 적용하고, react-three-fiber가 WebGL에 적용하고, Ink가 터미널에 적용한 게 모두 같은 원리라는 게 보입니다. 표면(API 사용법)이 아니라 본질(설계 철학)을 이해해야 다음 환경에서 응용할 수 있습니다. SQL을 "데이터 조회 언어"로만 알면 SELECT-FROM-WHERE에서 멈추지만, "관계대수의 표현 형식"으로 이해하면 dataflow 언어로도 응용할 수 있습니다. Git을 "버전 관리 도구"로만 알면 commit-push-pull에서 멈추지만, "DAG 기반 콘텐츠 주소 저장소"로 이해하면 Dolt 같은 데이터베이스가 떠오릅니다. Claude Code = React 앱이라는걸 발견했을 때 깨달은건, 깊이 있는 이해를 해야 새로운 응용을 할 수 있다는 것입니다. Enter 한 번 누르면 React 안에서 어떤 단계가 일어나는지, 트릭으로 터미널 스크롤백을 어떻게 보존하는지, 코드 단위로 따라간 내용은 영상에 담았습니다. https://youtu.be/W83jWFwEnTU #AI개발 #ClaudeCode #React #ProductEngineer #프론트엔드 #AIEngineering

알림

알림이 없습니다