Firebase 원격 구성을 사용하여 점진적으로 Firebase App Check 출시

1. 소개

앱 증명과 함께 Firebase 앱 검사 를 사용하여 백엔드 서비스를 보호하고 Firebase 서비스에 대한 요청이 실제 앱에서 오는지 확인할 수 있습니다.

일반적으로 할당량 제한에 도달하지 않도록 사용자를 App Attest 서비스에 점진적으로 온보딩하는 것이 좋습니다. 자세한 내용은 Apple의 " App Attest Service 사용 준비 " 설명서를 참조하십시오.

" 단계별 버전 업데이트 릴리스 "에 설명된 대로 Apple의 App Store Connect 기능을 사용하여 앱 업데이트를 점진적으로 릴리스하는 기능을 사용하면 앱 확인 롤아웃을 더 원활하게 만들 수 있습니다. 이것은 간단하고 간단한 솔루션입니다. 그러나 앱 버전 업데이트를 단계적으로 출시하면 새 앱 버전을 게시하지 않고 기존 업데이트된 앱의 롤아웃을 제어하거나 동작을 변경할 수 없습니다.

App Attest로 앱 확인 출시를 더 잘 제어할 수 있는 한 가지 방법은 Firebase 원격 구성을 사용하여 한 번에 일정 비율의 앱 사용자에 대해 App Attest로 앱 확인을 활성화하는 것입니다. 이렇게 하면 증명 서버의 조절을 방지하는 데 도움이 될 수 있습니다. Google Analytics를 사용하여 롤아웃이 사용자에게 미치는 영향을 관찰할 수 있습니다.

배울 내용

이 다단계 코드랩에서는 Firebase 원격 구성을 사용하여 앱용 App Check를 출시하는 방법을 알아봅니다.

이 Codelab은 DatabaseExample 빠른 시작 앱을 기반으로 하고 Firebase App Check와 통합된 Firebase 프로젝트를 사용합니다 (Apple 플랫폼용 Firebase App Check Codelab ) . DatabaseExample 빠른 시작 앱을 사용하면 Firebase 실시간 데이터베이스의 기능을 사용하여 로그인하고 게시물을 추가할 수 있습니다.

이 코드랩의 단계를 조정하여 자체 앱을 테스트할 수도 있습니다.

전제 조건

필요한 것

  • 엑스코드 12.5+
  • 앱 증명 테스트의 경우:
    • 새로운 앱 식별자를 생성할 수 있는 Apple 개발자 계정
    • 앱 증명 기능이 활성화된 명시적 앱 ID가 있는 애플리케이션. 프로세스에 도움이 필요한 경우 앱 ID 등록앱 기능 활성화 문서를 참조하세요.
    • App Attest 를 지원하는 iOS/iPadOS 기기
  • 다음이 포함된 Firebase 프로젝트:
  • 원격 구성을 생성 및 관리하고 Google 애널리틱스를 볼 수 있는 권한이 있는 앱의 연결된 Firebase 프로젝트에 대한 액세스 권한

2. 사용자 지정 증명 공급자 만들기

이 단계에서는 App Attest가 활성화된 경우에만 토큰을 제공하는 사용자 지정 공급자 클래스를 만듭니다. 원격 구성은 구성된 Firebase 앱 인스턴스에 의존하며 이 단계에서 구현하는 맞춤 제공자는 구성을 완료하기 위한 자리 표시자 역할을 합니다.

다음 단계를 완료하려면 Xcode에서 앱의 프레임워크, 라이브러리 및 포함된 콘텐츠 섹션Firebase , FirebaseRemoteConfigFirebaseAnalytics 를 추가해야 합니다. 이를 수행하는 방법의 예는 Apple 플랫폼용 Firebase 앱 확인 codelab을 참조하세요.

  1. AppCheckProvider 프로토콜을 준수하는 NSObject 의 하위 클래스인 " MyAppCheckProvider " 파일을 만듭니다.
  2. 나중에 채울 빈 getToken() 메서드를 포함합니다.

getToken() 메서드가 있는 사용자 지정 공급자 클래스에 대한 다음 예제 코드를 참조하세요.

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {}
}

AppAttestProvider 를 인스턴스화하려면 해당 FirebaseApp 의 인스턴스를 전달해야 합니다. 저장 속성을 만들고 초기화 매개변수로 수락합니다.

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  // Firebase app instance served by the provider.
  let firebaseApp: FirebaseApp

  // The App Check provider factory should pass the FirebaseApp instance.
  init(app: FirebaseApp) {
    self.firebaseApp = app
    super.init()
  }

  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {}
}

토큰 요청을 앱 증명 제공자에게 전달

이제 getToken() 메서드에서 토큰 요청을 App Attest 공급자에게 전달할 수 있는 모든 것이 준비되었습니다.

참고: FirebaseAppCheck 프레임워크 참조 에서 getToken() 메서드에 대해 자세히 알아보세요.

