서문
시간이 지나도 사람들이 지하철을 문제없이 다닐 수 있는 이유는 직관적인 지하철 노선도가 있기 때문이다.
해리 벡 (Harry Beck)은 지하철을 이용하는 승객의 목적을 정확히 파악했다. (하나의 역에서 다른 역으로 이동하는 것)
해리 벡의 가장 위대한 업적은 지하철 노선을 추상화한 것이다.
추상화를 통한 복잡성 극복
현실에 있는 것들과 상호작용하기 위해서는 현실을 먼저 이해해야 하지만, 현실은 복잡한 것투성이다.
따라서 인간은 본능적으로 현실을 분해하고 단순화하는 전략을 따른다. 해리 벡의 지하철 노선도처럼 진정한 의미에서의 추상화는 현실에서 출발하되, 불필요한 부분을 도려가면서 사물의 놀라운 본질을 드러나게 하는 과정이다.
또한, 목적에 부합하여야 한다.
현상은 복잡하다. 법칙은 단순하다. 버릴 게 무엇인지 알아내라. - 리처드 파인만 (Richard Phillips Feynman)
추상화의 전략은 다음과 같다.
- 구체적인 사물들 간의 공통점은 취하고 차이점은 버리는 일반화를 통해 단순하게 한다.
- 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거함으로써 단순하게 한다.
객체지향 패러다임은 객체라는 추상화를 통해 현실의 복잡성을 극복한다.
객체지향과 추상화
이상한 나라의 앨리스를 예시로 보면 추상화를 적용한 것 (기껏해야 트럼프에 불과해)을 볼 수 있다.
앨리스는 정원사들, 병사들, 왕자, 공주, 하객 왕, 하객 왕비, 하트 왕, 하트 왕비를 모두 트럼프 카드로 추상화하였다. 공통점만을 취한 것이다.
트럼프 카드로 추상화한 것은 곧 그룹을 나눈 것과 같다. 앨리스는 트럼프 카드인 것 / 토끼인 것으로 그룹을 나눴다. 이렇게 그룹화한 것은 현실 (정원)에 내재된 복잡성을 효과적으로 감소시킨다. 그룹은 공통점을 강조함으로써 나올 수 있는 것이다.
객체지향에서는 이렇게 공통점을 기반으로 객체들을 묶기 위한 그릇을 개념 (concept)이라고 한다. > 개념은 추상화의 첫 번째 전략을 사용한 것과 같다. 또, 우리는 공통점 중 중요하다고 생각되는 것만 생각하였다. 이것은 추상화의 두 번째 전략을 사용한 것과 같다.
즉, 개념과 그룹의 차이는 공통점을 기반으로 객체를 분류할 수 있는 체와 같은 역할을 하는 것이며, 그룹은 개념에 맞는 객체들이 모여 있는 공간이라는 것이다.
객체가 적합한 개념 그룹에 들어갔을 때 그 객체를 개념의 인스턴스 (instance)라고 한다.
그렇다면 개념은 어떤 정보들이 담겨있을까? 개념의 세 가지 관점은 다음과 같다.
- 심벌 (symbol): 개념을 가리키는 간략한 이름 또는 명칭 > 트럼프 카드
- 내연 (intension): 개념의 완전한 정의를 나타내며, 내연의 의미를 이용해 객체가 개념에 속하는지 여부를 확인할 수 있다. > 트럼프는 몸이 납작하고 두 손과 두 발이 네모난 몸 모서리에 달려 있다.
- 외연 (extension): 개념에 속하는 모든 객체의 집합 > 정원사, 병사, 신하 등등은 트럼프 카드에 속한다.
- 개념이 이렇게 구성되어 있다는 사실보다는 개념을 이용해 객체를 분류 (classification)할 수 있다는 것이 더 중요하다. 이것은 객체지향 패러다임이 복잡성을 극복하는 기본적인 수단이기 때문이다. 클래스 (class)와 분류의 철자가 공통적이다!
분류는 특정한 객체를 특정한 개념의 객체 집합에 포함시키거나 포함시키지 않는 작업을 의미한다.
어떤 객체를 어떤 개념으로 분류할지가 객체지향의 품질을 결정한다. 또한 적절한 분류 체계는 개발자에게 정신적인 지도를 제공한다.
타입
공학자들은 개념을 더 세련되 보이도록 타입 (type)이라는 것을 정의하였다.
메모리 세상에서는 타입이 정해지지 않는다. 타입이 없다는 것은 메모리 안의 데이터를 다룰 수 있는 단 하나의 타입 (비트열)만이 존재한다는 것을 의미한다.
애플리케이션에서 이렇게 타입이 정해지지 않은 데이터를 다룰 때면, 이 값이 숫자인지, 문자인지, 메모리 상의 주소인지 혼란스러운 때가 많아지게 된다. 따라서 개발자들은 메모리 안의 데이터에 특정한 의미를 부여함으로써 이 혼란을 줄여나가기 시작했다. 숫자형, 문자열형, 논리형 등등 말이다.
이를 통해 타입 시스템의 목적은 메모리 안의 모든 데이터가 비트열로 보임으로써 야기되는 혼란을 방지하는 것임을 알 수 있다.
또한 타입의 특징은 다음과 같다.
- 타입은 데이터가 어떻게 사용되느냐에 관한 것이다. 의미를 부여한 이유는 그 의도에 맞게 사용되기 때문이다.
- 타입에 속한 데이터를 메모리에 어떻게 표현하는지는 외부로부터 감춰진다. 개발자는 겉으로 드러나는 특징만 가지고 사용해도 충분하며, 예시로 문자열형 데이터가 메모리 안에서는 어떻게 표현되는지 같은 것은 알 필요가 없다.
실제 객체지향에서의 타입도 전통적인 데이터 타입과 연관성이 있다. 우리는 객체지향 프로그램을 작성할 때 객체를 일종의 데이터처럼 사용한다. 객체지향 프로그램에서 사용되는 모든 객체의 상태를 모으면 애플리케이션에서 관리해야 하는 전체 데이터를 표현할 수 있다.
그러나 객체가 실제 데이터는 아니다. 객체지향에서 중요한 것은 상태가 아니라 객체의 행동이기 때문이다. 상태는 단순히 행동의 부수 효과를 표현하기 위해 존재하는 부산물일 뿐이다.
위에서 언급한 타입의 특징은 곧 객체의 특징과 같다.
- 객체가 어떤 행동을 하느냐에 따라 객체의 타입이 결정된다. > 상태는 중요하지 않다. 중요한 것은 객체의 “행동”이다.
- 객체가 서로 다른 상태를 가지고 있다고 하더라도 동일한 행동을 한다면 두 객체는 같은 타입이다. 반대로 객체가 서로 같은 상태를 가지고 있다고 하더라도 다른 행동을 한다면 두 객체는 다른 타입이다.
- 객체의 내부적인 표현은 외부로부터 감춰진다. > 이는 객체의 캡슐화를 의미한다.
첫 번째 특징으로부터 객체지향의 중요한 개념인 다형성이 설명된다. 이전 장인 2장: 이상한 나라의 객체에서 보면, 행동을 수행할 적절한 객체를 선택하라. 고 되어 있다. 행동은 곧 객체의 책임을 의미한다. 따라서 동일한 행동은 동일한 책임을 의미하며, 동일한 책임은 동일한 메시지 수신을 의미한다. 같은 메시지를 수신하더라도 각기 다른 방법으로 응답할 수 있는 것을 다형성이라고 한다.
첫 번째 특징을 정확히 준수하기 위해서는 객체가 외부에 제공하는 책임을 먼저 결정해야 한다. 그래야만 행동에 따라 객체를 분류할 수 있다. 이야기했듯이 행동은 곧 객체의 책임을 뜻하기 때문이다. 이는 저번에도 작성했던 책임 주도 설계를 의미한다.
인간과 트럼프 카드들을 분류해 본다고 하자. 데이터를 중심으로 분류해보려고 한다면, 인간과 트럼프 카드 모두 팔다리가 있기에 분류하기 애매하다. 그러나 행동을 중심으로 분류해보면, 사람은 똑바로 팔 다리를 통제할 수 있는 반면 트럼프 카드들은 종이기 때문에 팔 다리가 펄럭거린다.
타입의 계층
이상한 나라의 앨리스에서의 트럼프 캐릭터들은 엄밀히 따져봤을 때 실제 트럼프가 아니다. 실제 트럼프와 비슷한 행동을 할 수 있지만, 인간처럼 걸어 다닐 수 있다. 그럼에도 트럼프 캐릭터로 분류했던 이유는 트럼프가 가지고 있던 행동을 가지고 있기 때문이다.
이를 더 세부적으로 표현하면 트럼프라는 외연 안에 트럼프 인간이라는 외연이 부분 집합으로 있는 것이다. 트럼프 인간은 트럼프의 특징을 가진 채로 더 특별한 행동들을 가진다. 이렇게 트럼프 카드 - 트럼프 인간의 관계와 같은 것을 일반화/특수화 관계 (generalization/specialization)라고 한다.
계속 행동을 이야기하는 것으로부터 우리는 일반화/특수화 관계가 행동을 기준으로 구분된다는 것을 유추할 수 있다.
행동의 가짓수와 외연의 크기는 서로 반비례한다. 일반화의 외연은 특수화에 비해 더 크지만, 명시된 행동의 가짓수는 특수화가 더 많이 있기 마련이다. 일반화는 말 그대로 모든 객체가 일반적으로 수행할 수 있는 행동들만을 가지고, 특수화는 일반화의 특성에 더해 특별한 행동들을 더 할 수 있기 때문이다.
일반화를 보통 슈퍼타입이라고 하고, 특수화를 서브타입이라 한다.
다시 돌아가서 “기껏해야 트럼프에 불과해”라고 했던 앨리스의 말을 다시 들여다보자.
- 앨리스는 등장인물들의 차이점은 배제하고 공통점만을 강조했다.
- 트럼프 인간을 더 단순하게 바라보기 위해 특수한 행동을 배제하고 더 포괄적인 트럼프로 분류했다.
이렇게 객체지향에서는 주로 분류와 일반화/특수화 관계를 동시에 사용하는 경우가 많다.
정적 모델
객체지향에서 타입을 사용하는 이유는 시간에 따라 동적으로 변하는 객체의 복잡성을 극복하기 위해서다.
앨리스의 키가 시시각각으로 변하더라도 앨리스는 결국 앨리스일뿐이다. 이는 동적으로 변하는 앨리스의 상태를 시간과 무관한 정적인 모습으로 다룰 수 있게 해 준다.
이런 관점에서 타입은 결국 추상화다. 불필요한 요소를 제거하고 정적인 관점에서만 생각할 수 있도록 해 주기 때문이다.
이것을 통해 동적 모델과 정적 모델의 의미를 이끌어낼 수 있다.
- 동적 모델이란 시간에 따라 변하는 객체를 포착한 모델을 뜻한다. 객체가 특정 시점에 구체적으로 어떤 상태를 가지는지 표현한다. 이는 런타임 시 객체의 상태 변경을 추적하고 디버깅하는 것으로 표현할 수 있다.
- 정적 모델은 객체가 가질 수 있는 모든 상태와 모든 행동을 시간에 독립적으로 표현한 모델을 뜻한다. 이는 클래스를 작성하는 것으로 표현할 수 있다.
단, 타입과 클래스는 엄밀히 말해 서로 다른 뜻이다. 타입은 객체를 분류하기 위해 사용되며, 클래스는 단지 프로그래밍에서 타입을 구현하는 데 사용되는 메커니즘 중 하나일 뿐이다.
요약
- 추상화의 전략은 첫 번째로 공통점은 취하고 차이점은 버리는 것이며, 두 번째는 불필요한 세부 사항을 제거하는 것이다.
- 개념은 공통점을 기반으로 객체를 나누기 위한 체와 같다.
- 객체를 나누기 위한 기준은 객체의 행동이다. 또한 행동은 곧 책임을 의미한다. 따라서 책임 주도 설계가 중요한 것이다.
- 컴퓨터 세계에서 적용되는 개념은 일반화/특수화 관계로 나뉜다.
- 타입을 사용함으로써 객체지향에서는 시간에 무관한 객체의 특징을 기반으로 정적 모델을 만들 수 있다.
- 타입과 클래스는 엄밀히 말하면 다른 의미다. 클래스는 프로그래밍에서 타입을 구현하기 위한 방법 중 하나일 뿐이다.
'도서 📚 > 📗 객체지향의 사실과 오해' 카테고리의 다른 글
6장: 객체 지도 (0) | 2023.11.08 |
---|---|
5장: 책임과 메시지 (0) | 2023.11.07 |
4장: 역할, 책임, 협력 (0) | 2023.11.05 |
2장: 이상한 나라의 객체 (1) | 2023.11.01 |
1장: 협력하는 객체들의 공동체 (2) | 2023.10.31 |