여기 아주 간단한 코드가 있다.
import React, { useState } from 'react';
function CounterButton() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<button onClick={handleClick}>Count: {count}</button>
</div>
);
}
export default CounterButton;
누군가 '버튼을 누르면 무슨 일이 벌어지나요?' 라고 물으면, 다음과 같이 쉽게 대답할 수 있다.
"버튼을 누르면 count 상태가 1씩 증가합니다."
(아마도) 군더더기 없는 설명이다.
한편, 이렇게 대답할 수도 있다.
"버튼을 누르면 onClick 핸들러가 실행되고, setCount 함수가 호출되어 count 값을 1 증가시킵니다."
약간의 디테일을 추구하는 동기에게 같은 질문을 했다고 치자. 그 동기는 이렇게 대답할 수도 있다.
"버튼 click 이벤트가 발생하면, React가 이벤트를 감지하고, 등록된 onClick 핸들러를 호출합니다. setCount를 호출하면 React 내부에서 상태 업데이트가 예약되고, 이후 컴포넌트가 다시 렌더링됩니다."
같은 코드를 두고 같은 질문을 했는데 다른 답변이 나온다.
나를 포함한 대부분 주니어 개발자는 저 정도 범위 내에서 답변할 것 같다.
그렇다면, 그나마 디테일했던 세번째 대답이 과연 '버튼을 누르면 무슨 일이 벌어지나요?' 라는 질문에 대한 정확한 답일까?
'버튼 클릭과 상태 업데이트'라는 간단해보이는 동작 기저에는 다음과 같은 layer가 작동하고 있다.
1. 애플리케이션 레벨 (React, Vue 등 라이브러리/프레임워크)
2. 웹 플랫폼 레벨 (JavaScript, HTML, CSS, 브라우저 API)
3. 브라우저 엔진 레벨 (렌더링 엔진, JS 엔진, 이벤트 루프)
4. 네트워크 레벨 (HTTP/HTTPS, DNS, 서버 통신)
5. 가상 머신 레벨 (JIT, 가비지 컬렉션)
6. OS 레벨 (프로세스 관리, 네트워크 스택, 메모리)
7. 하드웨어 레벨 (CPU, GPU, RAM, 디스플레이)
우리는 사실 굉장히 추상화된 레벨 위에서 답변하고 있는 것이다.
이 모든 레벨을 아울러 각 연결 지점을 물흐르듯 설명할 수 있는 사람은 흔치 않을 것이다.
만약 나에게 각잡고 설명해보라고 하면 제대로 답변하지 못할 것 같다.
이처럼, 무언가를 '정확하게' 이해한다는 것은 굉장히 어려운 일이다.
(사실 더 깊게 내려간다고 하면 끝도 없이 가야하지만(우주의 시작까지), 그건 이미 공학의 영역이 아니다.)
GPT에게 위 질문에 대한 대답을 단계적으로 구체화해달라고 하니 다음과 같은 답변을 해주었다.
부정확한 내용이 포함되어 있을 수도 있지만, 스스로 많은 반성을 하게 되는 답변들이다.
Q. 버튼을 누르면 무슨 일이 벌어지나요?
Level 1
"React는 브라우저의 기본 DOM 이벤트 시스템을 추상화하여, 모든 이벤트를 SyntheticEvent로 처리합니다. 버튼을 클릭하면 React가 onClick 핸들러를 호출하고, 상태 변경(setCount)을 예약합니다. 상태가 업데이트되면 React는 가상 DOM을 통해 변경 사항을 비교하고, 필요한 부분만 실제 DOM에 반영합니다."
- React의 SyntheticEvent 메커니즘 언급 (React가 이벤트를 통합 관리).
- 가상 DOM과 DOM 업데이트 최적화 과정을 설명.
Level 2
"브라우저는 버튼 클릭 시 기본 DOM 이벤트를 생성하고, React는 이 이벤트를 캡쳐하여 SyntheticEvent로 변환합니다. React의 Event dispatcher는 onClick 핸들러를 호출하고, JavaScript의 이벤트 루프를 통해 상태 업데이트 함수(setCount)를 실행합니다. 이 과정에서 가상 DOM을 사용해 변화된 상태를 반영하고, DOM 조작이 효율적으로 이루어지도록 reconciliation 과정을 수행합니다."
- 브라우저의 이벤트 생성 → React의 이벤트 변환 흐름을 구체적으로 설명.
- React의 reconciliation 과정과 DOM 업데이트 최적화 메커니즘 소개.
- JavaScript의 이벤트 루프 언급(비동기 실행 관점).
Level 3
"버튼 클릭은 브라우저에서 마우스 클릭 입력을 감지하여 이벤트를 생성합니다. 브라우저의 이벤트 루프가 이 이벤트를 Event Queue에 넣고, React의 SyntheticEvent 시스템이 이를 캡처합니다. React는 Virtual DOM의 기존 상태와 새로운 상태를 비교하여, 변경된 부분만 실제 DOM에 반영하는 방식으로 성능을 최적화합니다. 이 과정에서 requestAnimationFrame과 같은 브라우저 API를 통해 렌더링 타이밍을 조율합니다."
- 브라우저와 React의 상호작용을 더 깊게 다룸 (Event Queue → SyntheticEvent).
- requestAnimationFrame과 같은 성능 최적화 기술 언급.
- 이벤트 루프와 브라우저 렌더링 주기의 연결을 소개.
Level 4
"브라우저의 렌더링 엔진은 버튼을 HTML로부터 생성된 DOM 트리와 CSSOM 트리를 기반으로 그립니다. 클릭 이벤트가 발생하면, 브라우저의 Input System이 하드웨어 입력(마우스 클릭)을 감지하고, 이를 OS 레벨에서 이벤트 메시지로 처리합니다. JavaScript 엔진은 React 이벤트 핸들러를 호출하며, React의 Fiber Reconciler는 상태 변경을 추적하고 업데이트된 Virtual DOM과 실제 DOM 간의 diffing을 수행해 효율적으로 렌더링합니다."
- DOM/CSSOM 생성 및 브라우저 렌더링 파이프라인 언급.
- React의 Fiber Reconciler와 상태 변경 추적 메커니즘 소개.
- 브라우저와 OS 간의 상호작용 간략히 다룸.
Level 5
"버튼 클릭은 브라우저가 OS의 입력 하드웨어 API를 통해 전달받은 신호를 처리하는 것으로 시작됩니다. OS는 이를 브라우저의 Input System에 전달하고, 브라우저는 JavaScript 엔진(V8)을 통해 React의 이벤트 핸들러를 실행합니다. React는 Fiber 알고리즘으로 상태 업데이트를 스케줄링하며, diff 알고리즘을 사용해 Virtual DOM과 실제 DOM 간의 최소 변경 사항을 찾아내어 GPU에 렌더링 명령을 전달합니다."
- OS 레벨에서 하드웨어 입력 처리 과정을 더 상세히 언급.
- React의 Fiber 알고리즘과 GPU 렌더링 명령 전달을 연결.
- Virtual DOM과 diff 알고리즘의 실제 적용.
Level 6
"버튼 클릭은 하드웨어에서 발생한 전기 신호로 시작됩니다. 마우스의 클릭 신호는 CPU로 전달되고, OS는 이 신호를 추적하여 브라우저의 이벤트 시스템으로 넘깁니다. 브라우저는 이를 JavaScript 엔진에서 처리하며, React의 Fiber 구조가 상태와 DOM 변경 사항을 계산합니다. 계산된 변경 사항은 브라우저의 컴포지터가 GPU 명령으로 변환하여 화면에 렌더링합니다."
- 클릭 이벤트의 하드웨어 처리 과정을 자세히 언급.
- 브라우저의 컴포지터(Compositor)와 GPU 렌더링 구체화.
Level 7
"하드웨어의 센서가 마우스 클릭 시 발생하는 전기 신호를 감지하고, 이를 디지털 신호로 변환하여 CPU가 처리합니다. OS는 인터럽트를 생성하고, 입력 장치 드라이버가 이 신호를 이벤트 메시지로 변환합니다. 브라우저는 이 메시지를 수신하여 렌더링 엔진과 JavaScript 엔진에 전달합니다. JavaScript 엔진은 React의 Fiber 구조를 통해 상태와 DOM을 관리하며, 최적화된 변경 사항을 GPU에 전달하여 화면을 다시 그립니다. 이 모든 과정은 브라우저의 이벤트 루프와 렌더링 파이프라인에 따라 동기적으로 또는 비동기적으로 실행됩니다."
- 하드웨어 → OS → 브라우저 → React → GPU의 모든 과정을 세밀하게 연결.
- 인터럽트 처리, 렌더링 파이프라인 등의 기술적 디테일 강화.
이 답변들에서 새롭게 공부할 거리가 얼마나 나왔는가를 생각해보면
무엇을 모르는지 아는 것은 그 자체로 매우 어려운 일인 것 같다.