getToken() 메서드에 다음 코드를 추가합니다.

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  // Firebase app instance served by the provider.
  let firebaseApp: FirebaseApp

  // The App Check provider factory should pass the FirebaseApp instance.
  init(app: FirebaseApp) {
    self.firebaseApp = app
    super.init()
  }

  private lazy var appAttestProvider = AppAttestProvider(app: firebaseApp)

  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {
    // Fetch App Attest flag from Remote Config
    let remoteConfig = RemoteConfig.remoteConfig(app: firebaseApp)
    remoteConfig.fetchAndActivate { remoteConfigStatus, error in
      // Get App Attest flag value
      let appAttestEnabled = remoteConfig.configValue(forKey: "AppAttestEnabled").boolValue

      guard appAttestEnabled else {
        // Skip attestation if App Attest is disabled. Another attestation
        // method like DeviceCheck may be used instead of just skipping.
        handler(nil, MyProviderError.appAttestIsDisabled)
        return
      }

      // Try to obtain an App Attest provider instance and fail if cannot
      guard let appAttestProvider = self.appAttestProvider else {
        handler(nil, MyProviderError.appAttestIsUnavailable)
        return
      }

      // If App Attest is enabled for the app instance, then forward the
      // Firebase App Check token request to the App Attest provider
      appAttestProvider.getToken(completion: handler)
    }
  }
}

enum MyProviderError: Error {
  case appAttestIsDisabled
  case appAttestIsUnavailable
  case unexpected(code: Int)
}

이전 코드는 원격 구성 AppAttestEnabled 부울 매개변수를 확인합니다(이 원격 구성 매개변수는 나중에 코드랩에서 생성됨). 값이 false이면 코드가 실패하여 현재 장치에서 App Check가 롤아웃되지 않았음을 나타냅니다. 값이 true이면 코드는 앱 증명 공급자를 얻으려고 시도하고 얻을 수 없으면 실패합니다. 이러한 오류 검사가 통과되면 코드는 토큰 요청을 앱 증명 공급자에게 전달합니다.

애널리틱스 이벤트 추가

Analytics 이벤트를 추가하면 App Check 롤아웃이 얼마나 성공적인지에 대한 더 나은 통찰력을 얻을 수 있습니다. 분석은 더 많은 청중을 위해 App Attest를 활성화해야 하는지 여부를 결정하는 데 도움이 됩니다.

두 개의 Analytics 이벤트(성공 시 AppAttestSuccess 및 실패 시 AppAttestFailure )를 기록하십시오. 이 두 가지 Analytics 이벤트는 App Check 롤아웃의 성공을 추적하고 대규모 롤아웃을 진행해야 하는지 여부를 결정하는 데 도움이 될 수 있습니다.

func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {
  // Fetch Remote Config.
  let remoteConfig = RemoteConfig.remoteConfig(app: firebaseApp)
  remoteConfig.fetchAndActivate { remoteConfigStatus, error in
    // Get App Attest flag value from Remote Config.
    let appAttestEnabled = remoteConfig.configValue(forKey: "AppAttestEnabled").boolValue

    guard appAttestEnabled else {
      // Skip attestation if App Attest is disabled. Another attestation
      // method like DeviceCheck may be used instead of just skipping.
      handler(nil, MyProviderError.appAttestIsDisabled)
      return
    }

    // Try to obtain an App Attest provider instance and fail otherwise.
    guard let appAttestProvider = self.appAttestProvider else {
      handler(nil, MyProviderError.appAttestIsUnavailable)
      return
    }

    // If App Attest is enabled for the app instance, then forward the
    // Firebase App Check token request to the App Attest provider.
    appAttestProvider.getToken { token, error in
      // Log an Analytics event to track attestation success rate.
      let appAttestEvent: String
      if (token != nil && error == nil) {
        appAttestEvent = "AppAttestSuccess"
      } else {
        appAttestEvent = "AppAttestFailure"
      }
      Analytics.logEvent(appAttestEvent, parameters: nil)

      // Pass the result to the handler
      handler(token, error)
    }
  }
}

3. Provider Factory 클래스 업데이트

토큰 요청을 App Attest 제공자에게 전달하는 로직을 구현하고 일부 Analytics 이벤트를 추가한 후에는 App Check for Apple Platforms 코드랩 에서 생성한 MyAppCheckProviderFactory.class 를 업데이트해야 합니다. 이 클래스는 시뮬레이터용 App Check 디버그 공급자 를 대상으로 하고 그렇지 않으면 사용자 지정 공급자를 대상으로 합니다.

Apple 플랫폼용 Firebase App Check Codelab에서 생성한 MyAppCheckProviderFactory 클래스에서 다음 코드를 편집합니다.

// MyAppCheckProviderFactory.swift

import Firebase

class MyAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
  func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
      #if targetEnvironment(simulator)
      // App Attest is not available on simulators.
      // Use a debug provider.
      let provider = AppCheckDebugProvider(app: app)

      // Print only locally generated token to avoid a valid token leak on CI.
      print("Firebase App Check debug token: \(provider?.localDebugToken() ?? "" )")

      return provider
      #else
      if #available(iOS 14.0, *) {
        // Use your custom App Attest provider on real devices.
        return MyAppCheckProvider(app: app)
      } else {
        return DeviceCheckProvider(app: app)
      }
      #endif
  }
}

