조던 워크는 대학 시절의 낡은 프로그래밍 서적들을 다시 펼쳤다. 그중에서도 그의 손길이 가장 오래 머문 것은 로빈 밀너(Robin Milner)가 창시한 스탠다드 ML(Standard ML)의 해설서였다. 동료들이 최신 자바스크립트 프레임워크의 동향을 쫓을 때, 그는 수십 년 된 학술 언어의 철학 속으로 깊이 파고들었다.
스탠다드 ML의 세계에서 데이터는 신성불가침의 영역이었다. 한번 값이 할당된 변수는 절대로 바꿀 수 없었다.
val x = 10
이 선언이 실행되는 순간, x
는 영원히 10이 되었다. 만약 11이라는 값이 필요하다면 x
를 11로 바꾸는 것이 아니라, 새로운 변수 y
를 만들어 x + 1
의 결과를 담아야 했다.
val y = x + 1
이 ‘불변성(Immutability)’이라는 원칙은 처음에는 비효율적이고 답답하게 느껴졌다. 하지만 조던은 그 이면에 숨겨진 강력한 장점을 꿰뚫어 보고 있었다.
예측 가능성.
값이 절대 변하지 않으니, 프로그램의 어느 시점에서든 변수의 값을 신뢰할 수 있었다. x
라는 변수를 마주치면, 그 값은 의심의 여지 없이 10이다. 다른 함수가 그 값을 몰래 바꾸었을지도 모른다는 불안감을 가질 필요가 없었다. 복잡한 시스템에서 버그를 추적할 때, 이것은 엄청난 무기였다.
조던은 이 개념을 페이스북의 뉴스피드에 대입해 보았다.
현재의 방식은 이렇다. PostModel
이라는 거대한 객체가 있고, 그 안에는 likes
, comments
, author
등의 속성이 있다. ‘좋아요’ 버튼을 누르면, 누군가가 PostModel.likes
의 값을 1 증가시킨다. 댓글이 달리면 다른 누군가가 PostModel.comments
배열에 새로운 데이터를 밀어 넣는다.
하나의 거대한 PostModel
객체를 수십 개의 코드 조각이 달려들어 마구잡이로 수정하고 있었다. 이 때문에 ‘좋아요’를 눌렀을 뿐인데 댓글이 사라지는 등의 예측 불가능한 버그가 발생했다.
‘만약… 게시물 데이터가 불변이라면?’
조던의 머릿속에서 새로운 아이디어가 번개처럼 스쳤다.
- 최초의 게시물 데이터
post_version_1
이 있다. 이 데이터는 절대 수정할 수 없다. - 사용자가 ‘좋아요’를 누른다.
- 시스템은
post_version_1
을 수정하는 대신,likes
카운트만 1 증가시킨 완전히 새로운 복사본,post_version_2
를 생성한다. - 이제 시스템은
post_version_1
과post_version_2
를 비교한다. 둘은 다른 객체이므로, 데이터에 변화가 생겼다는 것을 아주 쉽게 알 수 있다. - 더 나아가, 두 객체의 속성을 비교하면
likes
속성만 바뀌었다는 사실도 명확히 알 수 있다.
이 방식은 지금의 복잡한 이벤트 리스너 시스템을 완전히 대체할 수 있는 가능성을 품고 있었다. 더 이상 “likes
값이 바뀌었니?”, “comments
배열 길이가 달라졌니?” 라고 일일이 묻지 않아도 된다. 그냥 이전 데이터 객체와 새 데이터 객체가 같은지 다른지만 비교하면 그만이었다.
비교는 지극히 빠르고 효율적이었다.
이 아이디어는 조던이 오랫동안 고민하던 문제, ‘데이터가 바뀌었을 때 어떻게 화면을 갱신할 것인가’에 대한 혁신적인 해답을 제시했다.
‘변경을 감지하려 애쓰지 마라. 그냥 이전 상태와 다음 상태를 통째로 비교하라.’
물론 거대한 데이터 객체를 매번 새로 만드는 것은 메모리 낭비처럼 보였다. 하지만 조던은 그것이 예측 불가능한 버그와 씨름하며 개발자들이 낭비하는 시간과 비용에 비하면 아무것도 아니라고 생각했다. 더 중요한 것은, 영리한 최적화 기법을 사용하면 이 복사 과정을 매우 효율적으로 만들 수 있다는 사실이었다.
스탠다드 ML의 불변성이 주는 미학. 그것은 단순한 코딩 스타일이 아니었다. 복잡한 시스템의 동작을 단순하고, 명확하고, 예측 가능하게 만드는 강력한 철학이었다. 조던은 이 철학을 자바스크립트의 세계로 가져오기로 결심했다. 그의 손에서 코드의 연금술이 시작되려 하고 있었다.