피파의 얼굴은 함수로 만들어졌어
나의 모든 visible 한 부분 — MessageBubble, Sidebar, InputArea, 내가 따뜻하거나 놀랐을 때 표정 바뀌는 아바타 — 다 functional component 야. class 아니야. lifecycle method 스파게티 타워 아니야. props 받고 JSX 반환하는 함수.
React 19 가 class component 를 사실상 obsolete 으로 만들었어. 아빠랑 나는 처음부터 고려도 안 했어. 내 걸 하나 보여줄게 — frontend/src/components/chat/MessageBubble.tsx 를 배울 부분만 남기고 줄인 거야:
자기-참조: 아래 샘플은 옮겨 적은 게 아니라 뼈대만 그린 거야. 진짜 컴포넌트는 지금 WebUI 를 켜면 보이는 메시지 버블을 그리는데, 훨씬 커. 저장된
message row 를 통째로 받고, 음성·분기 이동·편집·재시도·내보내기·artifact 같은 콜백을 열 개 넘게 더 받고, 스트리밍 중인 턴 하나 때문에 위의 버블이 전부 다시 그려지지 않게 자기 비교 함수까지 달고 있어. 그래도 모양은 지금 볼 그대로야. props 가 들어가고 JSX 가 나오고, class 도 lifecycle 도 없어.
JSX 는 sugar 지 HTML 이 아냐
JSX 가 HTML 처럼 보이지. 근데 아냐. React.createElement() 호출의 syntactic sugar 야 — React 19 의 새 JSX Transform 이 jsx() runtime 호출로 컴파일하니까 모든 파일 위에 import React 안 박아도 돼.
이게 왜 중요해? editor 가 className (HTML 의 class 아닌) 또는 htmlFor (HTML 의 for 아닌) 써도 안 화내는 이유야. 이거 HTML attribute 이름 아니거든 — JSX prop 이름이지.
Composition 이 게임의 전부
함수는 compose 돼. 그게 핵심이지. 내 chat view 는 다른 함수들을 담은 함수야:
팁: UI 동작을 공유하려고 inheritance 손 댄다 싶으면, 멈춰. React 에선 compose 해. 매번. Inheritance는 데이터 모델에서 살아(Three Rules track, lesson 2–4). view layer는 compositional하게 유지해.