본문 바로가기

Coding/개발

iOS 시뮬레이터와 Firebase Emulator 간의 통신 문제 해결 보고서

문제 상황

Flutter 프로젝트에서 Firebase Emulator를 활용한 개발 환경을 설정하는 중, iOS 시뮬레이터에서 Firebase Emulator와의 통신 문제로 인해 다음과 같은 상황이 발생:

  • iOS 시뮬레이터에서 localhost를 사용하여 Firebase Emulator와 통신 시 연결 실패
  • 앱 실행 시 Firebase Emulator 설정이 제대로 적용되지 않아 Firebase 기능(Firestore, Functions, Storage 등) 호출이 정상적으로 이루어지지 않음
  • 흰 화면 상태에서 앱이 멈추거나, 통신 실패와 관련된 에러 로그 출력

 

문제 원인 분석

  1. localhost와 127.0.0.1의 차이
    • iOS 시뮬레이터는 localhost를 호스트로 사용할 경우, 실제 머신(Host Machine)이 아닌 시뮬레이터 자체를 참조.
    • 따라서 Firebase Emulator가 실제 머신에서 실행되고 있는 경우, iOS 시뮬레이터는 이를 인식하지 못하고 통신 실패.
  2. 환경 변수 설정 문제
    • .env.development 파일에서 FIREBASE_EMULATOR_HOST 값이 localhost로 설정되어 있음.
    • 이로 인해 앱 내 Firebase Emulator 초기화 코드에서 잘못된 호스트 값을 참조.
  3. Firebase Emulator 초기화 코드의 기본값 미설정
    • FirebaseFunctions 및 FirebaseStorage의 초기화 과정에서 기본값으로 localhost가 사용됨.
    • iOS 시뮬레이터에서 이 기본값을 변경하지 않으면 통신 문제가 발생.

문제 해결 과정

1. FIREBASE_EMULATOR_HOST 값 수정

.env.development 파일에서 FIREBASE_EMULATOR_HOST 값을 127.0.0.1로 변경:

 

FIREBASE_EMULATOR_HOST=127.0.0.1

 

  • 127.0.0.1은 호스트 머신을 참조하며, iOS 시뮬레이터에서도 이를 올바르게 인식할 수 있음.

2. Firebase Emulator 초기화 코드 수정

main.dart 파일의 Firebase Emulator 초기화 코드에서 localhost를 사용하던 부분을 FIREBASE_EMULATOR_HOST 값으로 대체:

 

FirebaseFirestore.instance.settings = Settings(
  host: '${dotenv.env['FIREBASE_EMULATOR_HOST']}:${dotenv.env['FIREBASE_FIRESTORE_PORT'] ?? '8080'}',
  sslEnabled: false,
  persistenceEnabled: false,
);

FirebaseFunctions.instance.useFunctionsEmulator(
  dotenv.env['FIREBASE_EMULATOR_HOST'] ?? '127.0.0.1',
  int.parse(dotenv.env['FIREBASE_FUNCTIONS_PORT'] ?? '5001'),
);

FirebaseStorage.instance.useStorageEmulator(
  dotenv.env['FIREBASE_EMULATOR_HOST'] ?? '127.0.0.1',
  int.parse(dotenv.env['FIREBASE_STORAGE_PORT'] ?? '9199'),
);

 

  • dotenv.env['FIREBASE_EMULATOR_HOST']를 활용하여 환경 변수에 정의된 호스트 값을 동적으로 참조.
  • 기본값으로 127.0.0.1 설정.

3. 환경 변수 검증 코드 강화

환경 변수 검증 단계에서 FIREBASE_EMULATOR_HOST 값이 비어있지 않은지 확인:

 

final requiredEnvVars = [
  'FIREBASE_ENV',
  'USE_FIREBASE_EMULATOR',
  'FIREBASE_EMULATOR_HOST',
  'FIREBASE_FIRESTORE_PORT',
  'FIREBASE_FUNCTIONS_PORT',
  'FIREBASE_STORAGE_PORT',
];

for (final envVar in requiredEnvVars) {
  if (dotenv.env[envVar]?.isEmpty ?? true) {
    throw Exception('⚠️ Required environment variable $envVar is not set');
  }
}

 

4. Firebase Emulator 실행

Firebase Emulator를 실행할 때 아래 명령어로 Firebase Emulator Suite를 올바르게 실행:

 

firebase emulators:start --only functions,firestore,storage

 

Firebase Emulator가 로컬 호스트(127.0.0.1)에서 실행되도록 설정.

 

5. iOS 시뮬레이터에서 앱 실행

Flutter 앱을 실행할 때 flutter run 명령어를 활용하여 iOS 시뮬레이터에서 앱을 실행.
환경 변수를 전달하여 Firebase Emulator 설정이 적용되도록 함:

 

flutter run --dart-define=ENV=development

 

결과

  • iOS 시뮬레이터와 Firebase Emulator 간의 통신 문제 해결.
  • 앱이 정상적으로 Firebase Emulator와 통신하며, Firestore, Functions, Storage 기능 호출 성공.

배운 점

  1. localhost와 127.0.0.1의 차이
    • iOS 시뮬레이터에서 localhost가 호스트 머신이 아닌 시뮬레이터 자체를 참조한다는 점을 이해.
    • 이를 해결하기 위해 127.0.0.1 사용.
  2. 환경 변수 관리
    • Firebase Emulator와 같은 개발 도구에서 필요한 환경 변수를 명확히 정의하고 검증하는 것이 중요.
  3. Firebase Emulator 초기화 코드 작성
    • 초기화 코드에서 환경 변수의 기본값을 설정하거나 명확히 정의함으로써 디버깅 시간을 단축 가능.

개선 방향

  • 환경 변수 자동 검증 도구 작성: 빌드 전에 환경 변수 설정 누락 여부를 검증하는 스크립트 작성.
  • Firebase Emulator 설정 가이드 문서화: 팀원과 공유할 수 있는 설정 가이드를 작성하여 반복적인 문제를 예방.
  • 시뮬레이터-에뮬레이터 통신 테스트 자동화: iOS 시뮬레이터와 Firebase Emulator 간의 통신 테스트를 자동화하여 문제를 조기에 발견.