[iOS] 앱 강제 업데이트

ungchun·2022년 8월 12일
0
post-thumbnail

프로젝트 앱을 출시하며 업데이트 관리를 어떻게 하는지 궁금해서 알아보고 적용시킨 다음 그 방법에 대해 정리해보고자 합니다. 정리하기에 앞서 저는 아직 취준생이고 현직에서는 업데이트 관리를 어떻게 하는지 모릅니다. 이 방법이 정답이 아닐 수 있으니 참고용으로 봐주시면 감사하겠습니다. 더 좋은 방법이 있거나 현직에서 사용하는 방법이 있으면 댓글로 알려주세요 !

업데이트 로직 ?

만약 업데이트와 관련된 로직이 안들어가있는 앱에서 심각한 버그가 발생했다? 버그를 수정하고 앱을 배포했는데도 불구하고 사용자 본인이 직접 업데이트하지 않는 한 강제로 앱을 업데이트시킬 방법이 없습니다. 따라서 업데이트와 관련한 로직을 앱을 처음으로 배포하기전에 포함시키는게 좋아 보입니다.


업데이트 로직 !

우선 저의 프로젝트에는 업데이트 버전을 이렇게 설정했습니다.
X.X.X 이렇게 버전이 있으면 세번째 숫자가 바뀌면 강제 업데이트 시키지 않고 맨 앞과 두번째 숫자가 바뀌면 강제 업데이트 하게 했습니다.
1.0.0 -> 1.0.1 면 강제 업데이트 X
1.0.0 -> 1.1.0 면 강제 업데이트 O
1.0.0 -> 2.0.0 면 강제 업데이트 O

// app version 확인, 앱 업데이트 관련
//
struct System {
	// 현재 버전 정보 : 타겟 -> 일반 -> Version
    static let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String 
    // 개발자가 내부적으로 확인하기 위한 용도 : 타겟 -> 일반 -> Build
    static let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String 
    
    static let appStoreOpenUrlString = "itms-apps://itunes.apple.com/app/apple-store/AppleID"
    
    // 앱 스토어 최신 정보 확인
    //
    func latestVersion() -> String? {
        let appleID = AppleID
        guard let url = URL(string: "http://itunes.apple.com/lookup?id=\(appleID)&country=kr"),
              let data = try? Data(contentsOf: url),
              let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any],
              let results = json["results"] as? [[String: Any]],
              let appStoreVersion = results[0]["version"] as? String else {
            return nil
        }
        return appStoreVersion
    }
    
    // 앱 스토어로 이동 -> urlStr 에 appStoreOpenUrlString 넣으면 이동
    //
    func openAppStore() {
        guard let url = URL(string: System.appStoreOpenUrlString) else { return }
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
    }
}

이렇게 업데이트 관련한 것들은 따로 빼서 정리했습니다.

AppleID는 본인의 AppleID를 적어주시면 됩니다. App Store Connect -> 앱 정보 에서 확인이 가능합니다 !

appVersion은 현재 자신이 쓰고 있는 앱의 버전 정보입니다.
buildNumber은 개발자가 내부적으로 테스트하기 위한 용도로 쓰입니다.
latestVersion은 현재 앱스토어에 올라가 있는 최신 앱의 버전 정보입니다.

여기서 우리는 appVersion과 latestVersion, 이 두개를 비교해서 강제 업데이트를 시킬 겁니다. 위에서 들었던 예로 보면
1.0.0 (appVersion과) -> 1.0.1 (latestVersion) 면 강제 업데이트 X
이렇게 되는 겁니다 !

...
	let marketingVersion = System().latestVersion()!
    let currentProjectVersion = System.appVersion!
    let splitMarketingVersion = marketingVersion.split(separator: ".").map {$0}
    let splitCurrentProjectVersion = currentProjectVersion.split(separator: ".").map {$0}
    
    // if : 가장 앞자리가 다르면 -> 업데이트 필요
    // 메시지 창 인스턴스 생성, 컨트롤러에 들어갈 버튼 액션 객체 생성 -> 클릭하면 앱스토어로 이동
    // else : 두번째 자리가 달라도 업데이트 필요
    //
    if splitCurrentProjectVersion[0] < splitMarketingVersion[0] {
    	let alert = UIAlertController(title: "업데이트 알림", message: "너랑나랑의 새로운 버전이 있습니다. \(marketingVersion) 버전으로 업데이트 해주세요.", preferredStyle: UIAlertController.Style.alert)
        let destructiveAction = UIAlertAction(title: "업데이트", style: UIAlertAction.Style.default){(_) in
        	System().openAppStore()
		}
		alert.addAction(destructiveAction)
		self.present(alert, animated: false)
	} else {
		if  splitCurrentProjectVersion[1] < splitMarketingVersion[1] {
			let alert = UIAlertController(title: "업데이트 알림", message: "너랑나랑의 새로운 버전이 있습니다. \(marketingVersion) 버전으로 업데이트 해주세요.", preferredStyle: UIAlertController.Style.alert)
			let destructiveAction = UIAlertAction(title: "업데이트", style: UIAlertAction.Style.default){(_) in
				System().openAppStore()
			}
			alert.addAction(destructiveAction)
			self.present(alert, animated: false)
		} else {
			// 이외에는 업데이트 필요 없음
        	...
        }

...

위에서 설정한 값들을 가지고 실질적으로 비교해서 업데이트가 필요한 버전이면 app store로 이동시켜 강제 업데이트를 시켜주는 코드입니다.

당연히 앱이 켜지고 메인으로 넘어가기전에 확인해야합니다. 업데이트가 필요한 버전인데 메인으로 넘어간다면 어떤 버그가 생길지 모르잖아요? 저는 메인으로 넘어가기전에 로딩뷰 viewDidLoad에 넣었습니다 !


결과

0개의 댓글