Git, CocoaPods, Xcode, Shell

[iOS - swift] Xcode 배포환경 설정 xcconfig, configuration, phase, deploy (alpha, beta, real, staging, production, CocoaPods)

jake-kim 2021. 8. 11. 22:49

Phase 설정

  • Debug (Development)
  • Debug (Staging)
  • Debug (Production)
  • Release (Development)
  • Release (Staging)
  • Release (Production)

Configuration 설정

  • Duplicate "Debug" Configuration 선택

  • 총 6개가 되도록 생성

Schemes 설정

  • Xcode는 project를 만들면 project이름으로 하나의 scheme이 디폴트로 생성
  • scheme은 build될때 어떤 configuration을 사용할지와 build target을 정의
  • Manage Schemes... 선택

  • shared가 체크되어 있는지 확인 > Duplicate 선택

  • 이름 먼저 변경: {앱이름} {Phase 이름}

  • Run 탭 ~ Archive 탭까지 모두 Configuration을 알맞게 설정 

  • shaed 체크 확인

Configurations 파일 생성

  • Targets에 체크되지 않도록 설정: 컴파일되지 않기 때문에 애플리케이션 번들에 미포함

  • key - value값 정의
    • $()는 '/'기호를 문자열로 쓰기 위해서 들어간것 (보통 '//' 처럼 있으면 주석처리 되므로)
// Development.xcconfig
// Server URL
ROOT_URL = http:/$()/localhost:3000

// Keys
API_KEY = 783u9djd8a_hkzos7jd803001nd

// App Settings
APP_NAME = PhaseEx (dev)
APP_BUNDLE_ID = com.PhaseEx.dev
  • Staging.xcconfig 파일도 생성
// Staging.xcconfig
// Server URL
ROOT_URL = https:/$()/www.staging.mytestapp.thoughtbot.com

// Keys
API_KEY = 89dhdyd93380dkqmoe_hd830dhq

// App Settings
APP_NAME = PhaseEx (staging)
APP_BUNDLE_ID = com.PhaseEx.staging
  • Production.xcconfig 파일
// Production.xcconfig
// Server URL
ROOT_URL = https:/$()/www.mytestapp.thoughtbot.com

// Keys
API_KEY = 9ud0930djd_md9zdjdko3830lb0d

// App Settings
APP_NAME = phaseEx
APP_BUNDLE_ID = com.phaseEx

xcconfig 파일 세팅

  • 선택

  • Configuration 파일이 target에만 설정된 화면: project에도 설정되어야 활성화

  • 완료

CocoaPods이 설치되어있고 xcworkspace로 프로젝트인 경우 해줘야할 사항

  • 해야할 사항: CocoaPods프로젝트에서도 위에서 설정한 config값들을 적용
    • .xcworkspace 삭제
    • podfile.lock파일, pods/ 디렉토리 삭제
    • pod install 실행
  • xcworkspace 실행 > 아래처럼 Pods-{프로젝트이름}로 config파일이 생성된것 확인

  • terminal에서 pod install 시 경고 메시지 발생 - xcworkspace와 CocoaPods으로 인해 waring메시지가 뜨는 경우: cocoaPods에는 configuration 파일들이 적용이 안되어 있기 때문에 발생

  • 해결방법: 위 경고 메세지에서 나온것을 보고 해당 config파일에 위에서 나온 'Target Support ...'를 #include하여 추가
    • 주의: 그대로 복사하면 문자열로 되지 않기 때문에, 콜론은 직접 써야하는것을 주의

그대로 복사한 경우 - 문자열로 인식 x
콜론을 사용하여 문자열로 변경 

  • could not find... 메시지가 나는 경우: 

  • Production은 앞에 Pods/ 디렉토리도 붙여야 오류가 안나는것을 주의

  • 완성
// Development.xcconfig
#include "Target Support Files/Pods-PhaseEx/Pods-PhaseEx.debug (development).xcconfig"
#include "Target Support Files/Pods-PhaseEx/Pods-PhaseEx.release (development).xcconfig"
// Server URL
ROOT_URL = http:/$()/localhost:3000

// Keys
API_KEY = 783u9djd8a_hkzos7jd803001nd

// App Settings
APP_NAME = PhaseEx (dev)
APP_BUNDLE_ID = com.PhaseEx.dev



// Staging.xcconfig
#include "Target Support Files/Pods-PhaseEx/Pods-PhaseEx.debug (staging).xcconfig"
#include "Target Support Files/Pods-PhaseEx/Pods-PhaseEx.release (staging).xcconfig"

// Server URL
ROOT_URL = https:/$()/www.staging.mytestapp.thoughtbot.com

// Keys
API_KEY = 89dhdyd93380dkqmoe_hd830dhq

// App Settings
APP_NAME = PhaseEx (staging)
APP_BUNDLE_ID = com.PhaseEx.staging



// Production.xcconfig
#include "Pods/Target Support Files/Pods-PhaseEx/Pods-PhaseEx.debug (production).xcconfig"
#include "Pods/Target Support Files/Pods-PhaseEx/Pods-PhaseEx.release (production).xcconfig"

// Server URL
ROOT_URL = https:/$()/www.mytestapp.thoughtbot.com

// Keys
API_KEY = 9ud0930djd_md9zdjdko3830lb0d

// App Settings
APP_NAME = phaseEx
APP_BUNDLE_ID = com.phaseEx

xcconfig파일에서 정의한 key값에 접근하도록 세팅

  • info.plist 수정
    • Bundle name: $(xcconfig에 정의한 key값)
    • Bundle Identifier: $(xcconfig에 정의한 key값)

  • xcconfig에 정의한 ROOT_URL과 API_KEY값 사용 방법
    • info.plist에 정의 
    • Environment.swift파일 생성 > plist안에 생성한 값 접근
  • info.plist 정의

  • Environment.swift에서 접근: Bundle.main.infoDictionary로 plist 접근
import Foundation

public enum Environment {
    // MARK: - Keys
    enum Keys {
        enum Plist {
            static let rootURL = "ROOT_URL"
            static let apiKey = "API_KEY"
        }
    }

    // MARK: - Plist
    private static let infoDictionary: [String: Any] = {
        guard let dict = Bundle.main.infoDictionary else {
            fatalError("Plist file not found")
        }
        return dict
    }()

    // MARK: - Plist values
    static let rootURL: URL = {
        guard let rootURLstring = Environment.infoDictionary[Keys.Plist.rootURL] as? String else {
            fatalError("Root URL not set in plist for this environment")
        }
        guard let url = URL(string: rootURLstring) else {
            fatalError("Root URL is invalid")
        }
        return url
    }()

    static let apiKey: String = {
        guard let apiKey = Environment.infoDictionary[Keys.Plist.apiKey] as? String else {
            fatalError("API Key not set in plist for this environment")
        }
        return apiKey
    }()
}

Provisioning Profile에서의 bundle id 설정

  • bundle id가 고정값으로 들어가있는 상황

  • target > build settings > Product Bundle Identifier에 xcconfig에서 정의한 bundle id key값을 $()으로 입력

  • Project > build settings > Product Bundle Identifier 동일하게 입력

  • 완료

* 전체 소스 코드: https://github.com/JK0369/PhaseEx

* 참고

- https://thoughtbot.com/blog/let-s-setup-your-ios-environments