쪼렙 as! 풀스택

iOS - Target 이용하여 비슷한 앱 여러개 찍어내기 본문

개발 일지/iOS & Android

iOS - Target 이용하여 비슷한 앱 여러개 찍어내기

코코앱 2017. 6. 8. 12:44

Intro.


  흔한 경우는 아니지만, 간혹 비슷한 앱을 찍어내야 하는 경우들이 생긴다. 스토어에 정식버전 앱 과 Free 버전을 따로 등록한 경우가 그러하고, 필자같은 경우는, 'IT알려줌' 앱과 '줄거리알려줌'을 개발할 때도 같은 서버와, 같은 계정관리, 거의 비슷한 기능의 앱을 개발해야 했다.

  

  이런 개별 앱을 모두 개별 프로젝트로 관리를 한다는건, 유지보수상 굉장히 큰 문제가 있다. 따라서 똑같은 기능을 하는건 공동의 리소스로 묶어서 관리하고, 각 앱마다 다른 부분만 분기해서 처리하는 일을 해야 한다.


  XCODE 로 iOS 용 앱을 개발할 때는, Target 을 추가하는 방식으로 이 문제를 해결했다.




목표

- 버튼을 누르면 Alert을 띄워주는 같은 기능을 하는 RedApp과 BlueApp 두개의 앱을 만든다.

- 하나의 소스파일을 공유하여 관리하되, 각 앱마다 버튼의 색상을 바꿔주고, Alert의 메세지도 다르게 표현해준다.


1.

- RedApp 이라는 새로운 프로젝트를 생성한다. (New Project - Single View Application)

- 공통으로 사용할 소스들을 관리할 Common 그룹을 새로 만든다.(프로젝트 우클릭 - New Group)

- 공통으로 사용할 MainViewController.swift, Common.storyboard 파일을 새로 만든다.(New File)

- 결과는 아래 스크린샷을 참조하면 된다.




2.

(1) Common.storyboard 에 ViewController를 하나 새로 만든다.

(2) 새로만든 ViewController 의 커스텀 클래스는 MainViewController로 설정 (Identity Inspector)

(3) Attributes Inspector에서 'Is Initial View Controller'를 체크해준다. (이 스토리보드에서 MainViewController를 시작포인트로 잡는다는 체크임)

(4) 버튼을 하나 생성하고, MainViewController 에 @IBOutlet 과 @IBAction 을 연결해줍시다.

(5) 버튼의 Tint = White, BackgroundColor = Red 로 디자인합시다. (눈에 띄게)






3. MainViewController 의 현재 소스코드는 아래와 같습니다.

- 그냥 버튼 누르면 '나느 레드앱'이라는 Alert 을 띄워주는것 밖에 없습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import UIKit
 
class MainViewController: UIViewController {
 
    @IBOutlet weak var button: UIButton!
 
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func clickButton(_ sender: Any) {
        alert(message: "나는 레드앱")
    }
    
    private func alert(message: String){
        let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }
}
 
cs




4.

- 프로젝트 선택 - Targets의 RedApp을 선택한 후, Main Interface 를 - 방금 만든 Common.storyboard를 선택해줍니다. 그러면 RedApp이 처음 실행될 때, Common스토리보드에서 InitialViewController 를 체크해두었던, MainViewController 를 시작포인트로 앱이 실행되게 됩니다.

- 이제 프로젝트 생성하면서 RedApp 그룹에 자동으로 만들어져 있던 'ViewController.swift' 파일과 'Main.Storyboard'파일은 전혀 쓸일이 없어졌습니다. 헷갈리니까 삭제해줍시다.

- 결과는 아래 스크린샷과 같습니다.





5. 앱을 실행해서 확인해봅니다. 그냥 버튼누르면 얼럿 뜨는게 전부임.






6. 이제 BlueApp 을 만들어보겠습니다. 아래 스크린샷과같이 타겟 하단의 "+" 버튼을 누르거나, 메뉴의 File - New - Target 을 선택 - Single View Application 선택을 합니다.






7. Single View Application 을 선택하고, BlueApp 이라는 타겟을 새로 생성합니다.







8. MainViewController.swift 와 Common.storyboard 파일의 Target Membership을 RedApp과 BlueApp 모두 선택해줍니다. 이 파일들을 빌드할때, RedApp과 BlueApp 에 포함되어 빌드할거라는 체크 내용입니다. (중요) 두 개 파일 모두 잘 체크 해줘야합니다.






