React Native의 파일 변경 감지 서비스 watchman

eeensu·2026년 3월 7일

React Native

목록 보기
18/41

RN에서 Watchman은 Metro bundler(React Native의 기본 JS 번들러)가 파일 변경을 빠르고 효율적으로 감지하기 위해 사용하는 파일 감시(file watching) 서비스이다. Meta가 만든 오픈소스 도구로, RN 개발환경을 Hot reload가 되어 부드럽게 만들어주는 핵심 백그라운드 프로세스 중 하나이다. React Native CLI로 프로젝트를 생성하면 자동으로 Watchman을 사용하기에 별도의 설치는 필요 없다.


Watchman 이 하는 일

  1. 개발자가 코드 수정 → 파일 저장
  2. Watchman이 변경 감지
  3. Metro Bundler에게 알림
  4. Metro가 변경된 파일만 다시 번들링
  5. Fast Refresh로 앱에 반영 (새로고침 없이)

왜 Node js 내장 감시기를 안 쓰고 watchman을 쓸까?

// Node.js 기본 fs.watch
fs.watch('./src', { recursive: true }, (eventType, filename) => {
  console.log(`${filename} changed`);
});

문제점은 아래와 같다.

  • node_modules (수만 개 파일) 감시 시 메모리가 폭발
  • 대규모 프로젝트에서 CPU 과부하
  • OS마다 동작 방식이 다름 (크로스 플랫폼 문제)
  • 파일 변경 이벤트가 중복 발생


Watchman 설정 파일

프로젝트 루트에 있는 .watchmanconfig 에서 설정하며, React Native 프로젝트에는 자동으로 생성되지만, 커스터마이징 가능하다. ignore_dirs 에 추천되는 폴더 및 파일들은 아래와 같다.

{
  "ignore_dirs": [
    ".git",
    "android/build",
    "android/app/build",
    "android/.gradle",
    "ios/build",
    "ios/Pods",
    "coverage",
    "vendor"
  ],
  "settle": 20
}
  • .git: 버전 관리를 위해 매우 빈번하게 내부 파일이 변경되는 폴더지만, React Native 번들링 과정에는 전혀 관여하지 않으므로 감시할 필요가 없다.

  • android/build, android/app/build, android/.gradle: 안드로이드 빌드 과정에서 수많은 임시 파일과 중간 산출물(Artifacts)이 생성됩니다. 이들은 Java/Kotlin 코드가 컴파일된 결과물이므로 앱을 실행할 때 Metro 번들러가 감시할 필요가 없다.

  • ios/build: iOS(Xcode) 빌드 시 생성되는 폴더로, 위와 동일한 이유로 무시 목록에 넣는다.

  • ios/Pods: CocoaPods로 설치된 iOS 네이티브 라이브러리들입니다. 이 폴더 안에 있는 소스는 보통 직접 수정하지 않기 때문에 감시를 꺼두면 성능 향상에 도움이 된다.

  • coverage: Jest 같은 테스트 도구가 코드 커버리지를 계산하고 결과를 저장할 때 만들어지는 폴더이므로 제외한다.

  • vendor: (선택) 만약 프로젝트 내에서 Fastlane이나 Ruby Gem을 사용할 때 생기는 플러그인 폴더이다.

  • node_modules 는 넣지 않는다. Metro 번들러가 우리가 설치한 외부 패키지들을 찾거나, 패키지의 캐시를 생성하고 의존성을 따라가기 위해 Watchman을 사용하기 때문입니다. node_modules를 여기에 추가하면 React Native 앱 빌드 또는 Fast Refresh 과정에서 오류가 발생할 수 있어 무시 목록에 넣지 않는 것이 좋다.



그럼 Watchman이 저 폴더의 파일들을 감시하지 않으면 리스크가 있을까?

이 설정 때문에 개발이 안 된다거나 제약이 생기는 일은 전혀 없으며, 리스크도 없다. 오히려 메타(Meta)와 React Native 커뮤니티에서 공식적으로 권장하는 최적화 방법(Best Practice)이다. Watchman의 유일한 목적은 "코드를 수정했을 때, 그 변경 사항을 감지해서 앱 화면에 바로 띄워주기 위함(Fast Refresh)"이다.

