[iOS Programming Big Nerd Ranch] 1. 간단한 iOS 앱 만들기


간단한 iOS 앱을 만들어보면서 기초를 알아보자.


Objective-C로 앱을 만들어봤지만 swift로 앱을 만들어본 적이 없어 책을 보면서 연습하려고 한다. 내가 이제부터 기록할 내용은 “iOS Programming - The Big Nerd Ranch Guide 6th edition”에 나와 있는 내용을 내가 실습하면서 중요한 포인트들이나 짚고 넘어가야 할 개념들을 정리할 것이다. 그래서 빠진 내용도 존재한다. 원서라 한글로 바꾸는 데 오역이나 의역이 있을 수 있다. 단순히 기록용이므로 모든 내용을 다 번역하지는 않을 것이다..

이 책도 최신판은 아니라 최근의 버전과 맞지 않거나 다른 부분도 있지만 따라하면서 실습하기는 좋은 것 같다. 참고로 책 표지는 아래와 같다.

image

MVC 패턴

앱을 개발하기 앞서 앱 구조의 핵심 개념인 MVC, Model-View-Controller 를 알아야 한다. MVC는 iOS 개발에 사용되는 디자인 패턴이다. MVC 패턴에서 모든 인스턴스는 모델 계층, 뷰 계층, 혹은 컨트롤러 계층 중 한 곳에 포함된다.

  • 모델 계층은 데이터를 가지고 있고 UI(User Interface)에 대해 아무것도 모르는 애들이다. 만약 고양이들의 이름을 단순히 화면에 보여주는 앱이 있다면 데이터인 고양이들의 이름을 담는 배열이 모델이 될 것이다.
  • 뷰 계층은 사용자에게 시각적으로 보여지는 객체들을 포함한다. 뷰 객체나 뷰의 예로는 버튼, 텍스트 필드나 슬라이더 같은 것들이 있다. 뷰 객체들은 앱의 UI를 구성한다.
  • 컨트롤러 계층은 앱이 관리되는 곳이다. 컨트롤러 객체나 컨트롤러는 앱의 관리자라고 생각하면 된다. 컨트롤러는 사용자가 보는 뷰들을 구성하고 뷰와 모델 객체들이 동기화되는 것을 보장해준다. 일반적으로 컨트롤러는 “그리고?”라는 질문을 하는 애들이라고 생각하면 된다.

image

위 그림은 사용자의 응답에 앱이 어떻게 반응하는지 플로우를 보여주는 것이다.

  1. 사용자가 뷰의 객체와 상호작용한다.(뷰의 버튼같은 걸 누른다 등등)
  2. 뷰가 컨트롤러에 메세지를 보낸다. (고양이 이름 모델에 “삼색이”라는 데이터를 추가해줘.)
  3. 컨트롤러가 모델 객체를 업데이트 한다. (고양이 이름 모델(배열 등등)에 “삼색이”라는 이름이 추가된다.)
  4. 컨트롤러가 모델 객체에서 뷰가 관심 있을 만한 데이터를 가져온다. (뷰에 고양이 이름을 출력해야 한다면 “삼색이”가 추가된 고양이 이름 배열을 불러온다.)
  5. 컨트롤러는 변경된 모델 객체를 가지고 뷰를 업데이트 한다. (“삼색이”가 추가된 고양이들의 이름을 화면에 출력한다.)

퀴즈 앱 만들기

image

만드려는 앱은 위와 같다. 정말 간단하다. 위에는 퀴즈 질문을 출력하고, 다음 질문을 보여주는 버튼이 있다. 중간에는 답을 표시하는 텍스트 필드가 있으며, 그 바로 밑에 답을 보여달라는 버튼이 있다. 이를 MVC 패턴을 이용해서 디자인 해볼 것이다. 아래는 이 앱의 인스턴스들과 그들 간의 관계를 표시한 그림이다.

image

Interface Builder

이제 Interface Builder라고 불리는 그래픽-스타일 의 에디터를 사용해서 앱을 만들 것이다. Interface Builder는 두 가지 파트로 나뉘어져 있다.

  1. document outline : 왼쪽에 있는 애들
  2. canvas : 오른쪽에 있는 애들이다.

밑에 있는 show/hide document outline을 클릭해서 document outline 부분을 나타냈다 감췄다 할 수 있다.

image

위 화면에서 canvas에 보이는 사각형을 scene이라고 하며 앱이 지금 가지고 있는 화면을 보여주는 부분이다.

