영감의 순간, 스토어의 재발견
제6화
발행일: 2025년 05월 08일
‘훅처럼 쓰면서도, 성능 문제를 해결한다…’
이 화두는 며칠 동안 카토의 머릿속을 떠나지 않았다. 마치 풀리지 않는 고대의 수수께끼처럼, 그의 모든 사고를 지배했다. 그는 코드를 작성하는 시간보다, 빈 화면을 응시하며 생각에 잠기는 시간이 더 많아졌다.
Context API의 근본적인 문제는 무엇이었나? 바로 상태 저장소(Provider)가 React 컴포넌트 트리 구조 안에 갇혀 있다는 점이었다. 부모 Provider가 변경되면, 그 아래 자식들은 좋든 싫든 영향을 받을 수밖에 없는 운명. 마치 연좌제처럼, 아무 잘못 없는 컴포넌트까지 리렌더링의 형벌을 받아야 했다.
‘만약… 만약 상태 저장소가 컴포넌트 트리 바깥에 있다면 어떨까?’
순간, 카토의 뇌리에 오래된 개념 하나가 먼지를 털고 떠올랐다. ‘외부 스토어(External Store)’.
React가 등장하기 이전, 혹은 초창기 시절에 사용되던 방식. 애플리케이션의 상태를 컴포넌트 계층 구조와는 별개인, 독립적인 객체나 모듈에 저장하고 관리하는 패턴이었다. Redux나 MobX 같은 라이브러리들도 결국은 이 외부 스토어 개념을 기반으로 하고 있었다.
‘그래, 외부 스토어… 상태를 트리 구조의 속박에서 해방시키는 거야!’
컴포넌트는 더 이상 상태를 ‘소유’하는 것이 아니라, 필요할 때 외부 스토어에 접근하여 데이터를 ‘빌려’ 쓰고, 변경 사항을 ‘알리는’ 역할을 하게 된다. 이렇게 되면 특정 컴포넌트의 변경이 다른 컴포넌트에게 직접적인 영향을 미치는 연쇄 반응을 끊어낼 수 있었다.
하지만 이것만으로는 충분하지 않았다. 외부 스토어를 사용하더라도, ‘어떻게’ 상태 변경을 감지하고 컴포넌트에게 알릴 것인가 하는 문제가 남는다. 단순히 스토어 전체를 구독하게 만들면, 결국 Context와 같은 문제에 봉착할 뿐이었다. 스토어의 아주 작은 일부만 바뀌어도 모든 구독자가 깨어나는 비효율.
‘핵심은… 구독 방식에 있어.’
카토는 손가락으로 관자놀이를 꾹꾹 눌렀다. 머릿속에서 수많은 아이디어 조각들이 부딪히며 불꽃을 튀겼다.
Context는 마치 광장의 확성기와 같았다. 누구든 들을 수 있지만, 모두에게 불필요한 소음까지 전달한다. Redux는 중앙 관제탑처럼 모든 통신을 통제하지만, 그 과정이 다소 번거롭고 규칙이 엄격했다.
‘더 효율적인 방법… 필요한 사람에게만, 필요한 정보만 전달하는 방법…’
그때였다. 카토의 머릿속을 번개처럼 관통하는 아이디어가 떠올랐다.
‘선택적 구독(Selective Subscription)!’
그래, 바로 이거다! 스토어 전체를 무작정 구독하는 것이 아니라, 컴포넌트가 정확히 자신이 필요한 상태 조각(slice)만 골라서 구독하는 것이다. 마치 수많은 라디오 채널 중에서 내가 듣고 싶은 주파수만 정확히 맞추는 것처럼!
컴포넌트는 스토어에게 선언한다. “나는 전체 상태 중에서 오직 ‘사용자 이름(username)’에만 관심이 있다!”
그러면 스토어는 오직 ‘사용자 이름’이 변경되었을 때만 해당 컴포넌트에게 업데이트 신호를 보낸다. 장바구니 내용이 백 번 바뀌든, 테마 설정이 천 번 바뀌든, 사용자 이름만 그대로라면 이 컴포넌트는 미동조차 하지 않는다. 불필요한 렌더링은 원천적으로 차단되는 것이다!
“크으…!”
카토는 자신도 모르게 낮은 탄성을 내뱉었다. 온몸에 소름이 돋는 듯한 전율. 복잡하게 얽혀 있던 문제의 실타래가 단숨에 풀려나가는 듯한 쾌감이었다.
외부 스토어로 상태를 트리 구조에서 분리하고, 선택적 구독으로 불필요한 전파를 막는다. 이 두 가지가 조합된다면… Context의 성능 문제는 완벽하게 해결할 수 있었다.
거기에 더해, 이 모든 것을 여전히 간단한 훅 API를 통해 제공할 수 있다면? 개발자는 복잡한 설정이나 보일러플레이트 없이, 마치 useState
를 사용하듯 직관적으로 상태를 관리할 수 있게 된다.
const username = useStore(state => state.user.name);
이 얼마나 아름다운가! 간결함과 성능, 두 마리 토끼를 모두 잡는 것. React의 철학을 해치지 않으면서도, 개발자의 고통을 덜어주는 해결책.
“찾았다…”
카토의 입가에 희미한 미소가 번졌다. 길고 어두웠던 터널의 끝에서 마침내 한 줄기 빛을 발견한 기분이었다. 물론 아직 구체적인 구현 방법, 넘어야 할 기술적인 허들들이 남아있었다. 하지만 방향은 명확해졌다. 가슴이 뜨거워졌다.
영감의 순간은 그렇게 찾아왔다. Context라는 거대한 벽 앞에서 좌절했던 개발자 다이시 카토. 이제 그는 그 벽을 넘어설 자신만의 무기를 발견한 것이다. 남은 것은 이 아이디어를 현실로 만드는 것뿐이었다. 그의 손가락이 다시 키보드 위에서 춤출 준비를 하고 있었다. 새로운 역사가 쓰여질 시간이 다가오고 있었다.