뉴스피드, 리액트의 시험대

522025년 10월 06일3

이론은 충분했다. 이제는 실전이었다. 톰은 팀에게 첫 번째 과제를 부여했다.
“리액트의 가능성을 증명합시다. 페이스북의 가장 복잡하고 중요한 기능 중 하나, 바로 뉴스피드의 댓글 입력창을 리액트로 다시 만들어보는 겁니다.”

그것은 단순한 기술 데모가 아니었다. 실제 수백만 사용자가 매일 사용하는 페이스북의 심장부를 건드리는, 위험하지만 의미 있는 도전이었다. 만약 리액트가 이 복잡성을 감당해낼 수 있다면, 그 가능성을 페이스북 전체에 증명할 수 있을 터였다.

팀은 가장 먼저 기존 댓글 입력창의 문제점을 분석했다.
기존 시스템은 jQuery와 약간의 백본 코드가 뒤섞여 있었다.

  • 사용자가 텍스트를 입력하면, jQuery 이벤트 핸들러가 글자 수를 세어 화면에 표시했다.
  • ‘@’를 입력하면 친구 자동완성 목록을 보여주기 위해 서버에 비동기 요청을 보냈다.
  • 자동완성 목록이 나타나면, 키보드 방향키로 목록을 탐색하는 로직이 실행되었다.
  • ‘게시’ 버튼을 누르면, 입력된 내용을 서버로 전송하고, 입력창을 비우고, 뉴스피드의 다른 부분(댓글 목록)을 갱신하라는 신호를 보냈다.

이 모든 로직이 서로 다른 파일에 흩어져, DOM의 상태를 직접 읽고 수정하며 복잡하게 얽혀 있었다. 하나의 기능을 수정하면 다른 기능이 고장 나는 일이 비일비재했다.

조던과 팀은 이 모든 것을 단 하나의 리액트 컴포넌트, <CommentBox> 안에 담기로 했다.

“가장 먼저 할 일은, 이 컴포넌트가 필요로 하는 모든 데이터를 props로 정의하는 겁니다.” 조던이 말했다. “<CommentBox>는 부모로부터 무엇을 받아야 할까요?”

팀은 논의 끝에 몇 가지 props를 정의했다.

  • currentUserAvatarUrl: 현재 로그인한 사용자의 아바타 이미지 주소.
  • onSubmit: 사용자가 댓글을 게시했을 때 실행될 콜백 함수.
// CommentBox를 사용하는 가상의 코드
React.createElement(CommentBox, {
  currentUserAvatarUrl: '...',
  onSubmit: function(commentText) {
    // ... 댓글을 서버로 전송하는 로직 ...
  }
});

<CommentBox>onSubmit이라는 함수를 props로 받음으로써, 댓글을 게시하는 구체적인 방법을 알 필요가 없어졌다. 그저 ‘게시’ 버튼이 눌리면 this.props.onSubmit()을 호출하기만 하면 됐다. 어떻게 서버와 통신하는지는 전적으로 부모의 책임이었다. 이로써 컴포넌트의 독립성이 확보되었다.

다음 단계는 render 메서드를 작성하는 것이었다.

// CommentBox의 render 메서드 (초안)
var CommentBox = React.createClass({
  render: function() {
    return React.createElement('div', { className: 'comment-box' }, [
      React.createElement(Avatar, { imageUrl: this.props.currentUserAvatarUrl }),
      React.createElement('textarea', { placeholder: '댓글을 입력하세요...' }),
      React.createElement('button', null, '게시')
    ]);
  }
});

여기까지는 순조로웠다. 정적인 화면을 그리는 것은 간단했다.
하지만 곧바로 거대한 문제에 부딪혔다.

“사용자가 textarea에 입력하는 텍스트는 어디에 저장해야 하죠?” 맷이 질문했다.
“이건 부모로부터 받은 데이터가 아닙니다. 사용자의 상호작용에 따라 컴포넌트 내부에서 실시간으로 변해야 하는 값입니다. props에는 담을 수 없어요.”

그의 말대로였다. 사용자가 입력하는 댓글 내용, 친구 자동완성 목록이 열려 있는지 닫혀 있는지 여부, 현재 선택된 자동완성 항목이 무엇인지…
이 모든 데이터는 컴포넌트가 스스로 기억하고 관리해야 할, 자신만의 ‘내부 상태’였다.

props의 불변성 원칙을 지키면서, 동시에 컴포넌트가 동적으로 변화해야 하는 이 모순적인 상황.
이 문제를 해결하기 위해, 리액트는 두 번째 심장, 즉 state라는 개념을 세상에 드러내야만 했다. 뉴스피드라는 거대한 시험대는 리액트의 진화를 강요하고 있었다.