3. 개발 과정

시작은 '따라하기'였지만

처음 시작했을 때는 명확한 목적이 있었든 없든, 일단 배민 블로그를 따라 해서 "CDP로 웹뷰를 마냥 재현할 수 있다"는 것까지는 만들었다.

그런데 만들고 나서야 이게 정말 중요한 것 같은데, 왜 이걸 먼저 하지 않았는지 하는 생각이 계속 들게 됐다.

CDP 클라이언트와 WebSocket 서버가 동작하니까 "이거 끝인가? 이거 아무도 쓸 거 없었을까?" 하는 생각도 들었다. 그리고 "나는 무슨 개발인지"에 대해 계속 고민하게 됐다.

그리고 배민 블로그에서 "기록방 URL로 당시 콘솔·네트워크·DOM을 다시 볼 수 있다"는 건 너무 강력했다. 그런데 이걸 딱 반복만 하는 수준이 아니라, "이 기능을 나도 해봐야지" 싶은 욕심이 생겨났다.

그게 다음 단계로 이어졌다.


3-tier 구조의 완성

초반에 설계할 때는 3-tier 구조를 명확히 잡고 싶었다. 웹 클라이언트, WebSocket 서버, Inspector.

이게 단순히 아키텍처일까? 아니면 나의 근성을 관리하는 방식일까.

[웹 클라이언트] ←→ [WebSocket 중계 서버] ←→ [Inspector]

각 계층이 독립적으로 동작할 수 있게 만들었다. 중간에 하나만 바꿔도 전체가 동작하지 않으면 디버깅하기 쉽고, 배포 전후에도 유지보수가 용이하게 설계되었다.

특히 Inspector는 React 기반으로 구현했고, 클라이언트는 Vite를 기본으로 쓰게 했다. 번들러 선택은 웹과 React Native 간의 호환성을 고려해서 Vite로 정했다. 처음엔 Webpack을 써보려다가도, HMR 동작 방식이나 설정이 꼬이는 걸 봐가면서 Vite로 넘어갔다.


'따라하기'에서 '나만의 것'으로

일단 기능을 다 만들어놓고 나서야 진짜 생각할 거리가 생긴다. 이게 배민 걸 그대로 따라한 건가, 아니면 나만의 것이 된 건가.

"배민 기술 블로그를 따라 해봤다"라고 쓰기엔, 내가 직접 겪은 문제들, 네이티브를 걷어내면서 얻은 감각, 커스텀 패널을 만들면서 배운 건 더 많았다.

다만 배민이나 카카오 같은 대기업 기술 블로그는 정말 잘 만들어져 있다는 걸 느껴야 했다. 그들도 점진적으로 개선하고 있었지만, 기본적인 인프라부터 깊게 쌓아놓고 있었다는 걸 확인할 수 있었다.


기능 쌓이고 순서가 바뀌기 시작함

초반에 구현한 기능들은 그냥 다 만들어놨다. CDP 클라이언트, WebSocket 서버, Console·Network·DOM 탐색, Redux DevTools, MMKV/AsyncStorage 보드, React Component Tree, 배민의 "패널 자동 열기" 기능 흉내 등등.

그런데 순서대로 하다가 중간에 바뀌는 순간이 왔다. "이거 나중에 이렇게 하면 편할 것 같은데" 하는 욕심이 생긴 거다.

그래서 기본 기능부터 다 쌓아 올리느라 "이거 나중에 커스텀 패널이라도 만들어야지" 하고 잠깐 생각했지만, 실제로 만들고 나서야 "야 이거 왜 이제 만드는지" 하는 게 많더라.

그래서 기능 순서를 바꿨다. 배민에서 한 것을 다 따라 하다 보니, 이제는 내가 주도적으로 어떤 기능이 필요하고 어떤 우선순위가 있는지 정하는 단계로 넘어갔다.


네이티브 의존성 걷어내기

React Native에서 CRD를 쓰면서 뭔가 이상하다 싶은 게 있었다.

"나는 웹 환경에서 웹서핑해서 알게 된 걸 좋아한다"는 걸 명심하면서, 그것도 React Native로만 쓰는 디버깅 툴을 고집하고 있던 게 눈에 띄었다.

