여러 프로젝트 구성

이 페이지에서는 앱에서 둘 이상의 Firebase 프로젝트를 사용하는 방법을 설명합니다.

대부분의 앱에는 하나의 Firebase 프로젝트와 시작하기 가이드에 설명된 기본 설정만 있으면 됩니다. 여러 Firebase 프로젝트를 사용하는 것이 유용한 경우는 다음과 같습니다.

  • 빌드 유형 또는 대상에 따라 서로 다른 Firebase 프로젝트를 사용하도록 개발 환경 설정
  • 앱에서 여러 Firebase 프로젝트의 콘텐츠 액세스

다양한 환경 지원

일반적인 사용 사례 중 하나는 개발 환경과 프로덕션 환경에 각각 별도의 Firebase 프로젝트를 지원하는 것입니다.

웹 및 Admin SDK를 구성할 때는 초기화 함수에 직접 값을 전달합니다. 이러한 SDK에서는 런타임 확인을 사용하여 개발 또는 프로덕션 구성 변수를 선택할 수 있습니다.

Android 및 Apple 플랫폼과 이들 플랫폼의 Unity 및 C++ 래퍼에서는 일반적으로 구성 파일에서 구성을 로드합니다. 구성 파일은 Apple 플랫폼의 경우 GoogleService-Info.plist, Android의 경우 google-services.json입니다. 이러한 파일을 옵션 객체(FIROption 또는 FirebaseOptions)로 읽으면 Firebase 애플리케이션 객체(FIRApp 또는 FirebaseApp)가 이 옵션 객체를 참조합니다.

이러한 플랫폼에서는 빌드 시간을 결정할 때 환경이 전환되며 이때 환경마다 다른 구성 파일이 사용됩니다.

Apple 애플리케이션에서 여러 환경 지원

기본적으로 FirebaseApp.configure()는 애플리케이션과 번들로 제공되는 GoogleService-Info.plist 파일을 로드합니다. XCode에서 개발 환경과 프로덕션 환경이 서로 다른 대상으로 구성된 경우 다음을 수행합니다.

  • GoogleService-Info.plist 파일 모두 다운로드
  • 두 파일을 서로 다른 디렉터리에 저장
  • 두 파일을 XCode 프로젝트에 추가
  • Target Membership 패널을 사용하여 두 파일을 서로 다른 대상에 연결

Target Membership 패널

여러 빌드가 단일 대상에 속하는 경우 최선의 방법은 두 구성 파일 모두에 고유한 이름(예: GoogleService-Info-Free.plistGoogleService-Info-Paid.plist)을 제공하는 것입니다. 그런 다음 런타임에 로드할 plist를 선택합니다. 다음 예시를 참조하세요.

// Load a named file.
let filePath = Bundle.main.path(forResource: "MyGoogleService", ofType: "plist")
guard let fileopts = FirebaseOptions(contentsOfFile: filePath!)
  else { assert(false, "Couldn't load config file") }
FirebaseApp.configure(options: fileopts)

Android 애플리케이션에서 여러 환경 지원

Android에서는 google-services.json 파일이 Google 서비스 Gradle 플러그인을 통해 Android 문자열 리소스로 처리됩니다. Google 서비스 플러그인 문서의 JSON 파일 처리에서 어떠한 리소스가 생성되는지를 확인할 수 있습니다.

앱 모듈 루트 아래에서 각 변형의 이름이 지정된 전용 디렉터리에 google-services.json 파일을 배치하면 서로 다른 빌드 변형google-services.json 파일을 여러 개 보유할 수 있습니다. 예를 들어 'development' 및 'release' 빌드 변형이 있으면 다음과 같이 구성할 수 있습니다.

app/
    google-services.json
    src/development/google-services.json
    src/release/google-services.json
    ...

자세한 내용은 Google 서비스 플러그인 문서의 JSON 파일 추가를 참조하세요.

이러한 리소스는 애플리케이션 코드보다 먼저 실행되고 해당 값을 사용해 Firebase API를 초기화하는 FirebaseInitProvider에 의해 로드됩니다.

이 Provider는 이름이 알려진 리소스만 읽으므로 Google 서비스 Gradle 플러그인을 사용하는 대신 문자열 리소스를 앱에 직접 추가하는 방법도 있습니다. 방법은 다음과 같습니다.

  • 루트 build.gradle에서 google-services 플러그인 삭제
  • 프로젝트에서 google-services.json 삭제
  • 문자열 리소스 직접 추가
  • build.gradle에서 apply plugin: 'com.google.gms.google-services' 삭제

