커스텀 훅의 발견이 가져온 충격은 쉽게 가라앉지 않았다. 팀원들은 마치 새로운 장난감을 얻은 아이들처럼, 온갖 종류의 커스텀 훅을 만들어보기 시작했다.
“localStorage
에 데이터를 저장하고 불러오는 로직, 이거 항상 귀찮았는데… useLocalStorage
로 만들면 되겠네요!”
“폼 입력 값을 처리하는 useInput
도 가능하겠는데요? useState
와 onChange
핸들러를 하나로 묶어서요.”
“API 호출할 때마다 나오는 로딩, 데이터, 에러 상태 관리도 useFetch
로 만들 수 있겠어요!”
아이디어는 봇물 터지듯 쏟아져 나왔다.
과거에는 HOC나 렌더 프롭으로 복잡하게 감싸거나, 모든 컴포넌트에 코드를 복사-붙여넣기 해야 했던 모든 상태 로직들이, 이제는 간결하고 재사용 가능한 함수로 다시 태어나고 있었다.
댄은 동료들이 열광하는 모습을 보며, 이 새로운 패러다임이 가진 파괴적인 힘을 실감했다. 이것은 단순한 API 추가가 아니었다. 이것은 리액트 생태계 전체의 코드 작성 방식을 뿌리부터 뒤흔드는, 거대한 지각 변동이었다.
그는 문득, 자신이 과거에 만들었던 Redux를 떠올렸다.
Redux는 복잡한 상태 관리에 질서를 부여하기 위해 만들어졌다. 하지만 그 질서를 위해, 개발자들은 액션(Action), 리듀서(Reducer), 스토어(Store), connect
HOC 등 수많은 개념과 보일러플레이트 코드를 배워야만 했다.
하지만 이제, 간단한 전역 상태 관리는 useContext
와 useReducer
를 조합한 커스텀 훅만으로도 훨씬 간결하게 구현할 수 있을 터였다. 이것은 그가 만들었던 과거의 해답을, 그 자신의 손으로 뛰어넘는 순간이기도 했다.
“이것은… 혁명이야.”
댄은 나지막이 중얼거렸다.
그의 옆에 서 있던 소피가 조용히 그의 말에 동의했다.
“맞아요. 그리고 모든 혁명에는 저항이 따르죠.”
그녀의 말은 팀의 들뜬 분위기에 차가운 현실감을 불어넣었다.
전 세계 수백만 명의 개발자들이 클래스 컴포넌트에 익숙해져 있었다. 그들이 수년간 쌓아온 지식과 코드 자산을 하루아침에 낡은 것으로 만들어버릴 수도 있는 이 변화를, 과연 커뮤니티가 순순히 받아들일까?
“‘클래스를 버리라’는 메시지로 비치면 안 됩니다. 그랬다간 엄청난 반발에 부딪힐 거예요.” 소피가 경고했다. “훅은 점진적으로 도입할 수 있는, 100% 선택적인 기능이어야 합니다. 기존의 클래스 코드와 완벽하게 함께 작동해야 하고요.”
“맞습니다.” 세바스티안도 동의했다. “그리고 우리는 ‘왜’ 이 변화가 필요했는지, 우리가 어떤 문제를 풀려고 했는지 명확하게 설명해야 합니다. 개발자들이 훅의 멘탈 모델을 제대로 이해하지 못하면, 마법처럼 여기거나 오용하게 될 겁니다.”
‘호출 순서의 불변성’이라는 핵심 규칙.
조건문이나 반복문 안에서 훅을 호출하면 안 된다는 제약.
이것들은 훅이 가진 힘의 원천이자, 동시에 가장 위험한 함정이었다. 이 규칙들을 명확한 가이드라인과 도구로 뒷받침하지 않는다면, 훅은 개발자들에게 편리함이 아닌 혼란을 안겨줄 수도 있었다.
팀의 역할은 이제 두 가지로 나뉘었다.
하나는 훅 API를 더욱 견고하고 안정적으로 다듬는 기술적인 과제.
다른 하나는 이 거대한 변화를 어떻게 세상에 소개하고, 개발자들을 설득하며, 새로운 패러다임으로 안전하게 이끌 것인가 하는 소통의 과제였다.
그들은 자신들이 단순한 코드 몇 줄을 바꾼 것이 아니라는 사실을 무겁게 인지했다.
리액트라는 거대한 배의 항로를 통째로 바꾸고 있었다.
성공한다면 리액트는 더 가볍고, 더 빠르고, 더 강력한 배가 되어 순항할 것이다.
하지만 실패한다면, 커뮤니티는 분열되고 배는 좌초될 수도 있었다.
혁명의 깃발은 올랐다.
이제 남은 것은, 이 깃발을 들고 세상 앞에 나아갈 준비를 하는 것이었다. 그들의 눈앞에는 2018년 가을에 열릴 리액트 콘퍼런스라는 거대한 무대가 기다리고 있었다.