본문 바로가기
iOS

[iOS] NoStoryboard 로 프로젝트 구성하기

by teamnova 2021. 12. 26.

iOS 프로젝트를 구성할때 스토리보드를 이용하시나요? 

 

처음 접할때는 직관적인 앱의 흐름을 파악할 수 있고 

 

코드를 몰라도 View를 구성할 수 있다는 장점 덕분에 당연히 사용해야 하는거 아닌가 생각할지 모르겠지만 

 

이 스토리보드에도 장단점이 있습니다. 

 

스토리보드의 장점 

  • 빠른 초기화  : 뷰를 만드는데 오래걸리지 않는다는 장점
  • 시각화 : 앱의 흐름을 한눈에 볼 수 있는 점. 눈에 바로바로 보이기 때문에 이목을 끌 수 있는 점
  • 낮은 진입장벽 : 코드를 몰라도 초보자들이 뷰를 만들 수 있는 점

스토리보드의 단점

  • 생산성 : 앱이 점점 커지고 스토리보드 로딩시간이 길어지게 되면 오히려 생산성이 떨어짐
  • 가동성 : 스토리보드가 방대하면 읽기도 어려워지고 난잡해보여서 가독성이 많이 떨어짐
  • 협업 어려움 : 스토리보드 파일이 XML 포맷에다가 읽기도 어렵기 때문에 다수의 인원이 수정을 하게되면 Merge Conflict 처리가 큰 어려움으로 작용
  • 재사용성 : 스토리보드로 만든 뷰는 재사용하기가 어렵다
  • 번거로움 : 스토리보드로 만든 뷰들을 코드와 연결하기 위해서는 Identifier를 부여해줘야하는 데 이걸 매번 일일이 연결해주는 게 생각보다 번거롭다!

 

무엇보다도 코드로 UI를 짜야하는 이유가 하나 더 있는데요

 

Storyboard를 통해 만들 수 있는 UI는 전부 코드로 가능하다. 하지만, 코드로 만든 UI중에 Stroryboard로는 구현 못하는 것이 있다. 

 

 

 

그럼 스토리보드 없이 프로젝트를 구성해 볼까요? 

 

먼저 프로젝트를 스토리보드로 생성해 줍니다. 

그러면 다음과 같이 메인 스토리보드가 자동으로 생성되어 있는 것을 볼 수 있는데요

 

이걸 없애주기만 하면 되지 않을까요? 

 

Main 스토리보드 파일을 지워줍니다. 

 

그리고 빌드하고 실행을 해볼까요? 

 

 

실행이 되지 않네요. 

단순히 스토리보드 파일만 지워준다고 되는 문제가 아닌것 같습니다. 

 

info.plist 설정

설정을 해줘야 합니다.

Application Scene Manifest > Scene Configuration > Itm 0 (Default Configuration) > Storyboard Name 

보이시죠?  이걸 지워줍니다. 

 

 

그리고 해당 프로젝트 -> Target(프로젝트 이름) -> Deployment Info -> Main interface에서 Main을 지워줍니다.

 

그리고 나서 실행을 해주면 어떤가요? 

 

정상적으로 실행은 되지만 까만 화면밖에 보이지 않을거예요. 

 

스토리보드를 사용할때 설정해 주었던 Is Initial View Controller 라는 설정을 지금은 해줄 수 없잖아요? (스토리보드를 지웠으니깐)

 

그래서 설정을 해주어야 합니다. 

 

SceneDelegate 파일을 엽니다.  (AppDelegate 와 SceneDeleagte 에 대한 설명은 다른 포스팅을 통해 하겠습니다. 꽤나 중요하거든요.)

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        
        guard let _ = (scene as? UIWindowScene) else { return }
       
    }

여기를 주목해주세요 

 

변수이름이 있어야 할 부분에 " _ " 표시가 되어있는거 보이시나요?

 

변수의 이름을 나중에 사용하지 않으니 따로 이름을 지어주지 않는 경우입니다. 

 

우리는 사용해줘야겠죠? 

 

다음과 같이 변경해 줍니다. 

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: windowScene)
        let mainViewController = ViewController()
        
        window?.rootViewController = mainViewController
        window?.makeKeyAndVisible()
    }

makeKeyAndVisible() 이 뭔지 궁금하죠? Option키를 누른채로 마우스 커서를 가져다 클릭합니다. 

그럼 문서로 넘어가는데 다음과 같은 설명을 볼 수 있습니다. 

 

window의 rootViewController를 위에서 세팅해주고 makeKeyAndVisible() 부르면 마침내 저장한 rootViewController 가 상호 작용을 받는 현재 화면으로 세팅을 완료합니다. 

 

그리고 이제 화면을 구성해 볼까요? 

 

 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let test = UILabel()
        view.backgroundColor = .white
        view.addSubview(test)
        test.text = "No StrotyBoard"
        test.translatesAutoresizingMaskIntoConstraints = false
        test.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        test.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }


}

 

ViewDidLoad 라는 생명주기 함수에 다음과 같이 세팅을 해놓고 실행을 하면 저희가 원하는 화면이 나옵니다. 

 

 

 

다음시간에는 스토리보드를 사용하는것과 어떤 차이점이 있는지 알아보겠습니다.