지금까지 우리는 정해진 템플릿에 의해 Xcode 가 기본으로 생성해준 코드들과 XIB 내용을 살펴보고, 프로그램이 시작되는 동작을 살짝 엿보았다.
이제 Interface Builder 에서 새로운 UI 를 작성해 보자. 처음에는 하나의 Label 아이템만을 사용했지만, 이제는 3가지 아이템을 View 창 위로 끌어다 놓고, 위치와 속성을 조절할 것이다.
우리가 사용해볼 아이템은 Text Field, Label, 그리고 Round Rect Button 이 되겠다. 필자는 아래 그림처럼 세 아이템을 나열하고, 크기와 위치를 조정한 후, 몇가지 속성을 수정하였다. 기본적으로 이것은 Apple 의 iPhone Application Tutorial 문서에서 보여주는 예제와 같다.
여러분은 각자 원하는대로 조금씩 그 형태를 다르게 해도 무방하다. 참고로, 위 그림에서 버튼의 색이 파랗게 보이는 이유는 필자가 버튼 속성에서 Highlighted 항목을 체크 표시로 변경했기 때문이다.
각각의 UI 아이템을 배치하고 속성을 조절하는 것에 대해서 더 이상 설명할 필요는 없을 것으로 생각된다. 대부분 이런 식으로 UI 를 제작하는 프로그래밍 툴을 한두가지 사용해 본 경험이 있을 것이고, 근본적으로는 이런 식의 UI 디자인 개발 도구 자체가 직관적으로 사용할 수 있도록 되어 있기 때문이다.
게다가, 이건 다른 회사도 아닌 Apple 에서 만든 (NeXT STEP 부터의 역사를 가진) 개발 도구란 말이다. 직관적으로 빠르게 학습 가능한 UI 로는 세계 최고의 회사가 만든 도구라는 것을 상기하자.
이제, 우리가 원하는 프로그램의 외형은 일단 완성되었다. 성급하지만, 이 상태에서 Interface Builder 의 XIB 파일을 저장하고, Xcode 로 전환한 후 Build & Run 을 수행해 보자. 시뮬레이터가 동작하면서 지금까지 작성한 결과를 보여준다.
키보드 버튼들을 클릭하면, 입력된 문자가 텍스트 필드에 입력된다. 그런데, Enter 키를 클릭해도 아무런 변화가 없다. 키보드 입력 상태를 벗어나기 위해서 화면 밖 부분을 클릭하거나 다른 시도를 아무리 해봐도, 키보드를 다시 닫고 처음 화면으로 돌아갈 수 없을 것이다!
그 이유는, 필요한 키보드 입력 처리 코드를 작성하지 않았기 때문이다. Enter 키 입력에 대한 처리를 추가하면 의도한대로 다시 키보드를 닫을 수가 있게 될 것이다. 하지만 현재 상태로는 Home 버튼을 눌러서 프로그램을 종료한 후 다시 실행하는 방법 밖에는 없다. 실망스럽겠지만, 온전한 동작을 하도록 코드를 구성하는 것은 조금 후에 작업하도록 하겠다.
그러면 시뮬레이터를 닫아서 구경은 그만두고, 다시 Interface Builder 로 돌아가 보도록 하자.
자, 다시 현재 상황을 보자.
IB 에서 구성한 사용자 인터페이스는 시뮬레이터에서 확인해 본 대로, 정확히 눈에 보이는 것 그대로 구성되어 있다. 하지만 서로 연결되어 동작하는 것은 하나도 없는 상태다.
각 UI 아이템들이 서로 유기적인 동작을 이루기 위해서는, 먼저 '연결'이 되어야 한다. 따라서, 구체적인 코드를 작성하기 전해 해야 하는 작업은 이 아이템들을 연결하는 일이다.
구슬이 서말 이라도 꿰어야 보배이듯이, View 위에 아이템이 서말이라도 연결해야 보배다.
사실, 연결 작업 그 자체는 Objective-C 소스 코드에 코딩을 하는 작업이다. 그래서 지금 Interface Builder 를 닫고 Xocde Workspace 상에서 작업을 해도 된다. 실제 Apple 의 Tutorial 문서에서는 소스 코드에서 작업하는 것을 기본으로 설명하고 있다.
하지만, 여기에는 선택이 가능하다. 즉, 작업자의 기호에 따라 Workspace 에서 직접 소스코드를 작성해도 되며, 같은 작업을 Interface Builder 에서 해도 된다. 전적으로 이것은 프로그래머가 원하는 바에 달렸다.
이 문서에서는 이미 말한대로, Interface Builder 에서 작업하는 것을 중심으로 설명해 나가기로 한다. 작업 결과를 보면 자연스럽게 소스 코드를 어떻게 고치면 되는지 알 수 있고, 따라서 처음부터 소스코드에서 작업하는 것 보다는 IB 에서 하는 것이 기억하기 쉽다.
그러면, 짝짓기를 해보자.
Interface Builder 에서 작업했던 MyHellloViewController.xib 를 열고, 여기서 File's Owner 아이콘을 선택하면 Identity 창에 Class Actions 칸과 Class Outlets 창 등이 있는 것을 볼 수 있을 것이다.
지금부터 잘 보기 바란다.
먼저, 하나의 Action 을 지정하자.
액션은 말 그대로, 어떤 동작을 할 것인지에 관한 것이다.
MyHelloViewController 에 Action 을 추가한다는 것은, 다른 외부 객체가 지금 우리가 생성하고 있는 이 객체로 어떤 동작(Action)을 요구할 수 있도록 연결점을 만든다는 뜻이다.
도데체 어떤 녀석이 이 컨트롤러에게 동작을 요구할 것인가? View 에서 이 Controller 에게 동작을 요구할 녀석이 누구일지 생각해 보자.
현재 View 위에 배치된 세 개의 아이템 중, '버튼' 만이 그런 요구를 할 녀석이다. 사용자가 버튼을 클릭하면 버튼은 controller 에게 '야, 나 눌렸어! 이제 알아서 해!" 라고 Action 을 요구해야 한다.
따라서, 우리의 MyHelloViewController 에는 버튼이 Action 을 요구할 수 있는 문이 있어야 한다.
그 작업이 바로 컨트롤러에 Action 을 추가하는 작업이다.
Interface Builder 상에서 Action 추가는, Identity 창에서 Class Actions 항목 아래쪽에 있는 플러스[+] 버튼을 누른 후 왼쪽 칸에 원하는 이름을 기입하면 된다. 지금 type 은 신경쓰지 말고 id 로 남겨둔다.
Action 의 이름은 콜론(:)으로 끝나는 문자열이다. 왜냐하면, 사실 Action 이라는 것의 개념은 다른 클래스에서 호출하는 메소드와 같다. 즉, 다른 누군가가 호출할 함수 하나를 만든 셈이다. |
우리의 프로그램에서는 Action 은 하나로 충분하다. 이제, Identity 창의 아래쪽에서 Outlet 을 추가하도록 한다.
Outlet 은 Action 과는 반대다.
Outlet 은, 컨트롤러 안에서 다른 객체를 지정해서 사용할 명칭을 의미한다.
다시 말해서, 미국에 있는 어떤 도시를 우리나라 사람이 '나성' 이라고 부르는 행위와 같다. 여기서 '나성'이라는 단어는 우리나라가 사용하는 하나의 Outlet 이 되며, 이 Outlet 은 미국의 LA 와 연결된다.
비유가 좀 괴상한가? 말로 길게 설명하는 것이 오히려 도움이 안될지도 모르겠다.
일 단, 작업 진행을 계속 살펴보도록 하자. 그림에서 보는 것과 같이 Identity 창에서 두 개의 Outlet 을 추가하는데, label 이라는 이름의 아웃렛과 textField 라는 이름의 아웃렛이다. 이름은 아주 단순하게 지었다.
그리고 각 아웃렛의 우측 열에는 각 아웃렛이 연결될 Object 가 어떤 형태인지 그 클래스를 명시해 준다. 이렇게 위 그림과 같이 추가했다면 일단 Outlet 생성 작업은 끝이다.
다시 정리해보자. File's Owner 에 두 개의 Outlet 을 추가했다. 이 뜻은, MyHelloViewController 객체에서 label 이라는 이름으로 외부에 어떤 UILabel 형태의 객체를 참조해서 사용하겠다는 뜻이고, textField 라는 이름으로 외부의 어떤 UITextField 형태의 객체를 참조해서 사용하겠다는 뜻이다.
사용되어질 Action 도 만들고, 사용하겠다고 Outlet 까지 만들었는데, 누가 Action 을 사용해 줄 것이며, 누구의 객체를 Outlet 을 통해서 사용하겠다는 말인가?
컨트롤러 객체 안에서 혼자 주장해봤자 아무 소용 없다. 실제 우리가 목적으로 하는 형태로 실제 연결을 해 주면 진짜로 구슬 서 말이 꿰어서 보배가 된다.
IB 에서 연결 작업은 흥미롭다.
먼저, File's Owner 아이콘을 마우스 오른쪽 클릭 - 필자같이 아직도 원 버튼 마우스 사용자라면 Ctrl-클릭 - 을 한다. 그러면 반 투명으로 시커먼 목록 창이 하나 나타난다.
여기에는 컨트롤러 객체가 가지고 있는 아웃렛과 액션 등의 목록이 연결 상태와 함께 나타난다. 그중 우리가 앞에서 등록한 label 이라는 이름의 아웃렛이 보이는데, 여기서 우측에 있는 작은 동그라미를 클릭한 후 화면 밖으로 쭉 드래깅 해 보자!
파란 직선이 그어지는데, 이 선을 View 창에서 실제 Label 아이템 위에다가 놓고 마우스 버튼을 놓으면 해당 아웃렛과 지정한 라벨 객체의 연결이 완성된다. 아주 직관적인 작업이 아닐 수 없다.
설명이 조금 와닿지 않는다면, 아래 그림을 참조해서 잘 보기 바란다.
같은 방법으로 TextField 아웃렛도 연결해 보자. 잘 살펴보면, view 라는 이름의 아웃렛이 이미 View 와 연결되어서 등록되어 있는 것을 볼 수 있다. 이렇게 연결 작업이 끝난 label 아웃렛과 textField 아웃렛은 Controller 코드 안에서 원하는 목적에 맞게 사용할 수 있을 것이다.
이제 Outlet 을 준비하는 과정은 끝났다. 이제 남은 Action 의 연결을 완성하는 것으로 준비 과정을 마무리 짓기로 하자. Action 의 연결 작업도 Outlet 과 별로 다른점은 없다.
앞서 했던 방식대로, File's Owner 아이콘에서 마우스 우측 클릭으로 연결상태 창을 연 후에 이번에는 changeGreeting: 아웃렛의 우측 동그라미를 버튼과 연결한다.버튼 위레서 바우를 떼면, 버튼의 어떤 동작과 해당 Action 을 연결할 것인지 샌택하는 또 하나의 반투명 팝업 창이 나타난다. 여기서 가장 일반적으로 버튼 동작에 사용하는 Touch Up Inside 와 연결하면 된다.
참고로, 반대로 작업할 수도 있다. View 의 버튼 아이템에서 마우스 우측 클릭을 하면 마찬가지로 오른쪽에 동그라미를 달고 있는 항목들로 이루어진 반투명 창이 나타나는데, 여기서 Touch Up Inside 의 오른쪽에 있는 동그라미에서 마우스를 클릭한 후 File's Owner 아이콘으로 끌고가면 된다. 마우스를 놓으면 어느 Action 과 연결할 것인지를 선택하는 창이 나타나는데, 우리가 만들어놓은 Action 은 하나 뿐이므로, changeGreetion: 하나만 선택할 수 있는 작은 창으로 나타날 것이다. 이것을 선택해 주면 역시 Action 의 연결 작업이 완결된다.
이렇게 GUI 객체간의 연결 작업을 마우스로 선을 그어 연결하는 방식은 기본적으로 NeXT STEP 의 프로그래밍 환경에서 하던 것과 별 차이가 없다. 현재의 Xcode 는 NeXT STEP 의 개발 환경이 아직도 진화중인 모습에 불과하다고 말할 수 있다.
자, 이제 정신을 차려보자. 어느덧 Interface Builder 에서 구성할 수 있는 모든 작업이 다 끝난 셈이다. 지금 우리가 뭘 했는지 다시 한마디로 말해보자면, Interface Builder 를 이용해서 View 를 구성했고, 이와 연결된 Controller 의 기본 형태를 작성했다.MVC 중에서 View 와 Controller 일부를 작성한 셈이다.
Controller 를 작성했다고?
그렇다. 분명히 화면에 버튼과 라벨을 배치한 View 와 연결된, 그것의 컨트롤러인 MyHelloViewController 에 아웃렛과 액션을 정의해서 연결을 만들었다. 구체적인 동작은 없지만 Controller 의 기본 틀은 모두 작성한 것이다.
하지만, 당연히 Controller 라는 것은 Objective-C 소스 코드이어야 한다. 그래야 구체적인 동작을 작성해서 프로그램을 완성할 수 있으니까.
그렇다면, 지금까지 Interface Builder 에서 작성한 내용도 소스 코드로 작성되어 있어야 한다. 물론, 처음 템플릿에 의해 MyHelloViewController.m 과 MyHelloViewController.h 헤더 파일이 작성되어 있다. 그러나, 우리가 지금 추가로 Interface Builder 에서 작업한 내용은 아직 소스 코드에 반영되지 않은 상태다.
그래서, Outlet 과 Action 작성, 연결 등을 한 내용을 컨트롤러 소스 코드에 반영해주는 작업이 필요하다.
아래 그림처럼 Interface Builder 파일 메뉴를 보자. 여기서 Write Class Files... 항목을 선택하면 작업한 내용을 소스 코드로 작성해서 저장하게 된다.(잠깐. 작성된 View 를 저장하기 위해서는 XIB 파일을 저장해야 하는 것은 당연하다. 혼동하지 말자.)
저장하는 파일의 이름과 위치, 그리고 헤더 파일을 함께 저장할지 등을 묻는 대화창이 다음 그림과 같이 나타난다. 일반적으로 별도의 변경 없이 그대로 Save 버튼을 클릭해서 진행하면 된다. 앞서 언급한 바와 같이, MyHelloViewController.m 과 .h 는 템플릿에 의해 이미 작성되어 있기 때문에, 저장할 위치에 같은 이름의 파일이 보일 것이다.
같은 이름의 파일이 이미 있으므로, Save 를 진행하면 당연히 다음과 같은 창이 나타난다. 소스 머지를 선택하는 것이 일반적인 선택이 될 것이다. 혹은 기존 소스를 새로운 소스로 완전히 대체할 수도 있다. 상황에 맞게 선택하면 된다.
Interface Builder 안에서 할 수 있는 일들은 다 한것 같다. 이제 Xcode 의 Workspace 로 돌아와서, 방금 저장한 MyHelloViewController.m 과 MyHelloViewController.h 파일의 내용을 확인해 보자. 분명히 새로 추가된 내용들이 보일 것이고, 그것은 우리가 만든 Outlet 과 Action 에 대한 코드일 것이다.
Interface Builder 에서 Outlet 과 Action 에 대해서 작업한 내용이 결과적으로 Controller 소스 코드에 저장되는 것이라면, 그 반대의 작업도 가능하지 않을까?
다시말해서, 처음부터 Workspace 에서 MyHelloViewController.m/h 소스코드에 직접 코딩해서 작업하면 되지 않을까 하는 것이다.
물론 가능하다. 조금 익숙해진다면 각자 기호에 따라서 처음부터 코드로 작성하는 것이 편한 사람들도 있을 것이다. 그러나 처음에는 Interface Builer 에서 작업하는 것이 보다 직관적인 것은 사실이다.
한가지 주의할 것이 있는데, 처음부터 소스 코드에서 Outlet 과 Action 을 만들어서 연결하는 작업을 했다면, 반대로 나중에 Interface Builder 를 다시 실행해서 해당 View 의 XIB 내요을 수정하려 한다면, 작성된 컨트롤러 클래스 내용을 IB 로 반영해야 작업에 실수가 없게 된다.
메뉴에서 Read Class Files... 를 선택하면 아까 Write Class Files... 를 했던 것과는 반대로 클래스 소스 코드에 있는 내용이 Interface Builder 에 반영된다. Workspace 와 IB 사이를 왔다갔다 작업할 때는 꼭 이 점을 잊지말아야 사고를 막을 수 있을 것이다.
별것도 아닌 내용을 너무 장황하게 설명한 것은 아닌가 걱정된다. 그러나 Interface Builder 는 GUI 개발 도구 중에서 가장 쉬운, 그리고 MVC 모델이 완벽하게 실체화 된 개발 도구가 아닐까 감히 생각해본다. 따라서 처음 맥 환경에서 프로그래밍을 시도하려는 사람이라도 조금만 살펴보면 적응할 수 있으리라 생각된다.
또 한가지 명심할 것은, 지금까지 살펴본 것 처럼 View 를 구성하고 Controller 클래스를 만들고, Outlet 과 Action 을 작성하여 연결하는 등의 작업은 Mac Desktop 용 application 을 작성할 때에도 방법이 완전히 동일하다는 것이다. 차이가 있다면 오직 사용하는 UI 아이템들 뿐이다. 따라서, iPhone 프로그래밍 만을 하기 위해 Interface Builder 사용법을 익혔다 해도, 이미 절반 이상은 Mac OS 프로그래머가 된 셈이다.
반대로 생각하면, 기존에 Mac OS 에서 데스크탑용 프로그램을 Xcode 를 사용해서 작성할 줄 알던 사람이라면, iPhone 응용 프로그램은 아주 쉽게 작성이 가능한 것이다.
이 점이 전 세계를 놓고 봤을 때 무료로 배포된 iPhone SDK 를 통해서 곧 수 많은 응용 프로그램이 등장하리라는 예상이 가능한 요인 중 하나다.
맥 프로그래머가 극히 적은 국내에서는, 이 문서와 같은 기초 입문 문서가 많은 이들에게 도움을 줄 수 있으리라 감히 기대해본다.
이제 Controller 클래스가 제구실을 할 수 있도록 만들어보자.
댓글 없음:
댓글 쓰기