애플리케이션에서 여러 프로젝트 사용

여러 데이터베이스 인스턴스에 액세스할 때처럼 동일한 API로 여러 프로젝트에 액세스해야 하는 경우가 있습니다. 대부분의 경우에는 모든 Firebase API 구성을 관리하는 중앙 Firebase 애플리케이션 객체가 있습니다. 이 객체는 일반적인 설정 과정 중에 초기화됩니다. 그러나 단일 애플리케이션에서 여러 프로젝트에 액세스하려면 각 프로젝트를 개별적으로 참조하는 별도의 Firebase 애플리케이션 객체가 필요합니다. 이러한 다른 인스턴스는 개발자가 직접 초기화해야 합니다.

어떠한 경우든 개발자는 우선 Firebase 애플리케이션의 구성 데이터를 보유할 Firebase 옵션 객체를 만들어야 합니다. 옵션에 대한 전체 문서는 다음 클래스의 API 참조 문서에서 찾을 수 있습니다.

다음은 애플리케이션에서 이러한 클래스를 사용하여 여러 프로젝트를 지원하는 방법을 보여주는 예시입니다.

Swift

// Configure with manual options. Note that projectID and apiKey, though not
// required by the initializer, are mandatory.
let secondaryOptions = FirebaseOptions(googleAppID: "1:27992087142:ios:2a4732a34787067a",
                                       gcmSenderID: "27992087142")
secondaryOptions.apiKey = "AIzaSyBicqfAZPvMgC7NZkjayUEsrepxuXzZDsk"
secondaryOptions.projectID = "projectid-12345"

// The other options are not mandatory, but may be required
// for specific Firebase products.
secondaryOptions.bundleID = "com.google.firebase.devrel.FiroptionConfiguration"
secondaryOptions.trackingID = "UA-12345678-1"
secondaryOptions.clientID = "27992087142-ola6qe637ulk8780vl8mo5vogegkm23n.apps.googleusercontent.com"
secondaryOptions.databaseURL = "https://myproject.firebaseio.com"
secondaryOptions.storageBucket = "myproject.appspot.com"
secondaryOptions.androidClientID = "12345.apps.googleusercontent.com"
secondaryOptions.deepLinkURLScheme = "myapp://"
secondaryOptions.storageBucket = "projectid-12345.appspot.com"
secondaryOptions.appGroupID = nil

Kotlin+KTX

// Manually configure Firebase Options. The following fields are REQUIRED:
//   - Project ID
//   - App ID
//   - API Key
val options = FirebaseOptions.Builder()
    .setProjectId("my-firebase-project")
    .setApplicationId("1:27992087142:android:ce3b6448250083d1")
    .setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw")
    // .setDatabaseUrl(...)
    // .setStorageBucket(...)
    .build()

Java

// Manually configure Firebase Options. The following fields are REQUIRED:
//   - Project ID
//   - App ID
//   - API Key
FirebaseOptions options = new FirebaseOptions.Builder()
        .setProjectId("my-firebase-project")
        .setApplicationId("1:27992087142:android:ce3b6448250083d1")
        .setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw")
        // setDatabaseURL(...)
        // setStorageBucket(...)
        .build();

// The following fields are REQUIRED:
//  - Project ID
//  - App ID
//  - API Key
const secondaryAppConfig = {
    projectId: "<PROJECT_ID>",
    appId: "<APP_ID>",
    apiKey: "<API_KEY>",
    // databaseURL: "...",
    // storageBucket: "...",
};

C++

firebase::AppOptions secondary_app_options;

// API key, app ID, and project ID are always required.
secondary_app_options.set_api_key("<API_KEY>");
secondary_app_options.set_app_id("<GOOGLE_APP_ID>");
secondary_app_options.set_project_id("<PROJECT_ID>");

// The following options are specific to individual Firebase products
// and may not always be required.
secondary_app_options.set_database_url("<DATABASE_URL>");
secondary_app_options.set_messaging_sender_id("<SENDER_ID>");
secondary_app_options.set_storage_bucket("<STORAGE_BUCKET>");

Unity

Firebase.AppOptions secondaryAppOptions = new Firebase.AppOptions {
  ApiKey = "<API_KEY>",
  AppId = "<GOOGLE_APP_ID>",
  ProjectId = "<PROJECT_ID>"
};

Node.js

const secondaryServiceAccount = require('./path/to/serviceAccountKey.json');