거울 보고 있었나? 라고 생각하면서, 일단은 네이티브 의존성을 하나씩 빼보기로 했다.

완전히 새로운 패키지를 만들어서 웹에서만 돌아가는 Inspector로 구현했다. UI만 공유하고, 데이터 출처는 플랫폼마다 다르게 받도록 했다. React Native용 Native 모듈은 최소화해서, 웹에서 그대로 써보려는 걸로 마음을 정했다.

이건 너무 큰 깨달음이었다. 나는 이제 React Native를 쓰지 않고도 CRD를 만들어서 React Native를 쓴다.


커스텀 패널이라는 깎아지르는 싸움

기본 기능을 다 쌓아 올렸을 때, 개발할 때 귀찮은 걸 다 외워서 직접 만들어 쓰는 걸 좋아한다. 표준기능으로는 안 되는 걸 만들어서 쓰는데, 그게 너무 재밌어서 계속 만들고 있더라.

커스텀 패널이란, 브라우저 DevTools 기본 UI를 확장해서 내가 원하는 걸 보여주는 패널을 만드는 거다.

기본적으로 패널을 만들기 시작했지만, DevTools Extension을 쓰는 방식이지만, 실제로는 React를 사용해서 구현해서 React 라이프사이클 문제도 겪었다. CDP 메시지를 받아서 각 패널별로 렌더링하는데, 메시지 핸들러가 하나에 다 들어가면 코드가 너무 복잡해진다.

각 패널마다 별도의 메시지 핸들러를 만들고, CDP 서버에서는 해당 패널로만 메시지를 보내도록 구성을 변경했다. 그게 마침내 멀티 뷰 패널을 만드는 성공적인 결정이 됐다.


번들러가 주는 DX

번들러 학습을 하면서 가장 큰 깨달음 중 하나는, "이거 다 뒤지고 맞물려 있는데 나는 아예 모르겠네"였다.

Webpack, Vite, Metro 번들러를 각각 써보면서 환경이 어떻게 연결되는지, 빌드 속도나 HMR 동작에서 얼마나 많은 차이가 나는지 깊게 공부했다.

결국 번들러는 "이걸 쓰고 싶어" 하는 선택이 아니라 "이걸 쓰면 이런 환경이 되고, 그게 나의 개발 철학과 얼마나 잘 어울리는가"를 따져 결정해야 한다는 걸 배웠다.

CRD도 결국 개발 환경의 일부니까, 내가 쓸 번들러에 맞춰 CRD 자체를 설계·구현하면 DX가 급상승하는 걸 확인했다.


완성 전후

기본 기능 다 쌓고, 네이티브 걷어내고, 커스텀 패널까지 만들고 나니, 이제야 진짜 CRD라는 걸 이해하기 시작했다.

이건 배민 따라 하던 그냥 복제본이 아니라, 웹과 React Native 양쪽에서 모두 사용하는 공통 툴이 되었다.

웹에서는 CDP 클라이언트만 있으면 끝이고, React Native에서는 필요한 네이티브 기능만 있다.

아니, 정확히 말하면 이제는 React Native에 의존해서 CRD를 쓰는 게 아니라, CRD를 만들어서 React Native를 쓴다는 느낌일 것이다.


남은 과제

이 과제들을 해결하기 위해서는 배민이나 다른 트렌디한 프로젝트가 다시 불규칙하게 떠오르기 전에, 이걸 얼마나 깊게 파고들 수 있을지가 핵심이다.

그리고 배민 기술 블로그에서 말한 "개발 '백로그에서 골치 아팠다'는 말을 기억하면, 끝이 아닌 계속 진행 중이라는 걸 다시 상기시킬 수 있다.

1줄 요약

시작은 배민 따라 하기였지만, 3-tier 구조 완성, 네이티브 걷어내기, 커스텀 패널 구현, 번들러 학습 등의 과정을 거치며 웹과 React Native 양쪽에서 모두 사용하는 공통 툴이 되었다. 이제 남은 과제는 성능 최적화와 추가 기능을 얼마나 깊게 파고들 수 있을지가 핵심이다.