세 가지 거대한 벽

142025년 08월 29일4

페이스북 캠퍼스의 해가 서서히 저물고 있었다. 창밖의 하늘은 붉은색과 보라색이 뒤섞인 오묘한 빛을 띠었지만, 리액트 팀의 회의실은 여전히 환한 조명 아래 뜨거운 열기로 가득했다.

화이트보드에는 지난 몇 주간의 고민이 빼곡하게 적혀 있었다.
HOC, 렌더 프롭, this, 생명주기, 뒤섞인 관심사, 최적화 문제…
어지럽게 흩어져 있던 단어들을, 댄 아브라모프가 검은색 마커를 들고 세 개의 명확한 문장으로 정리하기 시작했다.

그것은 리액트가 마주한, 넘어야 할 세 개의 거대한 벽이었다.

첫 번째 벽: 상태 로직 재사용의 어려움 (The Difficulty of Reusing Stateful Logic)

댄은 화이트보드 중앙에 이렇게 적었다.
“우리는 UI가 아닌, 로직을 공유할 우아한 방법이 없다.”

HOC는 래퍼 지옥을 만들었고, 렌더 프롭은 콜백 피라미드를 만들었다. 두 패턴 모두 컴포넌트라는 틀을 이용해 로직을 억지로 공유하려다 보니, 코드의 구조를 왜곡시키고 복잡성을 증가시켰다. 개발자들은 ‘친구의 온라인 상태를 추적하는’ 순수한 로직을, 마치 라이브러리 함수처럼 간편하게 가져다 쓰고 싶어 했다. 하지만 현실은 언제나 거추장스러운 컴포넌트 포장지를 동반했다.

두 번째 벽: 복잡한 컴포넌트의 난해함 (The Difficulty of Understanding Complex Components)

댄은 첫 번째 문장 아래에 두 번째 문장을 적었다.
“컴포넌트가 커질수록, 코드는 필연적으로 뒤죽박죽이 된다.”

이것은 소피가 날카롭게 지적했던 문제였다. 클래스의 생명주기 모델은 관련 있는 코드를 시간의 흐름에 따라 흩어놓고(찢어진 기능), 관련 없는 코드를 하나의 메서드 안에 뒤섞어 놓았다(뒤섞인 관심사).

개발자가 버그를 수정하거나 새로운 기능을 추가하려면, 거대한 클래스 파일 안에서 파편화된 코드 조각들을 찾아 헤매야 했다. 코드는 작성된 의도대로가 아닌, 생명주기라는 인위적인 규칙에 따라 강제로 재구성되었다. 그 결과, 누구도 전체 그림을 쉽게 파악할 수 없는, 유지보수가 불가능에 가까운 괴물 컴포넌트가 탄생했다.

세 번째 벽: 개발자와 기계 모두에게 혼란스러운 클래스 (The Confusion of Classes for Both Humans and Machines)

마지막으로, 댄은 세바스티안의 통찰을 요약했다.
“클래스는 자바스크립트의 핵심을 흐리고, 최적화를 방해한다.”

초보 개발자들은 this의 변덕스러운 동작과 bind의 필요성을 이해하는 데 어려움을 겪었다. 함수형 프로그래밍에 익숙한 개발자들에게 클래스는 불필요하게 복잡한 문법이었다.
이것은 인간만의 문제가 아니었다. 자바스크립트 엔진과 번들러 역시 클래스의 동적인 특성 때문에 코드를 효율적으로 분석하고 최적화하는 데 한계를 보였다. 클래스는 리액트의 미래를 향한 길목에 놓인, 보이지 않는 속도 저감 장치였다.

댄은 마커를 내려놓고, 화이트보드에 쓰인 세 개의 문장을 바라보았다.
이 세 개의 벽은 서로 단단히 연결되어 있었다. 하나의 벽을 넘기 위해서는, 결국 세 개의 벽을 모두 무너뜨려야만 했다.

회의실의 공기는 무거웠지만, 누구의 얼굴에도 절망감은 없었다. 오히려 문제의 본질이 명확하게 정의되자, 그들의 눈빛은 더욱 단단해졌다. 더 이상 어둠 속을 헤맬 필요가 없었다. 부숴야 할 목표물이 명확해진 것이다.

소피가 입을 열었다.
“좋아요. 이제 문제는 명확해졌군요. 그렇다면 질문은 하나입니다.”

그녀는 댄과 세바스티안, 그리고 팀원들을 차례로 둘러보며 말했다.
“이 벽들을 어떻게 부술 거죠?”

그 질문에 대한 답은, 회의실 안 그 누구도 가지고 있지 않았다.
그들이 가진 것은 오직, 지금 이대로는 안 된다는 절박함과, 더 나은 방법을 찾을 수 있다는 희미한 믿음뿐이었다. 그 믿음을 현실로 만들기 위한, 길고 고된 여정이 이제 막 시작되려 하고 있었다.