조던 워크는 자신의 ‘FaxJS’ 프로토타입을 팀 리더 톰에게 시연했다. 톰은 팔짱을 낀 채 유심히 지켜보았다. 버튼을 클릭할 때마다 카운터 숫자가 정확히 올라갔다. 하지만 그의 표정은 밝지 않았다.
“작동하는 건 알겠습니다, 조던.” 톰이 입을 열었다. “하지만 매번 화면 전체를 지우고 새로 그리는 건 너무 무식한 방법 아닙니까? 화면이 깜빡이는 게 눈에 다 보이는데요. 백본은 이것보다 훨씬 영리하게, 바뀐 부분만 딱 집어서 업데이트합니다.”
톰의 지적은 정확했다. 성능 면에서 FaxJS의 첫 번째 프로토타입은 백본에 비해 한참 뒤처져 있었다.
“네, 맞습니다. 지금 이 구현은 끔찍하게 비효율적이죠.” 조던은 순순히 인정했다. 그리고는 화이트보드에 두 개의 그림을 그리기 시작했다.
왼쪽에는 백본의 구조를 그렸다. 모델과 뷰를 나타내는 여러 개의 상자들이 있었고, 그 사이를 잇는 화살표들이 거미줄처럼 얽혀 있었다. 화살표는 양방향을 가리키거나, 한 뷰에서 다른 뷰로 직접 이어지기도 했다.
“이것이 백본, 그리고 우리가 지금까지 해온 방식입니다.” 조던이 말했다. “뷰가 모델을 바꾸고, 모델이 다른 뷰를 바꾸고, 그 뷰가 또 다른 모델을 바꾸죠. 모든 것이 서로 ‘대화’하고 있습니다. 이 방식의 장점은 톰이 말한 대로, 변경 사항에 똑똑하게 반응해서 최소한의 부분만 업데이트한다는 겁니다. 하지만 단점은, 대화가 너무 복잡해지면 누가 누구에게 무슨 말을 했는지 아무도 추적할 수 없게 된다는 겁니다. 우리는 성능을 얻는 대신 예측 가능성을 잃었습니다.”
그는 오른쪽으로 옮겨가 훨씬 단순한 그림을 그렸다. 맨 위에 커다란 ‘Data’ 상자가 있었고, 그 아래에 화살표가 수직으로 내려와 ‘UI’ 상자를 가리켰다. 그것이 전부였다.
“이것이 FaxJS의 철학입니다. 데이터는 오직 한 방향, 위에서 아래로만 흐릅니다.”
그는 ‘UI’ 상자에서 위쪽 ‘Data’ 상자를 향해 점선으로 된 역방향 화살표를 하나 추가했다.
“UI에서 발생하는 사용자 행동, 예를 들어 버튼 클릭 같은 것은 절대로 다른 UI를 직접 바꾸지 못합니다. 그저 맨 위에 있는 원본 데이터를 바꿔달라는 ‘요청’을 보낼 뿐입니다. 그러면 데이터가 바뀌고, 그 바뀐 데이터를 기반으로 한 새로운 UI가 다시 위에서 아래로 통째로 내려오는 거죠. 모든 데이터의 흐름은 이 단 하나의 경로를 따라야만 합니다.”
이것은 ‘대화’가 아니라 ‘명령’이었다. 중앙 데이터 저장소가 모든 것을 통제하고, UI는 그저 명령을 받아 자신을 그리는 수동적인 존재가 되는 것이다.
톰은 두 그림을 번갈아 보며 조던의 설명이 가진 깊은 의미를 이해하기 시작했다. 왼쪽의 그림은 유연하지만 혼란스러웠고, 오른쪽의 그림은 경직되어 보이지만 지극히 단순하고 명료했다.
“그러니까… 우리는 버그를 추적하기 위해 수십 개의 화살표를 쫓아다니는 대신, 오직 단 하나의 화살표만 감시하면 된다는 거군요.”
“바로 그겁니다.” 조던의 눈이 빛났다. “우리는 이 원칙을 단방향 데이터 흐름(One-way data flow)이라고 부를 겁니다. 이 원칙을 지키는 한, 애플리케이션이 아무리 복잡해져도 데이터의 흐름은 언제나 예측 가능합니다.”
물론, 여전히 가장 큰 숙제는 남아있었다. 위에서 아래로 통째로 내려오는 이 비효율적인 ‘명령’을 어떻게 성능 저하 없이 구현할 것인가.
하지만 조던과 톰은 이제 알았다. 성능은 그 다음 문제였다. 가장 먼저 바로잡아야 할 것은 뒤죽박죽 엉켜버린 데이터의 흐름이었다. FaxJS는 그 해답의 첫 번째 실마리였다.