방금 제외한 폴더들은 우리가 "직접 코드를 타이핑해서 수정하는 폴더"가 절대 아니기 때문에 Watchman이 감시할 필요가 없다. 대부분 빌드 후 생성되는 결과물 / 네이티브 라이브러리 코드 / git과 같은 소스코드 버전 관리 폴더이기 때문이다.



.watchmanconfig 설정파일에 아무것도 설정하지 않았다면?

Watchman이라는 도구는 에뮬레이터나 시뮬레이터 '내부'에서 동작하는 것이 아니라, 개발자의 PC(Host OS) 백그라운드에서 동작한다. 따라서 앱 자체의 렌더링 성능(프레임 저하, 애니메이션 버벅임 등)이나 가상 기기 자체를 직접적으로 느려지게 만드는 것은 아니다.

하지만 개발 중일 때, android 애뮬레이터, ios 시뮬레이터의 속도가 느리다면, .watchmanconfig 에 아무것도 설정하지 않았던 것이 원인의 일부일 수 있다. Watchman이 프로젝트 내의 수만 개의 불필요한 파일들까지 모조리 감시하고 있었다는 뜻이기 때문이다.

  • PC의 CPU와 램 자원 낭비
    android/build, ios/build, ios/Pods, .git 폴더 등에는 앱 빌드 시 수만 개의 파일이 생성되고 또 지워진다. Watchman이 이 쓸데없는 파일 변화를 모두 추적하느라 개발자의 PC의 CPU와 RAM(메모리)을 엄청나게 소모하게 된다.

  • 에뮬레이터 자원 부족 현상
    안드로이드 에뮬레이터나 iOS 시뮬레이터는 기본적으로 PC 자원(CPU, 램)을 굉장히 많이 먹는 무거운 프로그램이다. 그런데 백그라운드에서 Watchman이 자원을 다 뺏어가 버리니, 에뮬레이터가 사용할 자원이 부족해져서 엄청나게 버벅거리고 멈추는 현상이 발생했을 수 있다.




pnpm start --reset-cache 와의 관계?

흔히 RN 개발환경에서 캐시 오류또는 여러 원인의 문제가 생겨 코드가 반영이 안될 때, metro 를 재시작하곤한다. 이때 npm start --reset-cache 명령어를 치는데, 이러한 상황에선 Watchman 과 어떤 관련이 있을까?

1. pnpm start --reset-cache의 정확한 역할

이 명령어는 Metro Bundler의 내부 캐시를 삭제하는 명령어다. Watchman의 캐시를 삭제하는 게 아니다.

Metro Bundler는 빌드 속도를 높이기 위해 두 가지를 캐싱(저장)해 둔다.

  • 변환 캐시 (Transform Cache) : ES6 / TypeScript 코드를 ES5로 변환한 결과물.
  • 의존성 그래프 (Dependency Graph) : A 파일이 B 파일을 import 하고 있다는 관계도.

--reset-cache를 입력하면, Metro는 이 두 가지 데이터를 메모리와 디스크(tmp 폴더)에서 즉시 삭제한다.


2. Watchman과의 관계 (트리거)

  1. Metro의 캐시가 사라졌다.
  2. Metro는 앱을 다시 빌드하기 위해, 프로젝트 내의 모든 파일 목록과 의존성 관계를 처음부터 다시 파악해야 한다.
  3. Metro는 파일 시스템의 현재 상태를 알기 위해 Watchman에게 "지금 파일 목록 전체랑 변경 사항 다시 다 줘!"라고 요청한다.
  4. 이 과정에서 Watchman이 혹시 놓쳤던 파일 변경 사항이나, Metro가 잘못 기억하고 있던 파일 경로가 강제로 최신 상태로 동기화(Sync)된다.

즉, "Metro의 기억을 지워서 Watchman에게 다시 물어보게 만드는 것"이다. 그래서 반영 안 되던 파일이 반영되는 것이다.

profile
안녕하세요! 프론트엔드 개발자입니다! (2024/03 ~)

0개의 댓글