FEInterview Prep

토스 · FEConf 2023 2023

React Native, Metro를 넘어서

Metro 번들러의 한계를 극복한 토스의 React Native 빌드 최적화 여정 (발표: 박서진, 토스)

React NativeMetro번들러모바일

요약

핵심 토픽

번들러ESBuildMetroReact NativeTree Shaking

학습 포인트

1. 번들러의 세 단계: Resolution, Load, Optimization

모든 번들러는 동일한 세 단계를 구현합니다. (1) Resolution — `import './utils'`를 `/src/utils/index.ts` 같은 실제 파일 경로로 해석. node_modules 탐색, alias 설정, tsconfig paths 해석이 이 단계에서 일어납니다. (2) Load — 파일을 읽고 브라우저가 이해하는 형태로 변환. TS→JS, JSX→JS, SVG→컴포넌트 변환이 여기서 발생합니다. (3) Optimization — Tree Shaking으로 미사용 코드 제거, minify로 압축. Webpack, ESBuild, Metro, Rollup, Vite 모두 이 세 단계를 구현합니다.

핵심 용어

ResolutionLoadOptimization의존성 그래프트랜스파일

2. Metro 번들러의 한계

Metro는 Meta가 React Native를 위해 만든 전용 번들러로, JavaScript 런타임(Node.js)에서 동작합니다. 주요 한계: (1) 빌드 속도 — Node.js 기반의 직렬 처리로 대형 프로젝트에서 수 분이 걸림, (2) 캐시 불안정 — 캐시 키 계산 오류로 `--reset-cache` 없이 빌드가 실패하는 경우가 잦음, (3) Tree Shaking 미지원 — 현대적 최적화 기법 부재로 번들 사이즈 최적화 불가, (4) CJS 중심 — CommonJS 모듈 시스템 기반이라 ESM 최적화 불가.

핵심 용어

Metro--reset-cache캐시 불안정CommonJS빌드 속도

3. ESBuild의 성능 비결

ESBuild는 Go 언어로 작성되어 멀티코어를 최대한 활용하고, 파싱·변환을 한 번의 AST 순회로 처리합니다. Webpack과 비교 시 10~100배 빠른 속도를 자랑합니다. 제약: TypeScript의 타입 검사를 수행하지 않고(트랜스파일만), 일부 복잡한 코드 변환(예: 데코레이터)은 지원하지 않습니다. Metro 교체 시 `customResolver`와 `customTransformer`를 구현해 ESBuild를 Load 단계에 끼워 넣으면 Metro의 React Native 생태계 호환성을 유지하면서 성능을 높일 수 있습니다.

핵심 용어

Go 언어멀티코어 병렬처리단일 AST 순회customTransformer타입 검사 분리

4. Vite의 번들 전략과 개발 서버 최적화

Vite는 개발 환경과 프로덕션 환경을 분리합니다. 개발 서버: ESBuild로 의존성만 사전 번들링하고, 소스 코드는 ESM 네이티브로 브라우저에 직접 서빙. HMR은 변경된 모듈만 교체해 전체 재빌드가 불필요합니다. 프로덕션 빌드: Rollup으로 최적화된 청크 생성(Tree Shaking, 코드 스플리팅). '왜 개발 서버가 빠른가': 번들 없이 브라우저의 ESM import로 필요한 모듈만 로드하기 때문입니다.

핵심 용어

Vite사전 번들링ESM 네이티브HMRRollup

면접 질문

중급

Q1. Webpack과 Vite의 번들 방식 차이와 Vite가 개발 서버에서 빠른 이유를 설명해 주세요.

힌트

[감점 답변] 정의만 반복하거나 "Webpack과 Vite의 번들 방식 차이와 Vite가 개발 서버에서 빠른 이유를 설명해 주세요."에 대해 장단점 없이 단편적으로 답하면 감점 포인트입니다. 면접관은 실무 적용 경험이 부족하다고 판단합니다. [좋은 답변] Webpack은 모든 모듈을 번들링한 후 서빙하는 방식이라 파일이 많을수록 느려집니다. Vite는 의존성(node_modules)만 ESBuild로 사전 번들링하고, 소스 코드는 번들링 없이 브라우저 ESM으로 직접 서빙합니다. HMR도 변경된 모듈만 교체해 재빌드 범위를 최소화합니다. '파일 수가 늘어도 초기 서버 시작 속도가 거의 변하지 않는다'는 점도 언급하면 좋습니다.

초급

Q2. 번들러에서 Resolution 단계가 왜 중요한가요?

힌트