// All required options are specified by the service account,
// add service-specific configuration like databaseURL as needed.
const secondaryAppConfig = {
    credential: cert(secondaryServiceAccount),
    // databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
};

Java

FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountKey.json");

FirebaseOptions secondaryAppConfig = new FirebaseOptions.Builder()
  .setCredential(FirebaseCredentials.fromCertificate(serviceAccount))
  .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
  .build();

이 옵션 객체를 초기화한 후 이 객체를 사용하여 Firebase 애플리케이션 인스턴스를 추가로 구성할 수 있습니다. 아래의 모든 예에서는 secondary라는 문자열을 사용합니다. 이 이름은 애플리케이션 인스턴스를 검색하고 [DEFAULT]라는 기본 인스턴스를 포함한 기타 인스턴스와 해당 인스턴스를 구분하는 데 사용됩니다. 다른 Firebase 프로젝트의 용도에 맞는 적절한 문자열을 선택하시기 바랍니다.

다음 스니펫은 대체 실시간 데이터베이스에 연결하는 방법을 보여줍니다. 다른 Firebase 기능의 API도 같은 패턴을 따릅니다.

Swift

// Configure an alternative FIRApp.
FirebaseApp.configure(name: "secondary", options: secondaryOptions)

// Retrieve a previous created named app.
guard let secondary = FirebaseApp.app(name: "secondary")
  else { assert(false, "Could not retrieve secondary app") }


// Retrieve a Real Time Database client configured against a specific app.
let secondaryDb = Database.database(app: secondary)

Kotlin+KTX

// Initialize secondary FirebaseApp.
Firebase.initialize(context = this, options, "secondary")

// Retrieve secondary FirebaseApp.
val secondary = Firebase.app("secondary")
// Get the database for the other app.
val secondaryDatabase = Firebase.database(secondary)

Java

// Initialize with secondary app
FirebaseApp.initializeApp(this /* Context */, options, "secondary");

// Retrieve secondary FirebaseApp
FirebaseApp secondary = FirebaseApp.getInstance("secondary");

// Initialize another app with a different config
const secondaryApp = firebase.initializeApp(secondaryAppConfig, "secondary");
// Access services, such as the Realtime Database
// secondaryApp.database();

C++

firebase::App* secondary_app = firebase::App::Create(secondary_app_options, "Secondary");
firebase::database::Database* secondary_database = firebase::database::Database::GetInstance(secondary_app);

Unity

var secondaryApp = Firebase.FirebaseApp.Create(secondaryAppOptions, "Secondary"));
var secondaryDatabase = Firebase.Database.FirebaseDatabase.getInstance(secondaryApp);

Node.js

// Initialize another app with a different config
const secondary = initializeApp(secondaryAppConfig, 'secondary');
// Access services, such as the Realtime Database
// const secondaryDatabase = secondary.database();

Java

// Initialize another app with a different config
FirebaseApp secondaryApp = FirebaseApp.initializeApp(secondaryAppConfig, "secondary");

// Retrieve the database.
FirebaseDatabase secondaryDatabase = FirebaseDatabase.getInstance(secondaryApp);

신뢰할 수 있는 애널리틱스 보고서 보장

Google 애널리틱스는 앱 시작 흐름 초기에 이벤트를 수집하며 경우에 따라 기본 Firebase 앱 인스턴스가 구성되기 전에 수집하기도 합니다. 이 경우 Firebase에서는 Android 리소스 또는 Apple 플랫폼의 GoogleService-Info.plist를 참조하여 이벤트를 저장할 올바른 Google 앱 ID를 찾습니다. 따라서 가급적 기본 구성 방법을 사용하는 것이 좋습니다.

런타임 구성이 필요한 경우 다음 사항에 유의하세요.

  1. AdMob을 사용하며 권장사항대로 시작할 때 광고를 요청하는 경우 리소스 기반 구성 방식을 사용하지 않으면 모바일 광고와 관련된 일부 애널리틱스 데이터가 누락될 수 있습니다.
  2. 앱의 배포 변형마다 하나의 Google 앱 ID만 제공해야 합니다. 예를 들어 구성에 특정 GOOGLE_APP_ID가 사용된 앱 버전 1을 출시한 후 다른 ID로 버전 2를 업로드하면 애널리틱스 데이터가 삭제될 수 있습니다.
  3. Apple 플랫폼의 경우 런타임에 다른 구성을 제공한다면 프로젝트에 GoogleService-Info.plist를 추가하지 마세요. GOOGLE_APP_ID가 변경되고 애널리틱스가 손실될 수 있습니다.