3-8. React Native Inspector 26.01.03 ~ 26.02.09

웹 다음은 React Native

12월의 10일 스프린트로 웹 쪽은 어느 정도 완성됐다. 그런데 처음 배민 블로그를 보고 시작한 이유가 "웹뷰 원격 디버깅"이었으니, 진짜 모바일 환경에서 돌아가야 의미가 있다.

1월 3일부터 React Native Inspector 개발을 시작했다(PR #49). React Native 앱에 삽입되는 CDP 클라이언트를 별도 패키지(react-native-inspector)로 만드는 작업이다.

웹 클라이언트와의 차이

웹에서는 console.log를 후킹하고 fetch를 래핑하면 되지만, React Native는 상황이 다르다.

React Native의 console은 이미 LogBox 같은 것들이 후킹하고 있어서, 후킹 순서가 꼬이면 무한 루프에 빠지거나 로그가 안 뜨는 문제가 생긴다. 네트워크도 React Native의 fetch는 웹 표준 fetch와 미묘하게 다른 부분이 있어서, XHR 응답 헤더 수집이나 blob 응답 처리에서 삽질을 했다(PR #54, #57).

콘솔과 네트워크 후킹

웹 클라이언트에서 만든 ConsoleHook, NetworkHook을 React Native에 맞게 포팅했다. 파일이 너무 커져서 작은 파일로 분리하는 리팩토링도 했다(PR #50).

콘솔 객체를 DevTools에서 펼쳐볼 수 있게 하려면 Runtime.getProperties를 구현해야 했다(PR #67). 웹에서는 브라우저가 자동으로 해주는 건데, React Native에서는 직접 객체를 Map에 저장하고, objectId로 참조해서, getProperties 요청이 오면 해당 객체의 프로퍼티를 순회해서 응답하는 걸 수동으로 구현해야 했다.

Redux DevTools 통합

React Native 앱에서 Redux 디버깅을 하려면 별도 작업이 필요했다(PR #58, #61). __REDUX_DEVTOOLS_EXTENSION__을 폴리필로 제공해서, Redux 스토어가 CRD를 통해 디버깅되게 했다.

devtools-frontend에서도 Redux DevTools Extension UI를 임베드하는 작업을 했다(devtools-frontend PR #7, #8). Redux 액션/상태를 시간순으로 보고, 타임 트래블 디버깅까지 가능하게 만들었다.

MMKV와 AsyncStorage도 DevTools 패널에서 볼 수 있게 했다(PR #66). key-value 쌍을 보고 수정/삭제까지 되는 보드 UI를 만들었다.

서버를 Rust로 포팅

1월 13일, 큰 결정을 했다. WebSocket 릴레이 서버를 Bun(TypeScript)에서 Rust로 포팅한 거다(PR #70).

이유는 Tauri 통합 때문이었다. Tauri 앱 안에서 서버를 같이 돌리려면, Rust로 되어 있는 게 훨씬 자연스럽다. Tauri 자체가 Rust 기반이니까, 서버도 Rust면 하나의 바이너리에 다 넣을 수 있다.

서버 코드를 Rust로 재작성하고(PR #70), 모듈 구조로 분리하고(PR #71), e2e 테스트도 마이그레이션했다(PR #74). Rust 서버의 유닛/통합 테스트도 추가하고(PR #79), 커버리지 PR 코멘트도 Rust용으로 만들었다(PR #78).

JSI에서 JavaScript로

처음에는 React Native Inspector에서 일부 기능을 C++ JSI(JavaScript Interface)로 구현하려고 했다. 네이티브 레벨에서 성능이 좋으니까.

그런데 JSI 모듈은 iOS/Android 양쪽 빌드 설정이 복잡하고, CMake 경로 길이 제한(PR #68) 같은 플랫폼 이슈도 겪었다. iOS 빌드 에러(PR #76), Objective-C++ 컴파일 에러(PR #83) 같은 것들을 잡다 보니 "이거 네이티브까지 갈 필요가 있나?" 하는 생각이 들었다.

결국 JSI를 걷어내고 순수 JavaScript로 전환했다(PR #90, #92). 콘솔과 네트워크 후킹은 JS 레벨에서 충분히 가능하고, 네이티브 C++ 코드를 유지보수하는 비용이 JS보다 훨씬 크다는 판단이었다. 이 결정으로 패키지가 훨씬 가벼워졌고, 빌드 문제도 사라졌다.

RN Inspector v0.1.0-rc.1 릴리스

2월 9일, chrome-remote-devtools-rn-inspector v0.1.0-rc.1을 릴리스했다.

이 시점에서 React Native Inspector가 지원하는 기능:

  • Console 로그 (객체 펼쳐보기 포함)
  • Network 요청/응답 (responseBody 포함)
  • Redux DevTools (타임 트래블)
  • MMKV / AsyncStorage 보드
  • React DevTools Components / Profiler 패널(PR #102)
  • deviceId 기반 클라이언트 식별(PR #110)
  • WebSocket 재연결 / graceful shutdown(PR #83)
  • Metro 프록시 연동(PR #115, #118)

웹에서 시작한 프로젝트가 React Native까지 확장되는 데 약 한 달 반이 걸렸다. 그 과정에서 JSI를 넣었다가 뺐고, 서버를 Rust로 바꿨고, 네이티브 빌드 이슈를 수없이 겪었다. 삽질의 연속이었지만, 결과적으로는 웹과 React Native 모두에서 같은 DevTools 경험을 제공하는 도구가 됐다.

1줄 요약

React Native Inspector를 별도 패키지로 개발하고, 서버를 Rust로 포팅하고, JSI를 걷어내고 JS-only로 전환해서, 2월 9일에 v0.1.0-rc.1을 릴리스했다.