[감점 답변] 정의만 반복하거나 "번들러에서 Resolution 단계가 왜 중요한가요?"에 대해 장단점 없이 단편적으로 답하면 감점 포인트입니다. 면접관은 실무 적용 경험이 부족하다고 판단합니다. [좋은 답변] Resolution 없이는 `import './utils'`가 실제로 어떤 파일인지 알 수 없다는 점을 먼저 설명하세요. 그다음 Resolution 설정이 중요한 실무 케이스를 설명하세요: tsconfig의 paths alias(`@/` → `src/`), node_modules에서 특정 버전 강제 선택(webpack alias), 플랫폼별 확장자 처리(.web.ts, .native.ts). 잘못된 Resolution 설정이 '파일을 찾지 못했다' 에러로 이어진다는 점도 언급하면 됩니다.

고급

Q3. 번들러를 직접 구현한다면 어떻게 시작하시겠어요?

힌트

[감점 답변] 정의만 반복하거나 "번들러를 직접 구현한다면 어떻게 시작하시겠어요?"에 대해 장단점 없이 단편적으로 답하면 감점 포인트입니다. 면접관은 실무 적용 경험이 부족하다고 판단합니다. [좋은 답변] 세 단계를 순서대로 구현한다고 설명하세요: (1) Resolution — 엔트리 파일에서 import 구문을 파싱해 의존성 그래프 생성, (2) Load — 각 파일을 읽어 브라우저가 이해하는 JS로 변환(필요시 Babel/tsc 활용), (3) Bundle — 의존성 그래프 순서대로 모듈을 하나의 파일에 합치되 각 모듈을 함수로 감싸 스코프를 격리. 이 세 단계가 100줄짜리 미니 번들러의 핵심 구조임을 설명하면 됩니다.

중급

Q4. ESBuild가 빠른 이유와 한계점은 무엇인가요?

힌트

[감점 답변] 정의만 반복하거나 "ESBuild가 빠른 이유와 한계점은 무엇인가요?"에 대해 장단점 없이 단편적으로 답하면 감점 포인트입니다. 면접관은 실무 적용 경험이 부족하다고 판단합니다. [좋은 답변] 빠른 이유: Go 언어로 멀티코어 병렬 처리, 파싱부터 변환까지 단일 AST 순회, 메모리 효율적인 자료구조. 한계: TypeScript 타입 검사를 하지 않음(트랜스파일만), 데코레이터 등 복잡한 변환 미지원, 플러그인 생태계가 Webpack보다 작음. 실무에서는 ESBuild를 빠른 트랜스파일에만 쓰고 tsc --noEmit으로 별도 타입 검사를 하는 방식이 일반적임을 언급하면 됩니다.

고급

Q5. React Native 프로젝트에서 빌드 성능을 개선하는 방법은?

힌트

[감점 답변] 정의만 반복하거나 "React Native 프로젝트에서 빌드 성능을 개선하는 방법은?"에 대해 장단점 없이 단편적으로 답하면 감점 포인트입니다. 면접관은 실무 적용 경험이 부족하다고 판단합니다. [좋은 답변] 여러 레이어로 설명하세요: 번들러 레벨(Metro → ESBuild 교체, Tree Shaking 도입), 코드 레벨(사용하지 않는 import 제거, lodash-es 같은 ESM 라이브러리 사용), 캐시 레벨(Metro 캐시 설정 최적화, CI 캐시), Hermes 엔진(바이트코드 사전 컴파일로 앱 시작 속도 향상). 각 방법의 효과 크기도 비교하면 좋습니다.

선행 학습

  • JavaScript 모듈 시스템(ESM, CommonJS) 차이
  • Webpack 기본 설정 경험
  • React Native 기초 개념

핵심 타임스탬프

번들러 핵심 구간00:00 - 03:00
ESBuild 핵심 구간03:00 - 07:00
Metro 핵심 구간07:00 - 12:00
React Native 핵심 구간12:00 - 17:00

학습 방법

1단계: 아주 간단한 미니 번들러를 직접 구현해보세요. `require` 구문을 정규식으로 파싱해 의존성 목록을 만들고, 각 파일을 읽어 하나의 파일에 합치는 100줄짜리 스크립트를 완성하면 Resolution과 Load 단계를 깊이 이해할 수 있습니다. 2단계: webpack-bundle-analyzer 또는 `vite --build && npx vite-bundle-visualizer`로 본인 프로젝트의 번들을 시각화하고 가장 큰 패키지를 분석해보세요. 3단계: ESBuild로 TypeScript 파일을 트랜스파일하는 간단한 스크립트를 작성해보고, Rollup으로 ESM 라이브러리를 번들링해보면 번들러별 특성이 명확해집니다. 4단계: 동료에게 "번들러"의 핵심을 5분 안에 설명해보세요. 막히는 부분이 아직 구조적으로 이해되지 않은 지점입니다.