iOS

[iOS / Swift] Firebase Remote Config로 강제/선택 업데이트 팝업 관리하기

evan.k 2023. 2. 3. 13:38

최근에 네이티브 코드와 웹뷰가 통신 하는 새로운 기능이 개발되었는데 앱을 업데이트 해야만 사용이 가능하여 웹뷰에서 버전을 체크하는 코드를 추가해야 했다.

앱의 구조가 웹뷰이기 때문에 네이티브 기능의 업데이트가 많은 편은 아니지만 대부분 주요 기능을 개발해서 유저들이 업데이트를 해야하는 경우가 대부분이었다.

매번 버전 체크를 하기에는 너무 번거롭고 하드 코딩이라 강제 업데이트에 대해 생각하게 되었다.

 

처음 생각했던 방식

앱스토어의 최신 버전과 현재 사용중인 버전을 비교하여 최신 버전이 아닐 경우 업데이트 팝업 노출

1. 앱 처음 켜질 때 업데이트 팝업 노출

2. willEnterForegroundNotification observer를 추가해  업데이트 하지 않은 유저들에게 다시 업데이트 팝업 노출

 

이 방식은 매 업데이트마다 유저들에게 팝업을 노출하기 때문에 유저들에게 피로감을 줄 수도 있다는 생각이 들었고 특정 버전에서만 업데이트 파업을 노출시키는 방식을 생각하게 되었다.

 

또한 업데이트 팝업의 케이스를 3가지로 수정했다.

1. 강제

2. 선택

3. 필요없음

강제 업데이트의 경우 팝업에서 '업데이트 하기' 버튼만 노출 시켰고

선택 업데이트 팝업은 '나중에 하기' 버튼을 추가해주었다.

 

두 번째 방식

db에 버전을 저장하고 서버에서 해당 버전을 불러와 비교 후 업데이트 팝업 노출

 

특정 버전을 알기 위해서 버전을 저장할 필요가 있었고 db에 저장 한 후 앱을 시작할 때 불러오는 방식을 생각했다.

 

버전을 바꾸기 위해 직접 db를 수정해야 하며 불필요한 서버 통신이 일어나는 점 때문에 더 좋은 방법을 생각하고 있을 때 Firebase의 remote config 라는 것을 찾았다.

 

Firebase Remote Config

 

Firebase Remote Config  |  Firebase 원격 구성

무제한 일일 활성 사용자를 위해 무료로 앱 업데이트를 게시하지 않고 앱의 동작과 모양을 변경합니다.

firebase.google.com

 

간단하게 설명하자면 Firebase dashboard에서 매개변수를 등록 후 앱 업데이트 없이 호출하여 사용할 수 있는 서비스이다.

이번 앱 업데이트 관련 작업 뿐만 아니라 후에 공지사항 등에 활용할 수 있을 것 같아 사용하기로 결정했다.

무엇보다 이 좋은 서비스가 무료이다.

 

세팅 하는 법은 위 링크에서 확인할 수 있다.

 

사용법

먼저 firebase remote config dashboard에 원하는 매개변수를 저장한다.

그리고 코드에서 매개변수를 호출하면 끝!

import FirebaseRemoteConfig

class ViewController: UIViewController {
	var remoteConfig: RemoteConfig?
    var forceUpdate: String! = "false"
    var isFetchRemoteConfig: Bool = false
    
    override func viewDidAppear(_ animated: Bool) {
    	checkVersion()
	}
    
    func checkVersion() {
    	remoteConfig = RemoteConfig.remoteConfig()
        
        let setting = RemoteConfigSettings()
        
        let setting = RemoteConfigSettings()
        setting.minimumFetchInterval = 60 * 60 * 24 * 1 // fetch 주기를 24시간으로 설정

        remoteConfig?.configSettings = setting
        
        self.remoteConfig?.fetch { [weak self] _, error in
            if let error = error {
                return
            }
            
            self!.remoteConfig?.activate { _, _ in
                print("Retrieved values from the cloud!")
            }
            
            let minimumVersion = self!.remoteConfig?.configValue(forKey: "minimum_version").stringValue ?? "0" // 최소 버전 호출
            self!.forceUpdate = self!.remoteConfig?.configValue(forKey: "force_update").stringValue ?? "false" // 강제 여부 호출
            let currentVersion = self!.getBundle(key: "CFBundleShortVersionString") // 현재 버전 체크
            self!.minimumNumber = Int(minimumVersion.components(separatedBy: CharacterSet.decimalDigits.inverted).joined())! // x.x.x 의 버전을 정수만 추출 xxx
            self!.currentNumber = Int(currentVersion!.components(separatedBy: CharacterSet.decimalDigits.inverted).joined())!

            if (self!.minimumNumber! > self!.currentNumber!) { // 버전 비교
                self!.showUpdatePopUp(forceUpdate: self!.forceUpdate!) // 앱 업데이트 커스텀 UI 노출 
            }
        }
    }
}

위 코드에서 보다시피 사용법은 매우 간단하다.

remoteConfig.fetch 를 통해 원하는 매개변수를 불러오면 된다.

버전은 4.2.1 등 정수만 있는게 아니기 때문에 정수값으로 변환하는 작업을 추가해줬다. 4.2.1 -> 421

현재 버전과 불러온 버전을 비교하여 최소 버전 보다 낮을 경우 업데이트 팝업을 띄워줬다.

 

강제 업데이트의 경우 '업데이트 하기' 버튼 클릭 후 앱스토어에 진입했다가 업데이트 하지 않고 다시 앱으로 돌아오는 케이스를 생각해야 했고 observer로 관리하기로 했다.

override func viewDidLoad() {
	super.viewDidLoad()
    
    observer = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) {
        [unowned self] notification in
        if (self.forceUpdate == "true") {
            checkVersion()
        }
    }
}

foreground 진입 시 checkVersion 함수를 실행하여 업데이트 하지 않은 경우에 다시 팝업을 띄워줬다.

 

업데이트 뿐만 아니라 다른 곳에서도 많이 활용할 수 있을 것 같다.