Skip to main content

01B. 모듈과 객체

About 1 minObjective-Ccrashcoursexcodeobjective-cobjc

01B. 모듈과 객체 관련

목차
OSX 구조를 이해하면서 배우는 Objective-C

앞에서는 모듈과 객체에 바탕을 둔 모델을 소프트웨어 개발에 사용하는 방법을 설명했습니다. 이 책에서 단순한 그림을 통해 설명했지만 실제로 객체지향 분석과 설계를 할 떄는 UML(Unified Modeling Language)을 사용합니다. 다양한 개발 방법론에서 무엇을 객체로 보고 모델화할 것인지 또 모델을 어떻게 그림이나 문서로 표현할 것인지를 다룹니다.

이번 절에서는 소소프트웨어 구성 요소인 모듈과 객체 관계를 설명하고 Objective-C뿐만 아니라 객체지향 언어의 중요 구성 원리인 정보 은폐 개념도 살펴봅시다.


소프트웨어 모듈

객체지향 외에도 소프트웨어는 보통 모듈(module, 집합)을 조합해서 만드는데, 모듈이란 무엇일까요? 소프트웨어 외에 공업 제품에서도 '전원 모듈'처럼 모듈이라는 말을 사용합니다. 모듈은 특정 역할을 수행하며 다른 부분에 영향을 주지 않고 독립적으로 동작하며 교체할 수도 있습니다.

소프트웨어 모듈도 비슷해서 기능을 제공하는 단위로 소프트웨어를 독립적으로 구성하는 각 부분이 모듈입니다. 모듈은 절차, 함수, 데이터로 구성되며 어떤 모듈은 또 다른 모듈을 구성하기도 합니다. 즉, 모듈에는 계층성이 있습니다.

여기서는 모듈이 제공하는 '기능'으로 절차나 함수 호출 외에도 변수에 대한 참조나 변경도 포함해서 살펴보겠습니다.


독립성 높은 모듈

오랫동안 좋은 모듈 구조에 관한 논의가 소프트웨어 개발 분야에서 있었습니다. 여러 가지 의견이나 개념이 있었지만 간단히 정리하면 '독립성 높은 모듈을 조합해서 소프트웨어를 구성하는 방법이 좋다'였습니다. 모듈에서 독립성이란 모듈 내부 구현 변경이 다른 모듈에 영향을 주지 않는 것입니다.

어떤 모듈에서 구현된 내용이 관련된 다른 모듈을 참조하지 않으면 이해가 되지 않는다든지 어떤 모듈 구현 방법을 변경하려고 하면 다른 모듈도 그 영향을 받아 바뀌어야 한다면 독립성이 낮은 모듈입니다.

모듈에는 어떤기능-What-을 제공하는가라면 측면과 그것을 어떻게-How-구현하는가라는 측면이 있었습니다. 이런 What과 How를 명확하게 구별할 수 있어야 독립성이 높은 모듈입니다. 반대로 독립성이 낮은 모듈은 어떤 기능을 제공하는지 명확하지 않으며 구현 방법과 제공하는 기능의 구별도 불분명합니다.

독립성이 높은 모듈은 그것이 어떤 기능(What)을 제공하는가만 알면 사용할 수 있기에 규모가 큰 소프트웨어도 만들기 쉽습니다. 그 기능을 어떻게(How) 구현하는가는 중요하지 않습니다. 따라서 제공하는 기능은 같지만 성능이 좀 더 좋은 모듈이 있다면 구현 방법에 관계없이 교환할 수 있습니다. 어떤 모듈에 문제가 생겼을 경우에도 그 모듈만 고쳐서 새로운 걸로 바꾸면 되므로 소프트웨어의 신뢰성과 보수성이 높아집니다.

반대로 그 모듈을 사용하는데 그다지 중요하지 않은 기능이나 내부 구현 방법에 의존하는 기능을 모듈 외부에서 사용한다고 하면 나중에 구현 방법을 바꾸너가 모듈 자체를 다른 걸로 바꾸는 것이 힘들어진다는 게 쉽게 상상이 갑니다.


모듈 정보 은폐

독립성이 높은 모듈 작성의 원칙을 정리하면 (1) 모듈을 사용하기 위한 최소한의 정보만 모듈 외부에 제공하고, (2) 그 기능을 어떻게 구현하는지는 외부로 노출하지 않는 것입니다. 즉, 모듈을 불랙박스처럼 다루는 것입니다.

