렌더 프롭(Render Prop) 패턴은 한동안 리액트 커뮤니티의 총아로 떠올랐다. 데이터의 흐름은 투명해졌고, 래퍼 지옥의 악몽은 사라지는 듯했다. 페이스북 팀 역시 새로운 컴포넌트를 개발할 때 이 패턴을 적극적으로 도입하기 시작했다.
문제가 수면 위로 떠오른 것은 여러 개의 상태 로직을 조합해야 하는, 조금 더 복잡한 UI를 만들면서부터였다.
어느 날, 댄은 동료가 작성한 코드를 리뷰하고 있었다. 그 컴포넌트는 다음과 같은 요구사항을 가지고 있었다.
- 현재 로그인한 사용자 정보를 가져와야 한다.
- 마우스의 위치를 추적해야 한다.
- 창의 크기가 변하는 것을 감지해야 한다.
개발자는 이미 만들어져 있던 렌더 프롭 컴포넌트들을 활용했다. 사용자 정보를 제공하는 <CurrentUser>
, 마우스 위치를 추적하는 <Mouse>
, 창 크기를 알려주는 <WindowSize>
가 그것이다.
그는 이 세 가지 데이터를 모두 사용하여 하나의 UI를 그려야 했다.
그가 작성한 코드는 다음과 같은 형태였다.
class Dashboard extends React.Component {
render() {
return (
<CurrentUser render={user => (
<Mouse render={mouse => (
<WindowSize render={windowSize => (
<div>
<h1>Welcome, {user.name}!</h1>
<p>Mouse is at: {mouse.x}, {mouse.y}</p>
<p>Window size is: {windowSize.width}px by {windowSize.height}px</p>
</div>
)}/>
)}/>
)}/>
);
}
}
코드는 작동했다. 기술적으로는 아무런 문제가 없었다.
하지만 댄은 코드를 읽는 순간, 숨이 턱 막히는 듯한 갑갑함을 느꼈다.
코드가 아래로 흐르지 않고, 오른쪽으로 끝없이 파고들고 있었다.
<CurrentUser>
가 user
데이터를 제공하면, 그 안에서 <Mouse>
가 mouse
데이터를 제공하고, 또 그 안에서 <WindowSize>
가 windowSize
데이터를 제공했다. 하나의 상태 로직이 추가될 때마다, 코드는 한 단계씩 더 깊은 들여쓰기를 강요했다.
마치 끝없이 중첩된 인형, 마트료시카 같았다.
이 구조는 과거 자바스크립트 개발자들이 비동기 처리를 위해 콜백 함수를 사용하다 마주쳤던 ‘콜백 지옥(Callback Hell)’과 소름 돋을 정도로 닮아 있었다.
댄과 동료들은 이 현상에 새로운 별명을 붙여주었다.
‘콜백의 피라미드’ 혹은 ‘운명의 산(Mount Doom)’.
오른쪽으로 뾰족하게 솟아오르는 코드의 모양이 마치 피라미드나 험준한 산봉우리 같았기 때문이다.
이 구조는 가독성을 심각하게 해쳤다.
개발자는 어떤 데이터가 어느 컴포넌트로부터 오는지 파악하기 위해, 여러 겹의 괄호와 들여쓰기 사이를 눈으로 힘겹게 오가야 했다. 실제 UI를 그리는 핵심 로직은 수많은 render
prop의 장벽 너머, 피라미드의 가장 깊은 곳에 파묻혀 있었다.
래퍼 지옥을 탈출했더니, 피라미드 지옥에 갇힌 꼴이었다.
댄은 의자에 등을 깊게 기댔다.
HOC(고차 컴포넌트)는 데이터의 출처를 숨겼다.
렌더 프롭은 데이터의 출처를 드러냈지만, 그 대가로 코드 구조를 망가뜨렸다.
두 가지 해결책 모두 절반의 성공이자, 절반의 실패였다.
그들은 같은 문제를 풀기 위해 서로 다른 길을 택했지만, 결국 또 다른 종류의 복잡성이라는 함정에 빠지고 말았다.
댄은 깨달았다.
이것은 더 이상 패턴의 문제가 아니었다. 상태를 가진 로직을 ‘재사용’하기 위해, 컴포넌트를 도구로 사용하는 것 자체가 근본적인 한계를 가지고 있었다. 컴포넌트는 본질적으로 UI를 구성하기 위한 단위이지, 순수한 로직을 담기에는 너무 무겁고 거추장스러운 그릇이었다.
“뭔가… 더 근본적인 것이 필요해.”
그의 중얼거림에, 회의실에 있던 모두가 조용히 고개를 끄덕였다.
점진적인 개선이나 영리한 패턴만으로는 부족했다.
리액트의 핵심 작동 방식에 손을 대야 할지도 모르는, 거대한 수술이 필요했다.
그리고 그 수술을 집도할 두 명의 핵심 외과의가 바로 이 회의실에 함께 앉아 있었다. 한 명은 리액트의 심장을 설계한 남자였고, 다른 한 명은 그 심장이 어떻게 뛰어야 하는지를 가장 깊이 이해하는 여자였다.