Expo의 역사: SDK 0에서 CNG와 개발 빌드까지
Expo를 설명할 때 가장 자주 붙는 말은 "React Native를 쉽게 쓰게 해 주는 도구"입니다. 틀린 설명은 아니지만 지금의 Expo를 이해하기에는 범위가 너무 좁습니다. Expo는 미리 만들어진 앱에서 JavaScript를 실행하던 초기 경험을 출발점으로 삼았고, 지금은 네이티브 프로젝트 생성과 모듈 개발, 라우팅, 빌드 전 단계까지 다루는 React Native 프레임워크가 됐습니다.
저도 처음에는 Expo Go를 Expo 자체로 생각했습니다. 공식 SDK 연표와 현재 문서를 함께 읽어 보니 둘을 분리해서 봐야 역사가 보였습니다. Expo Go는 Expo를 경험하는 한 가지 실행 환경이고, Expo의 본체는 프로젝트를 구성하고 네이티브 앱으로 확장하는 도구와 라이브러리의 집합에 가깝습니다.
시작은 2015년의 SDK 0이었습니다
Expo는 2015년에 설립됐습니다. 공식 SDK 연표에는 Expo SDK 0이 2015년 8월 17일 공개된 것으로 기록돼 있습니다. 같은 해 11월 SDK 1이 나왔고, 2016년부터 2018년까지는 짧은 간격으로 SDK가 계속 갱신됐습니다.
초기 모델의 장점은 명확했습니다. 개발자가 Android Studio나 Xcode에서 매번 네이티브 앱을 컴파일하지 않아도, 공통 실행 앱에서 JavaScript 번들을 열어 카메라와 위치 같은 기기 API를 시험할 수 있었습니다. QR 코드로 프로젝트를 여는 경험도 모바일 개발의 진입 비용을 크게 낮췄습니다.
반대편에는 분명한 경계가 있었습니다. 공통 실행 앱 안에 들어 있지 않은 네이티브 라이브러리는 바로 추가할 수 없었습니다. 이 때문에 Expo는 오랫동안 "빠르게 시작할 수 있지만 복잡해지면 벗어나야 하는 도구"라는 인상을 남겼습니다. 당시의 Managed Workflow와 Bare Workflow 구분도 이 인식을 강화했습니다.
| 시기 | Expo에서 달라진 중심 |
|---|---|
| 2015년 | Expo 설립, SDK 0 공개 |
| 2016년부터 2019년 | Expo SDK와 공통 실행 앱을 중심으로 빠른 개발 경험 확장 |
| 2021년 | 개발 빌드와 EAS가 커지며 사용자별 네이티브 런타임을 만드는 흐름 확대 |
| 2022년부터 2023년 | Expo CLI, Prebuild, Config Plugin, Expo Modules와 Expo Router가 하나의 개발 흐름으로 정리 |
| 2024년 | SDK 51부터 Expo Go가 한 번에 하나의 SDK만 지원, 실제 제품에는 개발 빌드 사용 권장 |
| 2025년 이후 | 기존 React Native와 네이티브 앱으로 점진적 도입 범위 확대 |
Expo Go의 편리함이 곧 한계였습니다
Expo Go는 네이티브 기능이 미리 컴파일된 범용 앱입니다. 프로젝트의 JavaScript와 에셋을 내려받아 실행하므로 첫 화면을 확인할 때까지의 시간이 짧습니다. 학습, 프로토타입, Expo SDK에 포함된 API 검증에는 지금도 유용합니다.
하지만 네이티브 바이너리는 JavaScript처럼 실행 중에 바꿀 수 없습니다. 프로젝트가 Expo Go에 없는 네이티브 모듈을 설치하거나, 별도의 앱 확장과 권한 설정을 요구하면 프로젝트 전용 바이너리가 필요합니다. 예전에는 이 지점이 Expo를 떠나는 것처럼 느껴졌습니다.
개발 빌드는 이 경계를 바꿨습니다. expo-dev-client를 포함해 앱을 한 번 빌드하면 Expo Go와 비슷한 런처와 개발 메뉴를 사용하면서도, 그 프로젝트가 실제로 요구하는 네이티브 모듈을 모두 넣을 수 있습니다. JavaScript만 바뀌는 동안에는 같은 개발 빌드를 계속 사용하고, 네이티브 런타임이 바뀔 때만 다시 빌드합니다.
Expo가 SDK 51부터 Expo Go의 동시 지원 SDK 수를 하나로 줄이고 실제 제품 개발에는 개발 빌드를 권장한 이유도 여기에 있습니다. Expo Go는 완제품의 제약 조건이 아니라 빠른 학습용 샌드박스로 역할이 명확해졌습니다.
Eject 대신 네이티브 프로젝트를 생성합니다
현재 Expo의 핵심 변화는 Prebuild와 Continuous Native Generation, 줄여서 CNG에 있습니다. CNG는 android와 ios 디렉터리를 영구적인 원본으로 관리하는 대신, 더 작은 입력으로 필요할 때 생성하는 방식입니다.
입력은 Expo SDK 버전에 맞는 네이티브 템플릿, package.json, app.json 또는 app.config.ts, Config Plugin과 사용자 네이티브 코드입니다. npx expo prebuild는 이 입력을 조합해 Xcode와 Gradle이 빌드할 수 있는 프로젝트를 만듭니다.
네이티브 템플릿
+ 앱 설정
+ 설치한 패키지와 자동 연결 정보
+ Config Plugin
+ 필요한 사용자 네이티브 모듈
= Android와 iOS 프로젝트이 모델에서는 앱 이름, 아이콘, 권한, Info.plist, AndroidManifest.xml 같은 변경을 선언적인 설정과 플러그인으로 표현할 수 있습니다. 직접 만든 Swift나 Kotlin 코드가 필요하면 Expo Modules API로 프로젝트 안에 둘 수 있습니다. 네이티브 기능 하나 때문에 전체 프로젝트 관리 방식을 포기할 필요가 줄어든 셈입니다.
CNG가 필수인 것은 아닙니다. 이미 android와 ios 디렉터리를 세밀하게 관리하는 React Native 앱은 그 구조를 유지하면서 Expo SDK의 라이브러리나 EAS만 점진적으로 도입할 수 있습니다. 이 선택 가능성이 초기 Expo와 현재 Expo를 가르는 중요한 차이입니다.
Expo는 앱이 아니라 프레임워크입니다
현재 Expo를 이해할 때는 세 층을 나누는 편이 편합니다.
| 층 | 역할 |
|---|---|
| Expo SDK와 Modules | 카메라, 파일, 알림 같은 API와 네이티브 모듈 체계 |
| Expo CLI와 Router | 개발 서버, 번들링, 프로젝트 생성, 네이티브 생성과 화면 라우팅 |
| Expo Go와 개발 빌드 | JavaScript를 실제 기기에서 실행하는 두 가지 런타임 |
EAS는 이 프레임워크와 잘 연결되는 클라우드 서비스지만 Expo 자체와 같은 것은 아닙니다. 로컬에서 npx expo run:ios와 npx expo run:android로 빌드할 수도 있고, 다른 CI 환경을 사용할 수도 있습니다. 반대로 기존 React Native 프로젝트가 Expo의 모든 개발 방식을 채택하지 않고 EAS Build만 사용하는 것도 가능합니다.
제가 Expo를 다시 설명한다면 "네이티브 코드를 숨기는 도구"라고 부르지 않겠습니다. 지금의 Expo는 반복되는 네이티브 프로젝트 작업을 설정과 생성 과정으로 옮기고, 필요할 때는 Swift와 Kotlin까지 내려갈 수 있게 만든 React Native 프레임워크입니다. Expo Go에서 시작된 편리함은 남았지만, 제품의 방향은 공통 실행 앱의 경계를 넓히는 데서 프로젝트별 네이티브 앱을 재현 가능하게 만드는 쪽으로 이동했습니다.
공식 자료
함께 읽기
- EAS의 역사: 앱 빌드에서 모바일 배포 플랫폼까지EAS를 eas build 명령어의 이름으로만 이해하면 서비스의 절반만 보게 됩니다. EAS는 Expo Application Services의 약자입니다. 소스 코드를 앱 바이너리로 만들고, 스토어에 전달하고, 이미 설치된 앱에 호환되는 업데이트를 보내는 모바일 배포 과정을 여러 서비스로 나눈 플랫폼입니다.
- Expo SDK 56 iOS 빌드 오류와 Swift weak let 호환성저는 견적킷을 iPhone에서 실행하려다 xcodebuild 코드 65를 만났습니다. 빌드 화면에는 Reanimated와 Worklets 컴파일 로그가 길게 지나갔고, 마지막에는 오류 15개가 있다는 메시지만 남았습니다.
- 모바일 앱 백업 설계: 암호화를 걷어내고 이미지 복원을 고친 과정영업 자료를 단말 안에 보관하는 앱에 백업 기능을 붙였습니다. 저장 대상은 멘트, 사진, 문서, 링크, 정보 카드였습니다. 처음에는 백업 파일 전체를 비밀번호로 암호화했습니다. 백업이 앱 밖으로 나가니 당연한 선택처럼 보였습니다.
- Expo로 개발할 때 자주 쓰는 실행 명령어 모음Expo 앱을 개발하다 보면 명령어보다 “지금 다시 빌드해야 하나?”가 더 헷갈립니다. 화면 코드만 바꿨는데 Gradle 빌드를 다시 돌리기도 하고, 반대로 스플래시 이미지를 바꾼 뒤 Metro만 재시작해서 왜 그대로인지 한참 보기도 합니다.
- Name-kit: 모든 이름을 짓는 앱의 방향과 Expo SDK 57 전환처음 만들려고 했던 것은 크리스천 작명 앱이었습니다. 이름의 뜻과 신앙적 가치를 함께 살피는 도구를 생각했습니다. 그런데 방향을 구체화할수록 작명의 범위를 한 분야에만 묶을 이유가 없다는 쪽으로 생각이 바뀌었습니다.