[App 개발] Cocoa Design Patterns (7) 마지막
본문
클래스 클러스터와 프록시를 설명할 때 이미 소개했습니다만, Facade(겉면 - 여기서는 포장지(Wrapper Facade)로 번역하겠습니다)는 복잡한 객체 집단을 간단히 단일화하여 보여주는 객체입니다. 포장지 패턴은 코코아에서 다른 패턴들을 연결하는 목적으로 많이 쓰이고 있습니다.
여러분이 사용하는 대부분 어플리케이션 킷들중에 특히 복잡한 것들은 다 포장지입니다. NSText와 NSImage 가 그 예입니다.
NSText 가 사용하는 방법은 아주 좋은 예제입니다; 대부분 코코아 개발자들은 그저 NSText 자체를 사용할 뿐 그 속에서 어떤 일이 일어나는지를 걱정하는 사람은 없습니다. 이렇게 되면 개발자도 편하고 대부분의 경우 문제가 없습니다. 사용하기 쉬운 대신에 약간의 자유성, 조정성, 그리고 확장성은 잃어버리게 됩니다. 어떤 개발자들은 포장지를 치우고 특별히 원하는 기능을 만들기를 원하고, 어쩌면 필요할 것입니다. 그러기 위해서는 연결되어 있는 수많은 객체 집단을 완전히 이해하는 데에 시간을 들여야 하는 문제에 직면하게 됩니다. 성능과 특화성을 위해서 복잡성이라는 문제를 해결해야 합니다.
Prototypes
어떤 코코아 객체들은 GOF의 프로토타입 패턴을 그대로 사용하고 있습니다. 프로토타입이란 직접적으로 사용되지 않고, 새로운 인스턴스를 생성하기 위한 템플릿으로 사용되는 인스턴스입니다. 새로운 인스턴스가 필요할 때 프로토타입이 복제됩니다. 이것은 NSMatrix 같은 일반적인 컨테이너에 유용한 방법입니다. 매트릭스의 크기를 키워 용량을 늘여야 할 때, 새로운 요소를 얻기 위하여 프로토타입을 복제합니다.
프로토타입 패턴은 어떤 적절한 인스턴스를 생성해서 원하는 대로 조정할 수 있게 합니다. NSMatrix 는 유연하기 때문에 인스턴스에 포함된 것을 알 필요가 없이 간단하게 생성하여 둘 사이의 조정이 필요없이 원하는 대로 자동으로 설치됩니다.
또한 외부에서 동적으로 여러분의 응용 프로그램으로 읽어들인 코드를 결합할 때에도 유용합니다. 개발자는 프로그램에서 여러 개의 프로토타입으로부터 객체 모음을 만들 수도 있습니다. 인터페이스 빌더에 있는 객체들은 모두 프로토타입입니다.
어플리케이션 킷에서 제공하는 어떤 view 들은 약간 다른 종류의 프로토타입입니다. 이들은 객체간에 공유되는 프로토타입입니다. 이러한 인스턴스의 재사용은 코코아에서, 특히 입력, 입력 확인, 출력 포맷 등의 작업에 일반적으로 사용되고 있습니다.
예를 들어, NSTextField 를 보시면 유저에게 간단한 텍스트 편집 필드를 제공합니다. 그런데 편집 기능을 담당하기 위해서 NSText 를 이용하고 있습니다. NSText 객체는 모든 내부 객체들이 포장지로 싸여 있어서 매우 덩치가 큰 객체이기 때문에 인터페이스에 있는 모든 필드에 NSText 객체를 생성하는 것은 비효율적입니다. 그 대신 모든 텍스트 필드는 필드 에디터라고 불리는 NSText 객체를 공유하고 있습니다.
다른 예로서, NSTableView 객체는 출력을 위한 열 서식 테이블 내부 객체를 가지고 있습니다. 이 객체도 열마다 공유하고 있습니다. 이렇게 객체가 설정되는 방식은 서식을 가지는 모든 열에서 동일하게 고려되고 있습니다.
Archiving and Coding
코코아 파운데이션 킷에는 객체의 "건조 동결법"이 있어서 후에 다시 불러들일 수 있게 만듭니다. 객체가 동결되면 메모리나 디스크, 데이터베이스, 기타 다른 방법으로 저장됩니다. 객체를 동결시키는 과정을 archiving 혹은 object serialization 이라고 부르고, 이것은 NSCoder 클래스에서 담당하고 있습니다. 코더는 간단한 NSCoding 프로토콜을 준수하는 어떠한 객체라도 동결시킬 수 있습니다. 또한 자신이 동결시킨, 혹은 다른 코더가 동결시킨 어떠한 객체도 해동시킬 수 있습니다.
인코딩과 디코딩 과정은 제 5 장 "Cocoa Conventions." 에 소개되어 있습니다.
코더에 의해 동결된 데이터에는 객체의 완전한 상태가 보존되어 있어 마치 GOF Memento 패턴과 유사합니다. 하지만 Archiving은 현존하는 객체의 지난 상태를 복구하지 않는 메멘토 패턴과는 약간 다릅니다. 대신에 객체를 소멸시키고 다시 원래 상태로 되살릴 수 있도록 객체를 저장합니다. Archiving 의 또 다른 활용은 복제 인스턴스를 만들거나 인스턴스를 현재 프로세스에서 다른 쪽으로 옮기는 데에도 쓰입니다.
Note
코코아에서 메멘토 패턴을 사용하는 다른 예는 되살리기(undo) 시스템입니다. 코코아의 되살리기 시스템은 객체의 상태를 저장하고 복구하기 위해 Archiving 이 사용되지는 않지만, 강제적인 되살리기 구현의 일부로 사용될 수 있습니다.
거의 모든 코코아 객체는 NSCoding 프로토콜을 준수합니다. 따라서 인터페이스 빌더에 의하여 살아있는 객체들이 조작되거나 변경될 수 있게 합니다. 인터페이스 빌더에서 객체를 .nib 에 저장할 때 NSCoder 인스턴스는 객체들을 동결시켜 파일에 기록할 수 있게 만듭니다. 코더는 심지어 반복 구조가 들어 있는 전체 객체 구조까지 모두 동결시킬 만큼 지능적으로 만들어져 있습니다. 객체 구조와 객체간의 연결이 모두 추적됩니다.
객체가 해동될 때 코더는 객체들에게 기상 메세지를 보내어 객체가 완전히 되살아나서 수행해야 할 특수한 활동들을 할 수 있도록 합니다.
Subviews
코코아의 윈도우 내의 모든 화면 영역은 NSView 객체의 서브클래스로 조정됩니다. 경우에 따라서는 view 들이 잘못 놓여 서로 겹치기도 하고, 어떤 경우는 다른 것을 완전히 포함하기도 합니다. 이 때, 포함하는 view 를 superview 라고 하고, 포함된 view 를 subview 라고 합니다. 경우에 따라서 superview 는 subview 주변에 그림을 첨가하기도 하고, 복잡한 유저 인터페이스를 만들기 위해 다른 subview들을 적층하기도 합니다. 이것은 GOF 의 Composite 와 Decorator 패턴의 혼성 구현이 되며, 그 자체로는 특별한 패턴 이름은 없습니다.
Composite 패턴은 여러 개의 view 를 이용하여 자기 view 를 만드는 방법입니다. 컴포지트 뷰의 예로서 NSTableView 객체가 있습니다. 이 객체는 테이블의 컬럼 헤더, 셀, 스크롤 바 등을 표현하기 위해서 다른 객체를 사용합니다. 이런 뷰들은 포함하는 테이블 뷰에 의하여 조립되고 조정됩니다.
Decorator 패턴은 어떠한 뷰에 가외의 장식물을 더하는 뷰를 만드는 방법입니다. 예를 들어, NSScrollView 객체는 어떠한 뷰를 취하여 가로 세로 스크롤 바를 더해줍니다. 내부에 스크롤 바를 첨가하는 가장 보편적인 뷰의 예는 NSText 인스턴스에서 스크롤 가능한 텍스트 영역을 만드는 경우입니다. 물론 어떠한 뷰의 내부에도 적용 가능합니다. 또 다른 decorator 의 예는 NSBox 클래스입니다. 이것은 뷰 집단의 경계선과 타이틀을 추가하는 기능을 합니다.
모든 코코아 뷰는 서브뷰와 슈퍼뷰를 가질 수 있어서 모두 다 컴포지트로, 데코레이터로, 혹은 둘다의 역할을 할 가능성이 있습니다.
Responder Chain
응답 체인은 패턴은 아니지만, 패턴의 또 다른 구현입니다. 이것에 대해서는 제 8 장 "Application Kit Framework Overview."에 소개되어 있습니다. 이것을 지금 소개해 드리는 이유는 이것이 GOF 의 Chain of Responsibility 패턴의 완벽한 구현이기 때문입니다. 간단히 말씀 드려서 응답 체인은 사용자의 입력을 받아서 입력 이벤트를 적절한 장소에 전달하는 역할을 합니다.
예를 들어, 사용자가 Edit 메뉴에 있는 Copy 명령을 선택했을 때, 메뉴 항목 -copy: 액션은 어디로 향해야 할까요? 현재 포커스를 갖고 있고 선택되어 있는 뷰가 이 메세지를 받을 첫 번째 기회를 가집니다. 만약 활동중인 뷰가 이 메세지를 처리하지 않을 때 메세지는 컨트롤의 윈도우로 전달되고, 그리고 아직도 처리되지 않았을 때에는 응용 프로그램 객체로 전달됩니다. -quit: 와 같은 메세지는 보통 응용 프로그램 객체까지 전달됩니다. 만약에 이벤트가 처리되지 못하고 체인 끝에서 소멸된다면 응용 프로그램은 사용자에게 경고음을 발생하고 액션을 이해하지 못했다고 경고를 줍니다.
어플리케이션 킷은 이벤트에 응답할 수 있는 객체의 체인을 생성하고, 체인의 앞에는 활성화된 인터페이스 컨트롤이 위치하고, 체인의 맨 뒤에는 응용 프로그램을 위치시킵니다. 어플리케이션 킷은 사용자가 다른 윈도우, 다른 컨트롤을 선택할 때마다 이 체인을 갱신하고 관리합니다. 이렇게 해서 응용 프로그램에서 메세지의 처리와 전송이 자동적으로 이루어집니다. 설계에 의하면 이것은 객체 집단의 구조의 결과로서 일어나게 됩니다.
컨트롤의 대상이 nil 로 설정되어 있다면 이것은 이 액션이 응답 체인의 앞에 있는 객체에게 보내지는 것을 알게 됩니다. 결과적으로 타겟이 자동적으로 갱신되는 효과를 가져옵니다. 따라서 여러분은 메뉴 항목의 대상을 변경하는 코드를 구현할 필요가 없습니다. 사실 어떤 메세지를 응답 체인의 어떤 객체가 처리할 수 있을지 없을지를 판단하는 것도 가능합니다. 이 정보를 이용하면 코코아에서 포커스가 변경될 때 메뉴 항목을 자동으로 활성화하거나 비활성화할 수 있습니다.
정리
코코아에서 응답 체인 패턴에는 타겟/액션 패턴과 Chain of Responsibility 패턴이 연결되어 있습니다. 그 외에도 코코아에서 패턴들이 연결되어 있는 여러 예들이 이번 장에서 소개되었습니다. 이러한 패턴간의 상호 대화는 일반적입니다. 코코아는 일관적으로 패턴을 적용하고 있기 때문에, API 의 양이 방대하기는 하지만 쉽게 배울 수 있다는 것을 발견하실 것입니다. 여러분들이 이러한 패턴에 익숙하다면 패턴들이 여러분이 기대한 방향때로 작동한다는 것을 발견하게 될 것입니다.
여러분이 익숙해지면, 객체의 문서를 읽지 않아도 메쏘드 이름을 알아맞힐 수 있을 정도가 될 것입니다. 그리고 여러분이 위의 것들과 동일한 패턴을 여러분의 프로그램에서 적용한다면 여러분이 만드는 객체들은 코코아의 성능을 보다 많이 끌어낼 수 있음을 발견하실 것입니다.
여기의 코코아 패턴의 논의들은 서론일 뿐입니다. 이 장에서는 단지 이론적인 것보다 프레임웍 안에서 동작하는 응용 프로그램의 관점으로서의 코코아 프레임웍에서 볼 수 있는 가장 일반적이고, 가장 많이 재사용되는 패턴들의 대략적인 설명입니다.
책 전체가 패턴을 설명하기 위해서 씌어져 있음을 염두에 두세요. 이 장은 시작일 뿐입니다.
결론적으로 이 장은 이 책을 위한 배경 지식, 언어, 용어, 패턴을 위한 장입니다. 지금까지 소개한 배경 지식들은 프레임웍을 이해하기 위한 기본입니다. 다음 장부터는 코코아 프레임웍에 대한 자세한 내용과, 그 성능을 끌어내기 위한 기술들이 소개될 것입니다.
최신글이 없습니다.
최신글이 없습니다.
댓글목록 0