이 interface builder의 가장 큰 특징은 다른 파일들에 포함되어 있는 코드를 시각적으로 표현해주는 것이 아니라는 것이다. 처음에 이것때문에 헷갈렸는데, 만약 처음 프로젝트를 생성하고 나서 내가 viewcontroller 파일을 하나 따로 만들었다고 해도 이 뷰 컨트롤러가 interface builder에 표시되지는 않는다는 것이다. 물론 연결시키는 방법도 있지만, 다른 작업을 하지 않는 이상 내가 만든 코드 파일이 이 interface builder에 나타나지 않는다.

Interface builder는 객체의 인스턴스를 생성할 수 있고 프로퍼티를 관리할 수 있는 객체 에디터다. 위에서도 잠깐 말했지만, 내가 에디터에서 인터페이스를 수정했다고 해도 이거를 표현하는 코드를 생성하거나 하지 않는다. .storyboard 파일은 필요할 때 메모리에 load 되어야 하는 객체 인스턴스들을 모아놓은 것이다.

Interface 만들기

먼저 .storyboard에서 볼 수 있는 화면이 어떤 기종의 화면인지 설정할 수 있는 부분은 아래의 View as ~ 버튼을 통해 설정할 수 있다.

image

나는 기본적으로 iPhone 11로 설정되어서 위와 같은 화면이 나온다. Device 부분을 클릭해서 내가 보는 화면이 어떤 기종의 화면인지 선택할 수 있고, Orientation 을 설정해서 가로 화면인지 세로 화면인지 선택할 수 있다.

View Object 만들기

뷰 객체를 만들기 번에, Xcode 의 utility 부분을 보겠다. 화면의 가장 오른쪽에 있는 부분을 utility area라고 한다.

image

이 utility area에서 여러 inspector를 설정하고 확인할 수 있다.

이제 뷰 객체를 추가해보도록 하자. 뷰 객체는 Library에서 추가할 수 있는데, 이는 Xcode의 오른쪽 상단에 있는 +버튼을 눌러서 객체를 보고 찾을 수 있다.

image

여기서 가장 왼쪽에 있는 버튼을 누르면 아래와 같이 뷰 객체들의 라이브러리가 나온다.

image

내가 원하는 객체를 드래그 한 후 스토리보드의 화면에 드롭해서 객체를 화면에 추가할 수 있다. 나는 label 두 개, button 두 개를 드래그 드롭해서 화면 가운데에 맞췄다.

image

각 요소를 더블클릭하면 내부의 텍스트를 수정할 수 있다. 텍스트를 수정했기 때문에 길이가 바뀌어서 화면의 중앙에 위치하지 않는다. 그래서 다시 화면 중앙으로 드래그 해줘야 한다.

image

시뮬레이터에서 돌려보기

지금까지 만든 것을 simulator에서 돌려볼 것이다. 왼쪽 위에 툴 바에서 scheme을 선택하고 돌려준다.

image

나는 디폴트가 iPod touch(7th generation)으로 되어있었다. 내가 스토리 보드로 작업한 화면은 iPhone 11인데, 여기서 중앙 정렬한 애들이 iPod touch로 시뮬레이션하면 중앙에 정렬되어 있지 않은 것을 확인할 수 있다. 이렇게 기기에 따라 뷰 객체의 위치가 달라지는 이유는 화면에서 고정된 위치를 갖고 있기 때문이다. 이를 해결하기 위해 Auto Layout을 이용한다.

Auto Layout

방금까지 Interface Builder canvas에서는 뷰 객체들을 예쁘게 정렬했는데, 시뮬레이터 및 다른 기기에서는 내가 원하는 대로 화면이 나오지 않을 가능성이 있다. 이렇기 때문에 Auto Layout을 이용해서 뷰 객체들의 레이아웃을 화면의 크기에 상관 없이 조정해줘야 하는 것이다.

Auto Layout은 씬에 있는 각 뷰 객체들의 위치와 size constraints를 명시함으로써 동작한다. 이 constraints는 이웃하는 뷰나 컨테이너 뷰(다른 뷰 객체들을 포함하는 뷰)에 상대적으로 작용한다.

이 Auto Layout constraints를 설정하려면 스토리보드 화면의 우측 아래에 있는 Auto Layout 메뉴를 사용한다.

image

중앙 정렬하기

먼저 캔버스의 가장 위에 있는 label을 클릭하고 Align 메뉴를 열어 “Horizontally in Container”를 선택하고 “Add 1 Constraint”를 클릭해준다.

image

이러면 화면의 크기가 어떻든 가로를 기준으로 화면의 중앙에 정렬하겠다는 뜻이다.