이 원칙을 정보 은폐(information hiding) 또는 캡슐화(encapsulation)라고 합니다.

모듈을 블랙박스로 만들면 그 모듈을 사용하는 입장에서는 제공된 기능만으로 프로그램을 작성해야 합니다.. 모듈 쪽에서 보면 제공할 기능만 구현되어 있으면 되므로, 예를 들어 더 빠른 알고리즘을 찾았다면 그걸로 바꾸거나 메모리 효율을 먼자하고 싶을 때 다른 구현 방법을 사용한다든지 하는 식의 변경이 쉽습니다. 즉, 독립성 높은 모듈이 만들어집니다. 또한 모듈을 사용하는 쪽에서도 내부 구현까지 보지 않고 제공된 기능만 알면 사용할수 있으므로 모듈의 재이용성이 편리해지고 소프트웨어 부품화도 쉬워집니다.

이전의 절차형 언어에서는 정보 은폐 기능이 충분하지 않아 독립서이 높은 모듈을 만들기 힘들었습니다. 이런 언어에는 데이터는 데이터로, 절차는 절차로 따로따로 있어서 모듈을 만드는 언어 기능이나 모듈 내부 구현을 외부로부터 감추는 방법이 없었습니다.

따라서 프로그래밍 언어에서 모듈을 언어 기능으로 제공하자는 움직임이 1980년 후반부터 확산되어 파스칼의 후속언어인 Module-2의 모듈, Ada의 패키지 등이 제안되었습니다.

C 언어는 각가의 소스 파일이 실질적인 모듈 단위입니다. 계층적 구조를 가진 모듈을 자유롭게 만드는 건 힘들지만 static 선언을 이용한 제한적인 함수 선언, 헤더 파일을 활용한 기능 그룹화 등을 사용해 독립성 높은 모듈을 구성할 수 있습니다. 하지만 이 방법은 프로그래머의 코딩 스타일에 크게 의존합니다. 다시 말해 독립성이 낮고 구성이 어류운 프로그램을 만들 가능성도 높아집니다.

클래스 정의와 인터페이스

객차지향 언어 프로그램에서 객체는 클래스 선언 및 정의라는 형태로 작성되어 인스턴스 객체는 프로그램 실행에 따라 동적으로 생성됩니다. 즉, 클래스 작성이 프로그램을 구성하는 단위인 모듈이 됩니다.

클래스를 구성하는 요소는 지금까지 설명한 것처럼 각 인스턴스의 인스턴스 변수와 인스턴스 사이에 공유되는 메서드입니다. 따라서 클래스 정의에는 인스턴스 변수와 메서드 정의가 포함됩니다. 하지만 인스턴스 객체를 사용하는 쪽에서 보면 그 객체를 어떻게 사용해야 하는지가 중요하지 구현 방법에 대한 정보는 필요하지 않습니다.

어떤 클래스를 사용하기 위해 클래스 외부에 공개된 정보를 클래스의 인터페이스라고 합니다. 인터페이스는 클래스가 어떤 인스턴스 변수를 가지고 어떤 메시지에 반응하는가에 대한 정보로 구성됩니다.

클래스 외부, 즉 클래스의 인스턴스를 사용하는 쪽에서 봤을 때 그 클래스에 대한 정보는 인터페이스 말고는 없습니다. 인터페이스에 적혀 있는 것 외에, 예를 들어 클래스 구현을 위한 내부에서 사용하는 데이터 구조나 절차 등은 클래스 외부에서 접근할 수 없습니다. [그림1-6]은 이런 개념을 가전 제품을 예로 들어 나타낸 것입니다. 사용자가 내부 구조를 알 필요 없이 제품 사용법(인터페이스)만 알면 됩니다.

이렇듯 모듈로서의 클래스는 클래스에 접근하는 방법을 인터페이스로 작성하고 그 외의 정보를 외부에서 보이지 않도록 하는 것으로 구현에 의존하는 자세한 데이터 구조나 절차를 은폐합니다. 잘 만든 클래스 설계는 이런 클래스에 정말 필요한 정보만 인터페이스로 작성해서 독립성 높은 모듈을 만듭니다.

인터페이스와 구현을 위한 코드 부분을 분리하는 언어도 있고 함께 사용하는 언어도 있습니다. Objective-C는 인터페이스를 따로 적은 언어입니다.


메시지 송신 구현