FirebaseApp 을 구성하기 전에 AppCheckProviderFactory 를 설정했는지 확인합니다.

// DatabaseExampleApp.swift

import SwiftUI
import Firebase
import FirebaseAppCheck

@main
struct DatabaseExampleApp: App {
  init() {
    AppCheck.setAppCheckProviderFactory(MyAppCheckProviderFactory())
    FirebaseApp.configure()
  }

  // ...
}

4. Firebase 콘솔에서 원격 구성 매개변수 추가

이제 Firebase 콘솔에 원격 구성 매개변수 AppAttestEnabled 를 추가합니다. getToken 메소드에는 이 매개변수가 필요합니다.

Firebase 콘솔에서 원격 구성 매개변수를 만들려면 다음 단계를 따르세요.

  1. 프로젝트에 대한 원격 구성 을 열고 매개변수 추가 를 클릭합니다. 원격 구성을 처음 사용하는 경우 구성 만들기 를 클릭합니다.
  2. 매개변수 이름(키) 필드에 AppAttestEnabled 를 입력하십시오.
  3. 데이터 유형 드롭다운에서 부울 을 선택합니다.
  4. 기본값 드롭다운에서 false 를 선택합니다.

Firebase 콘솔에서 원격 구성 매개변수 만들기

저장을 클릭하기 전에 사용자의 10%에 대한 조건부 값을 생성합니다.

  1. 새로 추가 > 조건부 값 > 새 조건 만들기 를 클릭합니다.
  2. 이름 필드에 조건 이름을 입력합니다.
  3. 다음 경우 적용... 에서 임의 백분위수 사용자 , <= 를 선택한 다음 % 필드에 10 을 입력합니다.
  4. 조건 만들기 를 클릭합니다.

Firebase 콘솔에서 원격 구성 조건 정의

App Attest가 사용자의 10%에게 롤아웃되도록 조건부 값을 true 로 설정합니다.

  1. 방금 만든 조건에 대해 값을 true 로 설정합니다.
  2. 저장 을 클릭합니다.

Firebase 콘솔에서 원격 구성 매개변수 검토

완료되면 원격 구성 변경 사항을 게시합니다.

기기에서 출시 테스트

앱 코드를 수정하지 않고 기기에서 다양한 원격 구성 플래그 값을 테스트하려면 A/B 테스트로 Firebase 원격 구성 실험 만들기 가이드에 따라 AppAttestEnabled 매개변수에 대한 실험을 구성하세요. 튜토리얼 섹션 " 테스트 장치에서 실험 검증 "에서는 테스트 장치에 다른 값을 할당하는 방법을 설명합니다.

마지막 단계는 Google Analytics를 사용하여 App Attest 롤아웃의 성공을 모니터링하는 것입니다.

5. AppCheck 롤아웃의 성공 여부 검토

Analytics 이벤트 대시보드에서 롤아웃의 성공을 측정할 수 있습니다. AppAttestSuccessAppAttestFailure 이벤트를 확인하십시오. 대시보드에서 이벤트를 보려면 최대 24시간이 걸릴 수 있습니다. 또는 디버깅을 활성화하고 DebugView를 사용하여 디버그 이벤트를 더 빠르게 볼 수 있습니다.

선택적으로 충돌 비율 증가에 대해 Crashlytics 대시보드를 모니터링할 수 있습니다. 앱에 Crashlytics를 추가하는 방법에 대한 자세한 내용은 Firebase Crashlytics 시작하기를 참조하세요.

대부분 의 AppAttestSuccess 이벤트와 소수 의 AppAttestFailure 이벤트가 표시되면 원격 구성 매개변수 AppAttestEnabled 의 조건을 수정하여 App Attest가 활성화된 사용자의 비율을 늘릴 수 있다는 좋은 신호입니다.

Firebase 콘솔에서 Analytics 이벤트 검토

선택 사항: Google 애널리틱스 잠재고객 활용

AppAttestEnabled Analytics 이벤트를 더 활용하려면 AppAttestEnabled 가 true로 설정된 사용자를 추적하는 Analytics 대상 을 만들 수 있습니다.

앱 증명은 iOS 14.0과 함께 출시되었습니다. 일부 사용자는 이 릴리스에 있지 않으므로 App Attest에 적합하지 않을 수 있습니다. 다른 Analytics 이벤트를 기록하여 이러한 사용자를 추적한 다음 DeviceCheck 와 같은 다른 증명 방법에 대해 해당 대상을 타겟팅할 수 있습니다.

선택 사항: Crashlytics를 사용하여 충돌 모니터링

출시 중 앱의 안정성을 더 잘 이해하려면 Firebase Crashlytics 를 사용하여 비정상 종료 및 치명적이지 않은 상태를 모니터링하세요.

6. 축하합니다!

원격 구성으로 App Check를 성공적으로 출시했습니다 🎉

추가 리소스: