첫 번째 프로토타입, 그 이름 FaxJS

252025년 09월 09일4

아이디어는 충분했다. 이제는 증명할 시간이었다. 조던 워크는 주말 내내 텅 빈 사무실의 불을 밝혔다. 그는 동료들에게 자신의 급진적인 아이디어를 설명했지만, 실제로 동작하는 결과물 없이는 한낱 공상으로 치부될 뿐이라는 것을 잘 알고 있었다. 그는 자신만의 작은 실험 프로젝트에 착수했다.

가장 먼저 할 일은 프로젝트에 이름을 붙이는 것이었다. 그는 이 라이브러리의 핵심 철학을 담을 수 있는, 간결하고 명확한 이름을 원했다. 그의 머릿속을 맴돌던 것은 UI = render(data)라는 공식이었다. 데이터가 주어지면, UI 전체의 모습이 담긴 완전한 ‘설계도’가 출력된다. 마치 팩스 기계와 같았다.

팩스를 보낼 때, 우리는 수정된 단어나 문장만 보내지 않는다. 언제나 문서 전체를 스캔해서 한 장의 완전한 이미지로 전송한다. 수신자는 그저 새로 도착한 완전한 문서를 받기만 하면 된다.

“Fax… JS.”

조던은 나지막이 중얼거렸다. 완벽한 이름이었다. 데이터의 세계에서 UI의 세계로, 언제나 완전한 결과물을 ‘전송’한다는 개념을 직관적으로 담고 있었다. 그의 첫 번째 프로토타입은 ‘FaxJS’라는 이름을 얻었다.

그의 목표는 단 하나, 가장 단순한 형태로 UI = render(data) 사이클을 구현해 보는 것이었다. 그는 밤을 새워 코드를 작성했다.

  1. UI 설명서 객체를 생성하는 헬퍼 함수 (createDescription)
  2. 이 설명서 객체를 받아 실제 DOM 요소로 변환하는 초보적인 렌더러
  3. 그리고 이 모든 것을 조율할 단 하나의 메인 함수

테스트 케이스는 간단한 카운터(Counter)로 정했다.

먼저, 데이터 모델을 정의했다. 불변성을 흉내 내기 위해, 그는 데이터를 단순한 객체에 담았다.

// 데이터 모델
var appState = { count: 0 };

다음으로, 이 데이터를 받아 UI 설명서를 반환할 컴포넌트 함수를 작성했다.

// Counter 컴포넌트 함수
function CounterComponent(props) {
  var countValue = props.count;
  
  return createDescription('div', null, [
    createDescription('h1', null, ['카운터']),
    createDescription('p', null, ['현재 값: ', countValue]),
    createDescription('button', { id: 'increment-button' }, ['1 증가'])
  ]);
}

이제 FaxJS의 핵심 로직을 가동할 차례였다. 그는 renderApp이라는 함수를 만들었다. 이 함수는 현재의 appStateCounterComponent에 전달하여 UI 설명서 트리를 얻고, 화면의 특정 위치(예: document.body)에 그 내용을 그려 넣는다. 초기 버전의 렌더러는 비효율적이지만 확실한 방식을 택했다. 기존의 모든 내용을 지우고, 처음부터 새로 그리는 것이다.

// FaxJS의 핵심 렌더링 함수
function renderApp() {
  var description = CounterComponent(appState);
  
  // body의 모든 자식 요소를 지운다.
  document.body.innerHTML = ''; 
  
  // description을 기반으로 실제 DOM을 생성하여 body에 추가한다.
  mount(description, document.body);
}

마지막으로, 버튼 클릭 이벤트를 설정했다. 중요한 것은, 이벤트 핸들러가 DOM을 직접 조작하지 않는다는 점이었다.

// 이벤트 핸들러는 오직 데이터만 변경한다.
document.addEventListener('click', function(e) {
  if (e.target.id === 'increment-button') {
    // 1. 데이터를 변경한다.
    appState.count = appState.count + 1;
    
    // 2. 전체 앱을 다시 렌더링하도록 요청한다.
    renderApp();
  }
});

모든 준비가 끝났다. 조던은 브라우저에서 HTML 파일을 열었다. 화면에는 ‘카운터’와 ‘현재 값: 0’, 그리고 ‘1 증가’ 버튼이 성공적으로 나타났다.

그는 떨리는 손으로 ‘1 증가’ 버튼을 클릭했다.

순간, 화면의 숫자가 ‘1’로 바뀌었다. 다시 클릭하자 ‘2’가 되었다.

느렸고, 비효율적이었으며, 화면 전체가 깜빡이는 조잡한 방식이었다. 하지만… 작동했다.

그는 성공했다. 데이터가 변하자, UI가 그에 맞춰 저절로 업데이트되는, 마법과도 같은 사이클을 처음으로 구현해 낸 것이다. 개발자는 오직 데이터만 변경했을 뿐인데, 라이브러리가 알아서 화면을 다시 그렸다.

물론 아직 갈 길은 멀었다. 화면 전체를 지우고 새로 그리는 이 방식으로는 실제 페이스북 애플리케이션에 적용할 수 없었다.

하지만 조던은 가장 중요한 첫걸음을 내디뎠다. 그는 자신의 아이디어가 단순한 공상이 아님을 증명했다. 이제 남은 과제는 이 팩스 기계에 ‘바뀐 부분만 감지해서 전송하는’ 지능을 부여하는 것이었다.