프로그램에는 여러 객체가 포함됩니다. 이런 객체가 자신에게 할당된 처리를 하는 방법은 여러 가지가 있습니다.

여러 객체가 동시에 어떤 처리를 하는데 메시지 송.수신도 병렬로 (그리고 비동기로) 일어난다고 합시다. 즉, 파티에서 여러 사람이 여기저기에서 서로 이야기를 하는 형태입니다. 이에 비해 한 번에 하나의 객체만 처리를 하고 메시지를 송신하는 것으로 다른 객체에 처리를 넘기는 방식도 있습니다. 이것은 한 명씩 순서대로 이야기를 하는 토론과 비슷한 형태입니다.

현재 다양한 객체지향 언어에서는 메시지에 의한 통신을 일반적인 절차 호출과 같은 방식으로 구현합니다. 어떤 객체에 메시지를 보내는 것을 그 객체에 관련된 어떤 절차를 호출하는 것과 같다고 봅니다. 메시지를 보내는 방법이나 구체적인 실행 절차를 정하는 방법 같은 일반적인 절차의 호출과는 다른 점도 많지만 메시지를 보내면 리시버가 그 처리를 끝낼 때까지 센더가 기다리는다는 점에서 절차 호출이라고 볼 수 있습니다.

한편, 독립해서 동작하는 프로세스끼리의 통신이나 네트워크로 묶인 다른 컴퓨터에서 돌아가는 프로그램끼리의 통신도 객체끼리의 메시지 접수로 추상화해서 생각할 수 있습니다. 이때 이전의 프로그래밍 언어의 절차 호출 방식으로는 대응하지 못하는 부분이 있습니다. 예를 들면 Objective-C는 처리가 끝나도 응답을 돌려주지 않아도 되는 메시지를 선언해서 효율적으로 프로세스끼리 통신을 합니다.

칼럼 3: C 언어의 새로운 규격

이 책은 여러분이 C 언어를 이미 알고 있다는 전제하에 설명합니다. Objective-C는 C 상위 호환 언어로 설계되어 C에 대한 기본 지식이 필수입니다. 따라서 C 언어 규격이 바뀌면 Objective-C 프로그램 작성 방법에도 영향을 줍니다.

K&R을 살펴봅시다. K&R은 C 언어의 창시자 C 언어 프로그래밍[1]을 집필한 커니핸B.W. Kernighan과 리치D.M. Rithchie의 이름에서 따온 말로, 표준 규격을 만들기 전의 C 언어 작성법을 의미합니다. ANSI 규격이 만들어 진 후 C 언어 프로그래밍은 2판으로 개정되었는데, 'K&R C'라고 부르면 개정 전 1판의 C 언어 작성법을 의미하는 겁니다.

1989년에서 1990년에 걸쳐 ANSI(미국규격협회)와 ISO(국제표준화기구)는 C 언어의 새로운 표준 규격을 공개했습니다. 현재 ANSI C라고 적혀 있으면 대부분 이 규격을 의미합니다. C89 또는 C90이라고 부릅니다.

1999년에 ISO는 기능을 확장한 표준 규격을 공개했는데, 이것을 C99라고 부릅니다. 현재 대다수 컴파일러에서 새로운 기능인 C99를 사용할 수 있습니다. 자주 사용되는 기능에는 inline함수, 가변 길이 배열과 포인터 최적화를 위한 restrict 수식어가 있습니다. 또한 이전에는 변수를 코드 앞단에 무조건 선언해야 했지만 C99에서는 변수를 사용하기 전이라면 어디서나 선언할 수 있습니다.

Mac OS X에서 제공하는 컴파일러는 GNU 프로젝트인 gcc를 바탕으로 만들었지만 Xcode 4.2 이후에는 LLVM 컴파일러인 clang을 사용합니다. 어느 쪽 컴파일러도 C, Objective-C, C++을 컴파일해서 Mac OS X, 아이폰, 아이패드 애플리케이션을 만들 수 있습니다. clang에서는 C99에 있는 기능을 대부분 구현하고 있으므로 C 프로그램을 만들 때뿐만 아니라 Objective-C 프로그램을 만들 때에도 C99에 있는 새로운 기능을 사용할 수 있습니다. 또한 나중에 살펴볼 블록 객체저럼 애플 사만의 독자적인 확장 기능도 있습니다.

이찬희 (MarkiiimarK)
Never Stop Learning.

  1. The C Programming Language (Prentice Hall, 1988) ↩︎