9. 앞서 4번 설명과 같이 BlueApp의 Main Interface 도 Common.storyboard 로 선택해줍시다. BlueApp 도 시작하면 자동으로 Common.storyboard 를 시작포인트로 앱이 실행되게 됩니다. 역시 자동으로 생성되었던 ViewController.swift 와 Main.storyboard 도 이제 필요 없으므로 삭제해줍니다. 






10. 타겟을 BlueApp으로 변경해서 Run 해봅니다. 뭐, 실행 결과는 RedApp과 완벽히 똑같을겁니다. 똑같은 스토리보드와 똑같은 MainViewController 를 실행할테니깐요. 앞으로, RedApp와 BlueApp을 실행할땐, 아래와같이 타겟을 변경해서 빌드하거나 런하면 되는것입니다.




11. 이제야 준비가 끝났네요;;; 이제부터 본격적으로 비슷하지만 다르게 돌아가도록 변경해보겠습니다. 먼저 현재 어떤 앱이 실행되고 있는지 구분할 AppManager.swift 파일을 만들어보겠습니다. Common 그룹에 New File - Swift file 합니다. 이때 중요한건 Targets 에다 RedApp과 BlueApp 모두 체크를 해줘야 합니다. 이 두 Target에서 모두 빌드될 소스라는 체크입니다. 여기서 체크하지 못했다면, 앞선 8번과정처럼 이 파일의 TargetMembership 을 체크해주면 됩니다.






12. AppManager 의 소스는 아래와 같습니다. 현재 실행되고 있는 앱이 어떤 앱인지 구분하기 위한 enum 과, 원하는 테마색상을 저장해둘 프로퍼티를 만들었습니다.

1
2
3
4
5
6
7
8
9
10
11
import UIKit
 
enum AppType {
    case RedApp
    case BlueApp
}
 
class AppManager {
    static var themeColor: UIColor!
    static var currentAppType: AppType!
}
cs





13. 이제 각 앱의 AppDelegate 에서, 앱이 실행되면 일단, AppManager의 프로퍼티값을 설정해주도록 합니다.

- RedApp의 AppDelegate.swift 에서...

1
2
3
4
5
6
7
8
9
// RedApp의 AppDelegate.swift ...
 
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
    AppManager.themeColor = UIColor.red
    AppManager.currentAppType = .RedApp
        
    return true
}
cs




- BlueApp의 AppDelegate.swift 에서...

1
2
3
4
5
6
7
8
9
// BlueApp의 AppDelegate.swift ...
 
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
    AppManager.themeColor = UIColor.blue
    AppManager.currentAppType = .BlueApp
      
    return true
}
cs





14. 이제 MainViewController.swift 에 있는 버튼을, 각 앱마다 테마색상으로 변경하고, 버튼 이름도 변경해주고, 버튼을 눌렀을 때 나오는 메세지도 변경해주겠습니다. 이런식으로 각각의 AppDelegate 에서 AppManager.themeColor 같은 프로퍼티 값을 하나 저장해두고 공통으로 쓰는 방법도 있고, 현재 앱 상태를 저장해두었다가, 필요할 때, if나 switch 로 분기를 써서 코딩을 할 수 도 있겠습니다.

- MainViewController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import UIKit
 
class MainViewController: UIViewController {
 
    @IBOutlet weak var button: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.button.backgroundColor = AppManager.themeColor
        
        switch AppManager.currentAppType! {
        case .RedApp:
            self.button.setTitle("빨간버튼"for: .normal)
        case .BlueApp:
            self.button.setTitle("파란버튼"for: .normal)
        }
    }
 
    
    @IBAction func clickButton(_ sender: Any) {
        
        if AppManager.currentAppType == .RedApp {
            alert(message: "난 RedApp")
        }
        else if AppManager.currentAppType == .BlueApp {
            alert(message: "난 BlueApp 이다.")
        }
    }
    
    
    private func alert(message: String){
        let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }
}
cs




이제 각 앱을 Run 해봅시다.



이런식으로 Target 을 추가해가면서, 공통된 소스를 사용하여 앱을 여러개 찍을 수 있겠습니다. Target 하나하나마다, 개별의 앱으로 빌드되기 때문에, 개별앱으로 앱스토어에 등록 가능하고, 또 유지보수에도 훨씬 수월할 수 있겠습니다.



Full Source - https://github.com/vowed21/MultiTargetExample









Comments