사이드 프로젝트에서 Expo를 사용하고 있는데 개념적인 부분들과 실제 겪었던 문제들을 정리해봤다.
EXPO란 무엇인가?
Expo는 React Native 기반 앱을 더 쉽게, 더 빠르게 개발할 수 있도록 도와주는 풀스택 앱 개발 플랫폼이다.
React Native 자체는 강력하지만, iOS/Android 네이티브 설정, 빌드 환경 구성, 인증서 관리, OTA 업데이트 등
신경 써야 할 부분이 너무 많다.
내가 실제 EXPO를 써보면서 느낀 장점은 다음과 같다:
1.개발 속도 극대화
개발 중 앱을 다시 빌드할 필요 없이 바로 반영되는 Fast Refresh.
앱쪽 로직을 수정해도 바로 바로 변경사항을 반영시켜서 테스트할 수 있음.
2. 네이티브 환경을 몰라도 앱 빌드 가능
Xcode/Android Studio 를 직접 다루지 않아도 됨.
네이티브 라이브러리를 자동으로 설정해줌.
3. EAS(Build/Submit/Update)로 완전 자동화된 CI/CD
EAS Build → iOS/Android 빌드 자동화
EAS Submit → 앱스토어 제출 자동화
단점은 그만큼 캡슐화된 기능들이 많다보니 처음 어떤 원리로 어떻게 동작하는지 이해가 안돼 헤매는 부분이 많았다. 아직도 정확하게 알지 못하는 부분이 많다.
Expo는 확실히 빠르게 앱을 만들기에 좋은 생태계지만, 환경변수 / config / 빌드 환경 같은 부분은 헷갈리기 쉽고 문서도 애매한 부분이 많아서 꽤 시간을 썼다.
📌 이슈 1) 환경변수(EAS Env) 주입이 되지 않는 문제
Expo/EAS 환경에서 개발 환경을 development / staging / production 총 3개로 나눠서 사용하고 있었다.
각 환경마다 WebView URL 이 달라서 env 값으로 주입하려고 했는데, development 환경에서 env 가 적용되지 않는 문제가 발생했다.
🔍 원인: developmentClient: true 때문
EAS Build 에서 환경변수를 주입하는 방식은 크게 두 가지다:
- .env 파일 기반 (eas build --local 에서만 완전함)
- eas.json → env → 앱으로 주입
그런데 문제는…
developmentClient: true 로 설정하면 EAS가 env를 “절대” 주입하지 않는다.
Development Client는 Expo Go 기반의 dev client를 만드는 용도라 실제 EAS 빌드 환경처럼 config & environment 가 반영되지 않는다.
그래서 아래처럼 eas.json 에 env 를 넣어도:
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"env": {
"EXPO_PUBLIC_WEB_URL": "<https://develop.example.com>"
}
}
}
➡ EXPO_PUBLIC_WEB_URL은 앱 안에서 인식되지 않는다.
🔧 해결 방법: fallback URL 적용
그래서 다음처럼 “환경변수 없을 때 fallback URL로 대체”하는 방식을 사용했다.
const webUrl =
process.env.EXPO_PUBLIC_WEB_URL ||
"<https://develop.d3lu9ioxm4rpwm.amplifyapp.com>";
- developmentClient: true → EAS env 미적용 → fallback URL 사용
- staging/production → EAS가 주입한 env 사용
이렇게 하면 development Client에서 실행할 때도 문제가 없다.
📌 핵심 사항 요약
- developmentClient: true
- → EAS가 env 주입도 하지 않고, app.config.js 의 extra도 반영되지 않는다
- dev client는 Expo Go의 확장판으로 규칙이 다르다.
- staging/production 환경처럼 정확한 빌드 환경을 반영하고 싶다면 dev client 사용을 피해야 함.
✔️ 올바른 해결 전략
방법 1) 개발 환경도 .env 기반으로 관리
- dotenv 설치
- app.config.js 에서 dotenv 불러오기
- 로컬 dev 전용으로 명확하게 분리 가능
방법 2) developmentClient 제거
- 개발이라도 빌드된 앱에서 정확한 env 를 확인해야 한다면 이 방법이 유리함
- 특히, WebView URL / API Endpoint 같이 민감하지 않은 값에 적합
📌 이슈 2) GoogleService-Info.plist 는 절대 gitignore 하면 안됨
처음에 보안적 이유로 Firebase의 GoogleService-Info.plist 를 .gitignore 에 넣었는데,
EAS 빌드 시 이 파일이 없으면 iOS 빌드가 거의 100% 실패한다.
이유:
EAS 빌드는 완전히 새로운 환경(클린)에서 돌아가므로,
로컬에 있는 파일을 가져가지 않으며 Git 에 있는 파일만 그대로 사용한다.
따라서 GoogleService-Info.plist 는 반드시 리포지토리에 포함해야 한다.
(보안이 걱정된다면 private repository를 사용하면 됨)
📌 기타 팁
1) 앱 버전 가져오기 — Constants.expoConfig.version
import Constants from "expo-constants";
const appVersion = Constants.expoConfig.version;
- app.json / app.config.js 의 "version" 값을 가져오는 것
- 실제 디바이스 설치 앱의 버전과 동일
- EAS Build 환경에서도 정상적으로 동작함
💡 따라서 강제 업데이트 / 버전 체크 구현할 때 쓰기 좋다.
2) Expo / EAS 에서 Build ID 확인하는 방법
CLI
eas build:list
Dashboard
EAS Dashboard → Builds → 각 빌드 클릭 → 상단의 Build ID 확인 가능
💡 오류 트래킹 / 배포 이슈 대응 시 특정 빌드로 바로 찾기 편함.
✨ 결론
Expo/EAS 를 쓰다 보면 가장 헷갈리는 부분이 env 주입 + developmentClient 차이인 것 같다.
정리하자면:
- developmentClient = dev 전용, env 안 들어옴
- staging/production 빌드는 env 잘 들어옴
- Firebase plist 는 절대 gitignore 하면 안 됨
- 버전 정보는 expoConfig에서 안정적으로 가져올 수 있음
'Dev Log' 카테고리의 다른 글
| API 개발 과정에서 반복되는 SQL 질문 (1) | 2025.12.07 |
|---|---|
| 서버 Yaml 파일 개념 정리 (2) | 2025.11.26 |
| 채널톡 연동 과정 정리 (0) | 2025.11.09 |
| Spring + MyBatis 기반 개인정보 암호화/복호화 과정 정리 (0) | 2025.11.02 |
| SQL 기본 개념 정리2 (0) | 2025.10.26 |