하위 뷰 객체들의 간격 고정하고 중앙 정렬하기

맨 위에 있는 label 말고 그 밑에 있는 애들이 바로 위에 있는 뷰 객체와의 간격을 고정해줘야 한다. 우리가 추가한 모든 뷰 객체들을 중복 선택한 상태에서 3번째 메뉴를 열어 아래와 같이 사각형의 윗 부분 막대기를 클릭해서 빨갛게 만들어주고 “Add Constraint” 버튼을 눌러준다.

image

그리고 중앙 정렬하는 것은 위에서 언급한 대로 설정해준다.

만약 설정이 잘못 되었다면 Documnet Outline의 View Controller 오른쪽에 빨간색이든 노란색이든 동그랗게 알림이 뜰 것이다. 이는 contraint가 잘못 설정되거나 설정이 아직 덜 된 부분이 있어 내가 제약을 추가해줘야 하는 부분이 있을 때 뜬다. 이 경우 클릭해서 어떤 부분이 모호한지 확인해서 수정할 수 있다. 만약 constraint를 잘못 설정해서 모든 제약을 날려버려야 한다면 View를 클릭하고 Auto Layout 메뉴의 삼각형이 있는 아이콘을 클릭해서 아래와 같이 제약들을 지울 수 있다.

image

만약 설정이 잘못 되었다면 Documnet Outline의 View Controller 오른쪽에 빨간색이든 노란색이든 동그랗게 알림이 뜰 것이다. 이는 contraint가 잘못 설정되거나 설정이 아직 덜 된 부분이 있어 내가 제약을 추가해줘야 하는 부분이 있을 때 뜬다. 이 경우 클릭해서 어떤 부분이 모호한지 확인해서 수정할 수 있다. 만약 constraint를 잘못 설정해서 모든 제약을 날려버려야 한다면 View를 클릭해서 아래와 같이 제약들을 지울 수 있다.

Connection 만들기

Interface Builder에서 만들 수 있는 connection 종류는 두 가지가 있다.

1. outlet

outlet은 객체에 대한 참조다.

outlet을 만드려면 아래와 같이 ViewController.siwft에 코드를 추가한다.

import UIKit

class ViewController: UIViewController {

    @IBOutlet var questionLabel: UILabel!
    @IBOutlet var answerLabel: UILabel!
}

@IBOutlet은 Xcode에 내가 이 outlet을 Interface Builder를 이용해서 UILabel 객체에 연결 시키겠다는 것을 알려준다. 내가 만든 outlet을 스토리보드에서 연결시키려면 ViewController를 컨트롤을 누른상태에서 드래그 해서 라벨에 드랍한다. 그러면 검정 색의 팝업이 뜨면서 어떠 outlet을 라벨에 연결할 것인지 선택할 수 있다.

image

2. action

action은 사용자가 상호작용할 수 있는 버튼이나 다른 뷰에 의해 실행되는 메서드다. action을 추가하려면 위에서 한 것처럼 controller 코드에 아래와 같이 코드를 추가한다.

우리가 만든 화면에서는 버튼을 누르면, 다른 객체의 메서드를 호출한다. 이 객체를 target이라고 한다.

@IBAction func showNextQuestion(_ sender: UIButton) {
}
@IBAction func showAnswer(_ sender: UIButton) {
}

@IBAction도 마찬가지로 interace builder에서 connection을 만들어주겠다는 것을 Xcode에게 알려주는 역할을 한다. 위 코드에서 버튼의 target은 ViewController가 되어서 showNextQuestion이나 showAnswer같은 메서드를 호출하는 것이다.

스토리보드에서 action의 connection을 만드려면 버튼을 컨트롤을 누른 상태에서 클릭해서 target으로 드롭한다. 그래서 여기서는 버튼을 눌러서 ViewController로 드롭한다. 그러면 outlet을 추가할 때와 마찬가지로 팝업이 뜨면서 어떤 action을 할 지 선택할 수 있다.

connection Summary 보기

지금까지 맺어진 connection은 5개다.

  1. outlet 2개
  2. action 2개
  3. ViewController의 view라는 프로퍼티가 앱의 백그라운드를 표현하는 뷰 객체에 연결된다.

이 연결된 connection들을 connections inspector에서 확인할 수 있다.

image

Application Icons

image

앱 아이콘 이미지 사이즈의 기준은 위와 같다. 앱 아이콘을 설정하려면 Assets.xcassets의 “AppIcon”의 원하는 항목에 이미지를 넣으면 된다.

image