티스토리 뷰

728x90

보통 테스트를 할땐 dev서버를, 

배포할땐 production 서버와 연결해서 테스트 하는데요.

 

현재 운영중인 앱에서도 각 환경별로 분기처리가 되어있는데

유독 aws관련한 json파일만 수동으로 바꿔줘야하는것에 불편함이 있었고

왜 이것만 안되지? 라는 의구심이 들었습니다.

 

오늘은 해당문제를 해결했던 방법과 환경변수 설정해주는 방법에 대해 블로깅 해보겠습니다.


1. Scheme 분류

스킴(Scheme)을 환경에따라 -Dev, -Release 이런식으로 구분하기 쉽게 분류를 해주도록 합니다.

New Scheme - '{프로젝트이름}-Dev' or '{프로젝트이름}-Release' 

 

 

2. Scheme 역할 설정

Scheme에따라 어떤 환경에서 실행(Run, Test, Archive 등)할 지 설정해주는 부분입니다.

Edit Scheme (단축키: Cmd + Shift + ,)으로 아래와 같이 환경에 따라 설정을 해줍니다.

예)

  1. Scheme이 Release일 경우 Info - Build Configuration 설정을 Release로 설정
  2. 좌측 카테고리 실행시 변경하고 싶은 환경으로 설정 (Run, Test, Profile, Analyze, Archive)

 

3. 앱 이름 설정 DisplayBundleName

Scheme을 설정한 값에 따라 앱 이름을 바꾸려면 아래와 같이 해줍니다. 

Project > TARGETS > Build Settings > info.plist 검색 > Bundle Display Name > 환경별 앱 이름 설정

 

저는 Debug환경일 경우 [Dev]앱이름 이렇게 설정했습니다.

 

Dev Scheme으로 설정 후 실행(Run)해보면

 


4. 환경변수에 따른 서버 설정

테스트환경에 따라 바라보는 서버도 다르게 지정해야겠죠. 

 

Build Settings → User-Defined → SERVER_HOST를 추가해줍니다.

테스트환경(Debug, Release)마다 연결하고 싶은 Host를 추가해줍니다.

 

 

Info.plist → Key값에 SERVER_HOST를 추가한후 Value값에 ${SERVER_HOST}를 추가합니다

 

Info.plist에 있는걸 가져오려면 아래 코드를 사용하면 됩니다.

let serverHost = Bundle.main.object(forInfoDictionaryKey: "SERVER_HOST") as! String

 

잘 가져오는지 볼까요?

Release로 설정후 앱 실행시점에 print를 확인해보면 

class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        let serverHost = Bundle.main.object(forInfoDictionaryKey: "SERVER_HOST") as! String
        print("Server host is: \(serverHost)")
        return true
    }
    
    // ...
}

굿

 

 

환경에 따라 값 변경해주는거 말고 파일을 불러올 수는 없나?

된다 된다 있다.

사실 이거 때문에 글을 썼습니다.


 

5. 파일 불러오기(feat. Info.plist)

 

저의 경우는 아래 파일들을 테스트환경에 따라 자동으로 설정되게 하고 싶었습니다.

  • infoPlist.strings 
  • GoogleService-Info
  • awsconfiguration.json

 


적용한 이유 

더보기

1. infoPlist.strings

 

먼저 현지화(Localization) 작업을 하면 info.plist를 통해 언어별로 보여질 내용을 적어야 하기 때문에 아래처럼 파일이 나눠집니다. (infoPlist.strings) 

꼭 할 필요는 없지만, 영문버전을 사용할경우 테스트할때도 앱 이름에 [Dev]가 보여지면 팀원들도 구분하기 명확할거 같아 추가했습니다. 

 

2. GoogleService-Info

 

앱 디버깅을 하기 위해 Crashlytics를 사용하고 있는데, dev로 테스트했을때 찍히는 로그와 prod에서 찍히는 에러로그들을 나눠 지표를 파악하고 싶었습니다.

 

 

3. awsconfiguration.json

 

AWS에서 제공하는 KVS(Kinesis Video Streams)를 사용하기 위해 인증이 필요한데 Dev, Release에 따라 값이 다르기 때문에 매번 수동으로 설정해뒀던걸 자동으로 바꿔주게 하고 싶었습니다.

 

방법

GoogleService-Info.plist을 환경별로 프로젝트를 만들었다고 가정후 예로 들자면 

 

1. Dev, Release 폴더를 따로 나누고

 

2. TARGETS → Build Phases → Run Script 추가 

 

3. shell 명령어 입력

 

환경별 파일 경로 지정

# Type a script or drag a script file from your workspace to insert its path.
case "${CONFIGURATION}" in
  "Dev" )
cp -r "$SRCROOT/${PROJECT_NAME}/FirebaseConfig/Dev/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;
  "Release" )
cp -r "$SRCROOT/${PROJECT_NAME}/FirebaseConfig/Release/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;
*)
;;
esac

 

다른 파일들도 위와 같이 경로지정을 해주면

빌드시 환경별로 지정해둔 파일을 가리키게 됩니다. 

 



Run Script의 경우 이름을 바꿔도 상관없음 

 


 

에러

 

해당 작업을 하면서 여러가지 에러가 있었는데 아래와 같이 해결 했습니다. 

 

1. Command PhaseScriptExecution failed with a nonzero exit code

 

경로에 해당 파일이 없다는 뜻인데

Xcode 좌측 네비게이터 끝 부분에 Build 버튼을 누르면 어디서 어떤에러가 났는지 확인할 수 있습니다.

해당 경로에 없는파일을 채워주면 해결 됩니다.

 

다른로그지만 이런식으로 디버깅을 할 수 있음

 

 

2. Multiple commands produce error

 

문제가 발생하는 파일 클릭 후 오른쪽 Utilities창 → Target Membership → 프로젝트 이름 체크해제,

 

Run Script의 순서를 Copy Bundle Resources 아래에 설정해주면 정상작동됩니다.

이런식으로 ..

 


 

조금만 더 빨리 적용했다면 그동안 아카이브 했을때 좀더 신경쓰는 수고를 덜어낼 수 있었을텐데 라는 생각이 들었습니다.

그래도 이번기회에 그동안 안돼서 못하는줄 알았던걸 고쳐내보니 뿌듯했던것 같습니다.

 

계속해서 의심해보고 확인해보는 걸 습관 들여보기

728x90