훅의 시대가 무르익은 어느 날, 댄 아브라모프는 자신의 옛날 노트를 우연히 발견했다. 그 노트에는 2016년, 이 모든 여정이 시작되었던 그 회의실에서 그가 직접 적었던 메모가 남아 있었다.
먼지 쌓인 페이지 위에는, 그들이 넘어서야 할 ‘세 개의 거대한 벽’이 희미한 잉크 자국으로 적혀 있었다.
- 상태 로직 재사용의 어려움.
- 복잡한 컴포넌트의 난해함.
- 개발자와 기계 모두에게 혼란스러운 클래스.
댄은 잠시 과거를 회상했다.
HOC의 래퍼 지옥과 렌더 프롭의 콜백 피라미드 속에서 길을 잃었던 순간들. this의 변덕에 좌절하고, 흩어진 생명주기 메서드 사이를 헤매던 동료들의 모습이 눈앞에 선했다. 그 시절, 저 세 개의 벽은 마치 영원히 넘을 수 없을 것 같은 거대한 산맥처럼 느껴졌다.
그는 미소를 지으며, 현재의 리액트 세계를 떠올렸다.
그리고 그 세 개의 문제가, 그들이 만든 ‘훅’이라는 단 하나의 해결책에 의해 어떻게 완벽하게 무너져 내렸는지를 하나씩 되짚어보기 시작했다.
첫 번째 벽: 상태 로직 재사용의 어려움.
댄은 useWindowWidth, useFetch, useForm과 같은 수많은 커스텀 훅들을 떠올렸다.
“‘커스텀 훅’이 이 벽을 무너뜨렸다.”
개발자들은 이제 상태와 부수 효과를 포함한 모든 로직을, 평범한 함수처럼 자유롭게 추출하고, 테스트하고, 공유할 수 있게 되었다. 로직 재사용은 더 이상 고통스러운 트레이드오프가 아니라, 리액트 개발의 자연스러운 일부가 되었다.
두 번째 벽: 복잡한 컴포넌트의 난해함.
그는 useEffect가 처음 탄생했던 순간을 기억해냈다.
“useEffect가 이 벽을 무너뜨렸다.”
useEffect는 componentDidMount, Update, Unmount에 흩어져 있던 관련 로직들을, 기능 단위로 함께 묶을 수 있게 해주었다. ‘관심사의 분리’라는 오랜 난제에 대한 우아한 해답이었다. 컴포넌트는 더 이상 뒤죽박죽 얽힌 스파게티 코드가 아니라, 각자의 역할을 책임지는 작은 훅들의 조합으로 이루어진, 읽기 쉬운 조립 설명서가 되었다.
세 번째 벽: 클래스의 혼란.
마지막으로, 그는 useState가 처음으로 함수 안에서 상태를 만들어냈던, 그 짜릿했던 실험의 순간을 떠올렸다.
“‘훅’ 그 자체가 이 벽을 무너뜨렸다.”
훅은 this 키워드와 bind의 필요성을 역사 속으로 사라지게 했다. 함수형 컴포넌트는 클래스보다 문법이 훨씬 간결했고, 초심자들이 배우기 쉬웠다. 또한, 함수는 클래스 인스턴스보다 가볍고 예측 가능했기에, 번들러 최적화와 미래의 동시성 렌더링을 위한 길을 열어주었다.
댄은 노트를 조용히 덮었다.
길고 길었던 싸움이었다.
수많은 시행착오와 격렬한 논쟁, 그리고 번뜩이는 영감의 순간들이 있었다.
결과적으로, 그들은 자신들이 처음 세웠던 목표를 모두 달성했을 뿐만 아니라, 그 과정에서 자신들이 상상했던 것보다 훨씬 더 위대한 것을 창조해냈다.
그들은 단순히 세 개의 벽을 넘은 것이 아니었다.
그들은 리액트 개발자들이 서 있는 땅 자체를 바꾸어 놓았다.
더 평탄하고, 더 넓고, 더 비옥한 땅.
그 위에서 미래의 개발자들이 어떤 놀라운 것들을 새로 지어 올릴지, 그는 조용한 기대를 품고 상상했다.
그들이 시작했던 전투는, 이제 끝났다.
완벽한 승리였다.


