###### tags: `BOOK` # 객체지향의 사실과 오해 ## 1. 협력하는 객체들의 공동체 > 시너지를 생각하라. 전체는 부분의 합보다 크다. - 스티븐 코비 객체지향 프로그래밍이란 현실 속에 존재하는 사물을 최대한 유사하게 모방해 소프트웨어 내부로 옮겨오는 작업이기 때문에 그 결과물인 객체지향 소프트웨어는 실세계의 투영이며, 객체란 현실 세계에 존재하는 사물에 대한 추상화라는 것이다. 아쉽게도 실세계의 모방이라는 개념은 객체지향의 기반을 이루는 철학적인 개념을 설명하는 데는 적합하지만 유연하고 실용적인 관점에서 객체지향 분석, 설계를 설명하기에는 적합하지 않다. 비유의 적절성을 더나 소프트웨어 방화벽과 건물의 방화벽 사이의 의미적 거리만큼이나 소프트웨어 객체와 실세계 사물 사이에 존재하는 연관성은 희미하다. 소프트웨어 개발자의 역할은 단순히 실세계를 소프트웨어 안으로 옮겨 담는 것이 아니라 고객과 사용자를 만족시킬 수 있는 신세계를 창조하는 것이다. 실세계의 모방이라는 개념이 비현실적임에도 여전히 많은 사람들이 실세계 객체와 소프트웨어 객체 간의 대응이라는 과거의 유산을 반복적으로 재생산하는 이유는 실세계에 대한 비유가 객체 지향의 다양한 측면을 이해하고 학습하는 데 매우 효과적이기 때문이다. 객체를 스스로 생각하고 스스로 결정하는 현실 세게의 생명체에 비유하는 것은 상태와 행위를 '캡슐화'하는 소프트웨어 객체의 '자율성'을 설명하는데 효과적이다. 현실 세계의 사람들이 암묵적인 약속과 명시적인 계약을 기반으로 협력하며 목표를 달성해 나가는 과정은 '메시지'를 주고받으며 공동의 목표를 달성하기 위해 '협력'하는 객체들의 관계를 설명하는 데 적합하다. 실세계의 사물을 기반으로 소프트웨어 객체를 식별하고 구현까지 이어간다는 개념은 객체지향 설계의 핵심 사상인 '연결완전성'을 설명하는 데 적합한 틀을 제공한다. 실세계의 모방이라는 객체지향의 개념은 훌륭한 프로그램을 설계하고 구현하는 실무적인 관점에서는 부적합하지만 객체지향이라는 용어에 담긴 기본 사상을 이해하고 학습하는 데는 매우 효과적이다. 비록 전통적인 관점이 문제 해결방법으로서의 실용적 측면에서는 의심스럽더라도 객체지향이라는 세계를 이해하는 데는 도움될 것이다. ### 협력하는 사람들 #### 커피 공화국의 아침 샐러리맨들이 매일 아침 달콤한 늦잠의 유혹을 물리치며 어딘가로 무거운 발걸음을 향하는 이유는 그곳에 회사가 잇기 때문이다. 다람쥐 챗바퀴 같은 지루한 일상에 한 가지 위안이 있다면 매일 아침 회사 카페테이라에 들러 따듯한 아메리카노를 마시는 일이다. 카페테리아 앞에 길게 늘어선 줄 속에 몸을 맡긴 채 이런저런 생각을 하다 보니 주문할 차례가 다가왔다. 환하게 웃는 얼굴을 보니 안개처럼 짙게 드리워져 있던 우울함의 농담이 조금은 옅어지는 것 같았다. 사원증으로 금액을 결제하고 캐시어로부터 영수증과 진동벨을 받은 후 주문대를 빠져나왔다. 손님의 주문을 받은 캐시어는 미리 준비된 컵의 옆면에 음료의 종류를 적은 후 카운터 옆에 있는 테이블에 놓았다. 캐시어가 컵을 놓은 테이블 위에는 지금까지 주문된 컵이 바리스타를 향해 일렬로 늘어서 있었다. 바리스타는 바쁜 손놀림으로 자신의 차례를 기다리고 있는 컵 하나를 들어 옆면에 적힌 주문 내역을 살펴봤다. 찰나의 순간에 주문 내역을 뇌에 한켠에 적어 넣은 바리스타는ㄴ 커피 머신을 향해 돌아서서 차분히 주문된 커피를 만들기 시작했다. 바리스타는 커피가 채워진 컵을 주문대 우측에 있는 테이블에 올려 놓았다. 캐시어는 진동벨을 울려 커피를 애타게 기다리고 있을 손님에게 준비가 끝났음을 알렸다. 어디선가 바쁜 발걸음이 들려오더니 한 손님이 진동벨을 캐시어에게 반환하고는 테이블 위에 놓인 컵을 재빠르게 채갔다. 손님은 커피를 주문하고, 캐시어는 주문을 받고, 바리스타는 커피를 제조한다. 바리스타의 제조가 끝난 커피는 다시 캐시어에게 전달되고 캐시어는 퀭한 눈으로 카페인을 기다리고 있는 손님에게 커피가 준비됐다는 반가운 소식을 알린다. 커피 한잔을 주문하는 이 작은 이벤트를 완성하는 데도 여러 사람의 조율과 조화가 필요한 것이다. 커피를 주문하고 제조하는 과정은 역할, 책임, 협력이라는 사람의 일상 속에 항상 스며들어 있는 세 가지 개념이 한데 어울려 조화를 이루며 만들어 낸 것이다. 감미로운 커피 맛을 음미하며 만족스럽게 자신의 자리로 돌아가는 모든 과정 속에는 손님, 캐시어, 바리스타 사이의 암묵적인 협력 관계가 존재한다. 따뜻한 커피와 함께할 수 있는 소박한 아침 시간의 여유를 누릴 수 있는 이유는 커피를 주문하는 손님, 주문을 받는 캐시어, 커피를 제조하는 바리스타라는 역할이 존재하기 때문이다. 손님, 캐시어, 바리스타는 주문한 커피를 손님에게 제공하기 위해 협력하는 과정에서 자신이 맡은 바 책임을 다한다. 커피 주문이라는 협력에 참여하는 모든 사람들은 커피가 정확하게 주문되고 주문된 커피가 손님에게 정확하게 전달될 수 있도록 맡은 바 역할과 책임을 다하고 있는 것이다. 역할, 책임, 협력은 우리가 삶을 영위하기 위해 다른 사람과 접촉하는 모든 곳에 존재한다. 때마침 손 안에 쥐고 있던 진동벨이 울렸다. 커피를 받아 들고 엘리베이터에 타고 나면 커피 주문이라고 불리는 협력 관계는 깔끔하게 마무리될 것이다. 객체지향에서 가장 중요한 개념 세 가지, 그것은 바로 역할, 책임, 협력이다. 이제 실생활에서 일어나는 커피 주문이라는 기분 좋은 협력 관계를 통해 객체지향의 기본적인 개념을 살펴보도록 하자. #### 요청과 응답으로 구성된 협력 사람들은 스스로 해결하지 못하는 문제와 마주치면 문제 해결에 필요한 지식을 알고 있거나 서비스를 제공해줄 수 있는 사람에게 도움을 요청한다. 일반적으로 하나의 문제를 해결하기 위해 다수의 사람 혹은 역할이 필요하기 때문에 한사람에 대한 요청이 또 다른 사람에 대한 요청을 유발하는 것이 일반적이다. 따라서 요청은 연쇄적으로 발생한다. - 커피 주문이라는 협력은 손님이 캐시어에게 원하는 커피를 주문하면서 시작된다. 손님이 캐시어에게 주문하는 것은 커피를 제공해 줄 것을 캐시어에게 요청하는 것이다. - 주문을 받은 캐시어는 주문 내역이 기록된 컵을 전달함으로써 바리스타에게 주문된 커피를 제조해줄 것을 요청한다. 요청을 받은 사람은 주어진 책임을 다하면서 필요한 지식이나 서비스를 제공한다, 즉, 다른 사람의 요청에 응답한다. 요청이 연이어 발생하기 때문에 응답 역시 요청의 방향과 반대 방향으로 연쇄적으로 전달된다. - 바리스타는 커피를 제조한 후 제조가 완료됐음을 캐시어에게 알려주는 것으로 캐시어의 요청에 응답한다. - 캐시어는 진동벨을 울려 손님에게 주문된 커피가 준비됐음을 알림으로써 손님의 주문에 응답한다, 요청과 응답을 통해 다른 사람과 협력할 수 있는 능력은 인간으로 하여금 거대하고 복잡한 문제를 해결할 수 있는 공동체를 형성할 수 있게 만든다. 협력의 성공은 특정한 역할을 맡은 각 개인이 얼마나 요청을 성실히 이행하는가에 달려 있다. #### 역할과 책임 사람들은 다른 사람과 협력하는 과정 속에서 특정한 역할을 부여받는다. 역할은 어떤 협력에 참여하는 특정한 사람이 협력 안에서 차지하는 책임이나 임무를 의미한다. 역할이라는 단어는 의미적으로 책임이라는 개념을 내포한다. 역할과 책임은 협력이 원활하게 진행되는 데 필요한 핵심적인 구성 요소다. 사람들이 협력을 위해 특정한 역할을 맡고 역할에 적합한 책임을 수행한다는 사실은 몇 가지 중요한 개념을 제시한다. - 여러 사람이 동일한 역할을 수행할 수 있다. - 역할은 대체 가능성을 의미한다. - 책임을 수행하는 방법은 자율적으로 선택할 수 있다. - 한 사람이 동시에 여러 역할을 수행할 수 있다. ### 역할, 책임, 협력 #### 기능을 구현하기 위해 협력하는 객체들 지금까지 설명한 실세계의 커피를 주문하는 과정은 객체지향의 핵심적이고 중요한 개념을 거의 대부분 포함하고 있다. 이제 커피 주문이라는 협력 관계를 통해 알아본 역할, 책임, 협력의 개념을 객체지향이라는 문맥으로 옮겨 보자. #### 역할과 책임을 수행하며 협력하는 객체들 아리스토텔레스의 말처럼 "인간은 사회적 동물이다." 사람들은 커피 주문과 같은 특정한 목표를 이루기 위해 서로 협력한다. 협력의 핵심은 특정한 책임을 수핸하는 역할들 간의 연쇄적인 요청과 응답을 통해 목표를 달성한다는 것이다. 객체의 세계는 인간의 세계와 유사하다. 사람들의 협력이 객체들의 협력과 다른 점이라면 사람들의 경우 공통의 목표를 달성하기 위해 협력하는 데 비해 객체들의 경우에는 애플리케이션의 기능을 구현하기 위해 협력한다는 점이다. 애플리케이션의 기능은 더 작은 책임으로 분할되고 책임은 적절한 역할을 수행할 수 있는 객체에 의해 수행된다. 객체지향 설계라는 예술은 적절한 객체에게 적절한 책임을 할당하는 것에서 시작된다. 역할은 관련성 높은 책임의 집합이다. 객체의 역할은 사람의 역할과 유사하게 다음과 같은 특징을 지닌다. - 여러 객체가 동일한 역할을 수행할 수 있다. - 역할은 대체 가능성을 의미한다. - 각 객체는 책임을 수행하는 방법을 자율적으로 선택할 수 있다. - 하나의 객체가 동시에 여러 역할을 수행할 수 있다. 역할은 유연하고 재사용 가능한 협력 관계를 구축하는 데 중요한 설계 요소다. 대체 가능한 역할과 책임은 객체지향 패러다임의 중요한 기반을 제공하는 다형성과도 깊이 연관돼 있다. ### 협력 속에 사는 객체 객체지향 애플리케이션의 윤곽을 결정짓는 것은 역할, 책임, 협력이지만 실제로 협력에 참여하는 주체는 객체다. 객체는 애플리케이션의 기능을 구현하기 위해 존재한다. 아주 작은 기능조차 객체 혼자 감당하기에는 버거울 정도로 복잡하고 거대하기 때문에 일반적으로 객체는 다른 객체와의 협력을 통해 기능을 구현하게 된다. 협력 공동체의 일원으로서 객체는 다음과 같은 두 가지 덕목을 갖춰야 하며, 두 덕목 사이에서 균형을 유지해야 한다. 첫째, 객체는 충분히 '협력적'이어야 한다. 둘째, 객체는 충분히 '자율적'이어야 한다. 인간 사회는 자율적인 존재로 구성된 협력 공동체다. 사람들은 다른 사람의 요청에 따라 행동하지만 최대한 스스로의 판단에 따라 결정하고 행동한다. 객체지향 설계의 묘미는 다른 객체와 조화롭게 협력할 수 있을 만큼 충분히 개방적인 동시에 협력에 참여하는 방법을 스스로 결정할 수 있을 만큼 충분히 자율적인 객체들의 공동체를 설계하는 데 있다. #### 상태와 행동을 함께 지닌 자율적인 객체 흔히 객체를 상태와 행동을 함깨 지닌 실체라고 정의한다. 이 말은 객체가 협력에 참여하기 위해 어떤 행동을 해야 한다면 그 행동을 하는 데 필요한 상태도 함께 지니고 있어야 한다는 것을 의미 한다. 객체의 자율성은 객체의 내부와 외부를 명확하게 구분하는 것으로부터 나온다. 객체의 관점에서 자율성이란 자신의 상태를 직접 관리하고 상태를 기반으로 스스로 판단하고 행동할 수 있음을 의미한다. 객체는 행동을 위해 필요한 상태를 포함하는 동시에(바리스타는 커피 제조 방법을 기억하고 있다) 특정한 행동을 수행하는 방법을 스스로 결정할 수 있어야 한다(바리스타는 자신이 알고 있는 방법에 따라 커피를 제조한다). 따라서 객체는 상태와 행위를 하나의 단위로 묶는 자율적인 존재다. 자율적인 객체로 구성된 공동체는 유지보수가 쉽고 재사용이 용이한 시스템을 구축할 수 있는 가능성을 제시한다. #### 협력과 메시지 가장 원초적인 의사소통 수단인 말부터 캐시어가 바리스타에게 도움을 요청하기 위해 컵 옆면에 적어 놓은 글자까지, 인간들은 원활한 협력을 가능케 하는 다양한 메커니즘을 통해 의사소통할 수 있다. 풍부한 메커니즘을 이용해 요청하고 응답할 수 있는 인간들의 세계와 달리 객체지향의 세계에서는 오직 한 가지 의사소통 수단만이 존재한다. 이를 메시지라고 한다. 한 객체가 다른 객체에게 요청하는 것을 메시지를 전송한다고 말하고 다른 객체로부터 요청을 받는 것을 메시지를 수신한다고 말한다. 객체지향의 세계에서 협력은 메시지를 전송하는 객체와 메시지를 수신하는 객체 사이의 관계로 구성된다. 이때 메시지를 전송하는 객체를 송신자라고 부르고 메시지를 수힌하는 객체를 수신자라고 부른다. #### 메서드와 자율성 객체가 수신된 메시지를 처리하는 방법을 메서드라고 부른다. 객체지향 프로그래밍 언어에서 메서드는 클래스 안에 포함된 함수 또는 프로시저를 통해 구현된다. 따라서 어떤 객체에게 메시지를 전송하면 결과적으로 메시지에 대응되는 특정 메서드가 실행된다. 메시지와 메서드의 분리는 객체의 협력에 참여하는 객체들 간의 자율성을 증진시킨다. 외부의 요청이 무엇인지를 표현하는 메시지와 요청을 처리하기 위한 구체적인 방법인 메서드를 분리하는 것은 객체의 자율성을 높이는 핵심 메커니즘이다. 이것은 캡슐화라는 개념과도 깊이 관련돼 있다. ### 객체지향의 본질 다음은 지금까지 설명한 내용을 모두 종함해서 객체지향의 개념을 간략하게 정리한 것이다. - 객체지향이란 시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법이다. - 자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다. - 객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다. - 객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수힌한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다. #### 객체를 지향하라 에스키모인들의 언어에는 하늘에서 내리는 눈을 의미하는 어휘의 수가 무려 400여 개에 이른다는 이야기가 있다. 사피어-워프 가설의 핵심은 "언어가 인간의 사고를 지배한다"는 언어결정론으로, 에스키모인들에게 눈을 지칭하는 많은 어휘가 존재하기 때문에 한국인에 비해 눈에 관해 좀 더 상세하고 정확하게 생각할 수 있다는 것이다. 유감스럽게도 에스키모인들의 눈에 관한 이 흥미로운 이야기는 사실이 아니다. "인류학자 로라 마틴은 한 다리 건널 때마다 부풀려지는 도시의 전설처럼 어떻게 이 이야기가 부풀려졌는지 기록하고 있다." 다양한 프로그래밍 언어가 출현하고 수많은 프로구래밍 서적이 출간되는 과정 속에서 클래스에 대한 중요성이 과하다 싶을 정도로 강조됐다. 한 다리를 건너면서 조금씩 부풀려지는 에스키모인들의 일화처럼 클래스의 중요성은 프로그래밍 언어라는 다리를 건너면서 조금씩 부풀려졌다. 그 결과 사람들은 객체지향의 중심에 있어야 할 객체로부터 조금씩 멀어져 갔다. 이제 많은 사람들은 객체지향이라는 말을 들으면 조건반사적으로 클래스라는 단어를 떠올린다. 클래스가 객체지향 프로그래밍 언어의 관점에서 매우 중요한 구성요소인 것은 분명하지만 객체지향의 핵심을 이루는 중심 개념이라고 말하기에는 무리가 있다. 훌륭한 객체지향 설계자가 되기 위해 거쳐야 할 첫 번째 도전은 코드를 담는 클래스의 관점에서 메시지를 주고받는 객체의 관점으로 사고의 중심을 전환하는 것이다. 객체지향의 중심에는 클래스가 아니라 객체가 위치하며, 중요한 것은 클래스들의 정적인 관계가 아니라 메시지를 주고받는 객체들의 동적인 관계다. 클래스의 구조와 메서드가 아니라 객체의 역할, 책임 협력에 집중하라. 객체지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다. ## 2. 이상한 나라의 객체 > 객체지향 패러다임은 지식을 추상화하고 추상화한 지식을 객체 안에 캡슐화함으로써 실세계 문제에 내재된 복잡성을 관리하려고 한다. 객체를 발견하고 창조하는 것은 지식과 행동을 구조화하는 문제다. - 레베카 워프스브록 심리학자인 엘리자베스 스펠크와 필립 켈만은 어린 아기들이 물체를 인지하는 방법을 연구하기 위해 한 가지 실험을 수행했다. 실험에서 심리학자들이 지루함의 기준으로 삼은 것은 아기의 시선이 머무는 시간이다. 두 심리학자는 아기의 시선이 머무는 상대적인 시간을 기준으로 지루함과 놀라움을 구분할 수 있다는 가정하에 아기의 인지능력을 판단할 수 있는 실험 한 가지를 고안했다. 필요한 재료는 아기의 주의를 끌기 위한 두 개의 막대와 막대를 가리기 위한 가림막이 전부다. 가림막 뒤편으로 한 막대 끝은 위로, 다른 막대 끝은 아래로 튀어나와 보이도록 위치시킨 후 아기가 지루해할 때까지 두 막대를 동일한 방향으로 함께 이동시킨다. 아기가 막대를 어떻게 인지하는지를 확인할 수 있는 방법은 가림막 뒤에서 하나의 막대를 움직이거나 두 개의 막대를 하나인 것처럼 보이도록 동시에 움직인 후 가림막을 치워 아기의 반응을 살펴보는 것이다. 두 심리학자는 3개월 정도밖에 안 된 아기들도 성인과 마찬가지로 두 개의 막대가 함께 움직일 경우 마음 속으로 두 물체를 하나의 물체로 결합할 수 있다고 결론 내렸다. 이 실험으로 사람은 태어난 지 얼마 안 된 시기부터 뚜렷한 경계를 가지고 함께 행동하는 물체를 하나의 개념으로 인지한다는 사실을 알 수 있다. ### 객체지향과 인지 능력 많은 사람들이 객체지향을 직관적이고 이해하기 쉬운 패러다임이라고 말하는 이유는 객체지향이 세상을 자율적이고 독립적인 객체들로 분해할 수 있는 인간의 기본적인 인지 능력에 기반을 두고 있기 때문이다. 고개를 들어 주위를 둘러보면 객체라고 부를 수 있는 다양한 존재를 볼 수 있다. 인간이 직접적으로 지각할 수 있는 대부분의 객체는 물리적인 경계를 지닌 구체적인 사물이다. 그러나 인간의 인지 능력은 물리적인 한계를 넘어 개념적으로 경계지을 수 있는 추상적인 사물까지도 객체로 인식할 수 있게 한다. 즉, 객체란 인간이 분명하게 인지하고 구별할 수 있는 물리적인 또는 개념적인 경계를 지닌 어떤 것이다. 객체지향 패러다임은 인간이 인지할 수 있는 다양한 객체들이 모여 현실 세계를 이루는 것처럼 소프트웨어의 세계 역시 인간이 인지할 수 있는 다양한 소프트웨어 객체들이 모여 이뤄져 있다는 믿음에서 출발한다. 그러나 현실 세계와 소프트웨어 세계 사이의 유사성은 여기까지일 뿐이다. 현실세계의 전등은 사람의 손길 없이는 스스로 불을 밝힐 수 없지만 소프트웨어 세계의 전등은 외부의 도움 없이도 스스로 전원을 켜거나 끌 수 있다. 실행 중인 객체지향 애플리케이션의 내부를 들여다볼 수 있다면 겉으로는 우리가 알고 있는 세계와 유사해 보이지만 본질적으로는 매우 이질적인 모습을 지닌 세계와 마주치게 될 것이다. ### 객체, 그리고 이상한 나라 #### 이상한 나라의 앨리스 도지슨은 앨리스 리델이라는 이름을 가진 이 소녀를 기쁘게 해주기 위해 주인공이 토끼를 따라 굴 속으로 내려가면서 겪게 되는 환상적인 이야기 한 편을 짓게 된다. 몇 년이 지난 후 도지슨은 루이스 캐럴(Lewis Carroll)이라는 필명으로 소녀에게 해주었던 이야기를 책으로 출간했다.이 책이 바로 전 세계 어린이들에게 꾸준한 사랑을 받아온 ⌜이상한 나라의 앨리스(Alice's Adventures in Wonderland)⌟다. 이 책에서 가장 인상 깊은 장면은 이야기 전반부에 앨리스가 아름다운 정원에 들어가기 위해 몸의 크기를 작게 줄이는 부분이다. > 언니와 함께 시냇가에 앉아 무료함을 달래던 앨리스는 조끼를 입고 회중시계를 든 채 시간에 쫓겨 허겁지겁 뛰어가는 토끼를 발견하고는 깜짝 놀란다. 호기심을 누를 수 없었던 앨리스는 토끼의 뒤를 쫓아 굴 속으로 들어가지만 갑자기 땅이 꺼지면서 컴컴한 굴 밑으로 떨어지게 된다. 오랜 시간이 흐른 뒤에 마침내 앨리스의 몸은 천장이 낮은 긴 통로 위로 떨어지게 된다.<br> > 앨리스는 복도 주변을 둘러보다 커튼 뒤에 숨겨져 있던 작은 문을 발견했는데, 그 문 뒤에는 아름다운 정원이 펼쳐져 있었다. 하지만 문의 높이가 40센티미터가 채 되지 않았기 때문에 앨리스는 문을 지나 아름다운 정원에 들어갈 수 없었다.<br> > 정원의 아름다움에 매료된 앨리스는 자신의 몸을 작게 만들 방법을 고민하기 시작했다. 방법을 찾기 위해 주위를 둘러보던 중에 탁자 위에 '마셔라'라는 커다란 글자가 인쇄된 병이 놓여 있는 것을 발견한다. 병 속의 액체를 들이키자 앨리스의 키가 24센티미터 정도로 작아졌다. 여유롭게 문을 통과할 수 있을 정도로 키가 줄었지만 이번에는 너무 작아져서 탁자 위의 열쇠를 이용할 수 없게 되었다.<br> > 그때 앨리스의 눈에 탁자 아래에 놓여 있는 케이크가 들어왔다. 앨리스가 케이크를 조금 베어물자 이번에는 머리가 천장에 닿을 만큼 앨리스의 몸이 커졌다.<br> > 이때 곁을 지나가던 토끼가 앨리스를 보고 놀라 들고 있던 부채를 떨어뜨리고는 달아나 버렸다. 앨리스는 더위를 식힐 요량으로 토끼가 떨어뜨린 부채를 이용해 부채질을 하기 시작했다. 그러자 앨리스의 몸이 서서히 작아지더니 60센티미터 정도의 크기로 줄어들고 말았다.<br> > 우여곡절 끝에 담뱃대를 뻐끔거리고 있는 쐐기벌레를 만난 앨리스는 쐐기벌레로부터 버섯 하나를 얻게 된다. 쐐기벌레는 버섯의 한쪽을 먹으면 몸이 커지고 다른 한쪽을 먹으면 몸이 작아진다는 말을 남기고는 풀밭 속으로 사라져 버렸다.<br> > 앨리스는 버섯의 한쪽을 먹어 몸을 키우다가 몸이 너무 커지면 반대쪽을 먹어 몸을 작게 줄였다. 반대로 몸이 너무 작아지면 다른 쪽을 먹어 몸의 크기를 조금씩 늘려 나갔다. 앨리스는 매우 신중하게 버섯의 양쪽을 번갈아 먹으며 몸의 크기를 조절했다.<br> > 커졌다 작아지고, 작아졌다 커지기를 반복하던 앨리스는 마침내 몸의 크기를 원래 상태로 돌릴 수 있었다. 탁자 위에 놓여 있는 열쇠를 이용해 문을 여는 데 성공한 앨리스는 버섯의 다른 쪽을 베어물어 다시 몸의 크기를 작게 만든 후 문을 통과해 그렇게 고대하던 아름다운 정원으로 발길을 늘여 놓을 수 있었다. 이야기의 많은 부분이 생략됐지만 작은 문을 통과하기 위해 온갖 고초를 겪었던 앨리스의 애처로운 모습을 떠올리는 데는 무리가 없을 것이다. #### 앨리스 객체 앞의 이야기는 앨리스가 겪고 있는 키의 변화에 초점을 맞추고 있다. 결국 앨리스의 키를 변화시키는 것은 앨리스의 행동이다. 앨리스가 하는 행동에 따라 앨리스의 상태가 변하게 된다. 앨리스의 상태를 결정하는 것은 행동이지만 행동의 결과를 결정하는 것은 상태다. 결국 케이크를 먹거나 부채질을 하기 전에 앨리스의 키가 얼마였느냐가 케이크를 먹거나 부채질을 한 후의 앨리스의 키를 결정한다. 따라서 앨리스가 한 행동의 결과는 앨리스의 상태에 의존적이다. 상태에 따라 행동의 결과가 달라지는 또 다른 예로 앨리스가 정원에 도달하기 위해 문을 통과하는 장면을 들 수 있다. 앨리스가 성공적으로 문을 통과할 수 있는지 여부는 전적으로 앨리스의 키가 얼마인가에 달렸다. 문을 통과한다는 행동의 결과는 앨리스의 위치라는 상태를 이용해 쉽게 설명할 수 있다. 앨리스가 문을 통과하는 데 성공했다면 앨리스의 위치는 아름다운 정원으로 바뀌어 있을 것이다. 그러나 앨리스가 문을 통과하지 못했다면 여전히 천장이 낮은 긴 통로 안에 있을 것이다. 어떤 행동의 성공 여부는 이전에 어떤 행동들이 발생했는지에 영향을 받는다는 사실도 눈여겨보기 바란다. 이것은 행동 간의 순서가 중요하다는 것을 의미한다. 문을 통과하는 행동이 성공하려면 음료나 케이크를 먹는 행동이 선행되어야만 한다. 행동에 의해 앨리스의 상태가 변경되더라도 앨리스가 앨리스라는 사실은 변하지 않는다. 지금까지 설명한 내용을 바탕으로 앨리스의 특징을 요약해 보자. - 앨리스는 상태를 가지며 상태는 변경 가능하다. - 앨리스의 상태를 변경시키는 것은 앨리스의 행동이다. - 행동의 결과는 상태에 의존적이며 상태를 이용해 서술할 수 있다. - 행동의 순서가 결과에 영향을 미친다. - 앨리스는 어떤 상태에 있더라도 유일하게 식별 가능하다. 무슨 상관이 있길래 객체지향을 설명하는 책에서 앨리스의 길고 지루한 모험담을 늘어놓는 것일까? 그것은 이상한 나라에 떨어진 앨리스가 객체지향 세계에 떨어진 객체들과 중요한 공통점 몇 가지를 공유하기 때문이다. ### 객체, 그리고 소프트웨어 나라 인간의 인지 능력 안에서 개수를 셀 수 있고, 다른 사물과 구분할 수 있으며, 생성 시점을 알 수 있고, 독립적인 하나의 단위로 인식할 수 있는 모든 사물은 객체다. 객체의 다양한 특성을 효과적으로 설명하기 위해서는 객체를 상태(state), 행동(behavior), 식별자(identity)를 지닌 실체로 보는 것이 가장 효과적이다. 이 책에서는 객체를 다음과 같이 정의하기로 한다. > 객체란 식별 가능한 개체 또는 사물이다. 객체는 자동차처럼 만질 수 있는 구체적인 사물일 수도 있고, 시간처럼 추상적인 개념일 수도 있다. 객체는 구별 가능한 식별자, 특징적인 행동, 변경 가능한 상태를 가진다. 소프트웨어 안에서 객체는 저장된 상태와 실행 가능한 코드를 통해 구현된다. 이제 앨리스가 헤매던 이상한 나라를 벗어나 객체지향이라는 나라에 살고 있는 객체의 관점에서 상태, 행동, 식별자의 개념을 정리해 보자. #### 상태 ##### 왜 상태가 필요한가 객체가 주변 환경과의 상호작용에 어떻게 반응하는가는 그 시점까지 객체에 어떤 일이 발생했는냐에 좌우된다. 어떤 행동의 결과는 과거에 어떤 행동들이 일어났었느냐에 의존한다는 것이다. 그러나 이 방법은 앨리스가 과거에 했던 모든 행동을 기억해야만 가능하기 때문에 행동의 결과를 설명하는 것을 매우 어렵게 만든다. 따라서 인간은 행동의 과정과 결과를 단순하게 기술하기 위해 상태라는 개념을 고안했다. 상태를 이용하면 과거의 모든 행동 이력을 설명하지 않고도 행동의 결과를 쉽게 예측하고 설명할 수 있다. 상태를 이용하면 과거에 얽매이지 않고 현재를 기반으로 객체의 행동방식을 이해할 수 있다. 상태는 근본적으로 세상의 복잡성을 완화하고 인지 과부하를 줄일 수 있는 중요한 개념이다. ##### 상태와 프로퍼티 앨리스가 문을 통과하면서 겪게 되는 소동 속에는 객체라고 부를 수 있는 다양한 사물들이 출현한다. 그러나 세상에 존재하는 모든 것들이 객체인 것은 아니다. 숫자, 문자열, 양, 속도, 시간, 참/거짓과 같은 단순한 값들은 객체가 아니다. 단순한 값들은 그 자체로 독립적인 의미를 가지기보다는 다른 객체의 특성을 표현하는 데 사용된다. 다시 말해 다른 객체의 상태를 표현하기 위해 사용된다. 때로는 단순한 값이 아니라 객체를 사용해 다른 객체의 상태를 표현해야 할 때가 있다. 앨리스가 현재 음료를 들고 있는 상태인지를 표현하고 싶다면 어떻게 할 것인가? 가장 간단하고 직관적인 방법은 앨리스의 상태 일부를 음료라는 객체를 이용해 표현하는 것이다. 객체지향 관점에서 앨리스는 음료에 관해 알고있는 상태이며, 앨리스 객체와 음료 객체는 서로 연결돼 있다. 따라서 앨리스의 상태는 키와 위치라는 단순한 값과 음료라는 객체의 조합으로 표현할 수 있다. 결론적으로 모든 객체의 상태는 단순한 값과 객체의 조합으로 표현할 수 있다. 이때 객체의 상태를 구성하는 모든 특징을 통틀어 객체의 프로퍼티(property)라고 한다. 일반적으로 프로퍼티는 변경되지 않고 고정되기 때문에 '정적'이다. 반면 프로퍼티 값(property value)은 시간이 흐름에 따라 변경되기 때문에 '동적'이다. 앨리스의 키는 음료를 마시면 작아질 것이고, 문을 통과하면 위치가 정원으로 바뀔 것이며, 음료를 다 마신 후에는 현재 가지고 있는 음료를 버리게 될 것이다. 이 시점에 앨리스의 키는 40센티미터로 줄어있으며 위치는 정원으로 바뀌어 있다. 또한 더는 음료를 가지고 있지 않은 것으로 보아 음료를 마시고 난 후 어딘가에 음료를 버린 것으로 보인다. 이전 시점에서는 앨리스와 음료 사이에 선이 존재했지만 이 시점에서는 선이 사라졌다는 것에 주목하라. 이것은 이전 시점에서는 앨리스가 음료에 관해 알고 있었지만 이 시점이 되면 음료에 관해 알지 못하는 상태로 변경됐음을 의미한다. 이처럼 객체와 객체 사이의 의미 있는 연결을 링크(link)라고 한다. 객체와 객체 사이에는 링크가 존재해야만 요청을 보내고 받을 수 있다. 즉, 객체의 링크를 통해서만 메시지를 주고받을 수 있다. 링크는 객체가 다른 객체를 참조할 수 있다는 것을 의미하며, 이것은 일반적으로 한 객체가 다른 객체의 식별자를 알고 있는 것으로 표현된다. 객체 간의 선으로 표현되는 링크와 달리 객체를 구성하는 단순한 값은 속성(attribute)이라고 한다. 앨리스의 키와 위치는 단순한 값으로 표현되기 때문에 속성이다. 객체의 프로퍼티는 단순한 값인 속성과 다른 객체를 가리키는 링크라는 두 가지 종류의 조합으로 표현할 수 있다. 이 책에서는 객체의 상태를 다음과 같이 정의하기로 한다. > 상태는 특정 시점에 객체가 가지고 있는 정보의 집합으로 객체의 구조적 특징을 표현한다. 객체의 상태는 객체에 존재하는 정적인 프로퍼티와 동적인 프로퍼티 값으로 구성된다. 객체의 프로퍼티는 단순한 값과 다른 객체를 참조하는 링크로 구분할 수 있다. 객체지향의 세계에서 객체는 다른 객체의 상태에 직접적으로 접근할 수도, 상태를 변경할 수도 없다. 자율적인 객체는 스스로 자신의 상태를 책임져야 한다. 외부의 객체가 직접적으로 객체의 상태를 주무를 수 없다면 간접적으로 객체의 상태를 변경하거나 조회할 수 있는 방법이 필요하다. 행동은 다른 객체로 하여금 간접적으로 객체의 상태를 변경하는 것을 가능하게 한다. 객체지향의 기본 사상은 상태와 상태를 조작하기 위한 행동을 하나의 단위로 묶는 것이라는 점을 기억하라. 객체는 스스로의 행동에 의해서만 상태가 변경되는 것을 보장함으로써 객체의 자율성을 유지한다. #### 행동 ##### 상태와 행동 객체의 상태를 변경하는 것은 객체의 자발적인 행동뿐이다. 객체의 행동에 의해 객체의 상태가 변경된다는 것은 행동이 부수 효과(side effect)를 초래한다는 것을 의미한다. 앞에서 설명한 것처럼 객체의 행동은 객체의 상태를 변경시키지만 행동의 결과는 객체의 상태에 의존적이다. 따라서 상태와 행동 사이에는 다음과 같은 관계가 있음을 알 수 있다. - 객체의 행동은 상태에 영향을 받는다. - 객체의 행동은 상태를 변경시킨다. 이것은 상태라는 개념을 이용해 행동을 다음의 두 가지 관점에서 서술할 수 있음을 의미한다. - 상호작용이 현재의 상태에 어떤 방식으로 의존하는가 - 상호작용이 어떻게 현재의 상태를 변경시키는가 앨리스가 통과해야 하는 문의 크기가 40센티미터라고 가정하면 문을 통과하는 행동은 과거의 행동을 돌아볼 필요 없이 앨리스의 '키'와 '위치'라는 두 가지 상태를 이용해 간단하게 서술할 수 있다. - 앨리스의 키가 40센티미터 이하라면 문을 통과할 수 있다. - 문을 통과한 후에 앨리스의 위치는 아름다운 정원으로 바뀌어야 한다. 상태를 이용하면 복잡한 객체의 행동을 쉽게 이해할 수 있다. ##### 협력과 행동 객체는 다른 객체와 적극적으로 상호작용하며 '협력하는 객체들의 공동체'에 참여하기 위해 노력한다. 객체가 다른 객체와 협력하는 유일한 방법은 다른 객체에게 요청을 보내는 것이다. 요청을 수신한 객체는 요청을 처리하기 위해 적절한 방법에 따라 행동한다. 따라서 객체의 행동은 객체가 협력에 참여할 수 있는 유일한 방법이다. 객체가 어떤 행동을 하도록 만드는 것은 객체가 외부로부터 수신한 메시지다. 객체는 수신된 메시지에 따라 적절히 행동하면서 협력에 참여하고 그 결과로 자신의 상태를 변경한다. 객체는 협력에 참여하는 과정에서 자기 자신의 상태뿐만 아니라 다른 객체의 상태 변경을 유발할 수도 있다. 정리하면 객체의 행동으로 인해 발생하는 결과는 두 가지 관점에서 설명할 수 있다. - 객체 자신의 상태 변경 - 행동 내에서 협력하는 다른 객체에 대한 메시지 전송 이 책에서는 행동을 다음과 같이 정의한다. > 행동이란 외부의 요청 또는 수신된 메시지에 응답하기 위해 동작하고 반응하는 활동이다. 행동의 결과로 객체는 자신의 상태를 변경하거나 다른 객체에게 메시지를 전달할 수 있다. 객체는 행동을 통해 다른 객체와의 협력에 참여하므로 행동은 외부에 가시적이어야 한다. ##### 상태 캡슐화 현실 속에서 앨리스는 스스로 음료를 마시는 능동적인 존재지만 음료는 스스로는 아무것도 할 수 없는 수동적인 존재다. 그러나 객체지향의 세계에서 모든 객체는 자신의 상태를 스스로 관리하는 자율적인 존재다. 앨리스가 음료를 마시는 행동은 앨리스 자신의 키를 작게 만든다. 따라서 앨리스 자신의 상태를 변경한다. 이 과정에서 앨리스는 자신이 먹은 양만큼 음료의 양을 줄여달라고 메시지를 전송한다. 이것이 앨리스가 음료를 마신다는 행동에 대한 모든 것이다. 음료의 양이 줄어들 것인지는 메시지를 수신한 음료가 결정할 사항이며, 앨리스와는 무관하다. 앨리스가 음료를 마시는 과정에서 이뤄지는 메시지를 통한 앨리스와 음료 사이의 협력 관계를 보자. 앨리스에게 전달되는 메시지는 drinkBeverage()이고 음료에 전달되는 메시지는 drunken(quantity)다. 객체는 상태를 캡슐 안에 감춰둔 채 외부로 노출하지 않는다. 객체가 외부에 노출하는 것은 행동뿐이며, 외부에서 객체에 접근할 수 있는 유일한 방법 역시 행동뿐이다. 객체의 행동을 유발하는 것은 외부로부터 전달된 메시지지만 객체의 상태를 변경할지 여부는 객체 스스로 결정한다. 상태를 외부에 노출시키지 않고 행동을 경계로 캡슐화하는 것은 결과적으로 객체의 자율성을 높인다. 결론적으로 상태를 잘 정의된 행동 집합 뒤로 캡슐화하는 것은 객체의 자율성을 높이고 협력을 단순하고 유연하게 만든다. 이것이 상태를 캡슐화해야 하는 이유다. #### 식별자 객체란 인간의 인지 능력을 이용해 식별 가능한 경계를 가진 모든 사물을 의미한다. 객체가 식별 가능하다는 것은 객체를 서로 구별할 수 있는 특정한 프로퍼티가 객체 안에 존재한다는 것을 의미한다. 이 프로퍼티를 식별자라고 한다, 모든 객체는 식별자를 가지며 식별자를 이용해 객체를 구별할 수 있다. 모든 객체가 식별자를 가진다는 것은 반대로 객체가 아닌 단순한 값은 식별자를 가지지 않는다는 것을 의미한다. 값(value)은 숫자, 문자열, 날짜, 시간, 금액 등과 같이 변하지 않는 양을 모델링한다. 흔히 값의 상태는 변하지 않기 때문에 불변 상태(immutable state)를 가진다고 말한다. 값이 같은지 여부는 상태가 같은지를 이용해 판단한다. 값의 상태가 같으면 두 인스턴스는 동일한 것으로 판단하고 상태가 다르면 두 인스턴스는 다른 것으로 판단한다. 이처럼 상태를 이용해 두 값이 같은지 판단할 수 있는 성질을 동등성(equality)이라고 한다. 객체는 시간에 따라 변경되는 상태를 포함하며, 행동을 통해 상태를 변경한다. 따라서 객체는 가변 상태(mutable state)를 가진다고 말한다. 타입이 같은 두 객체의 상태가 완전히 똑같더라도 두 객체는 독립적인 별개의 객체로 다뤄야 한다. 어린 시절의 여러분을 떠올려보자. 어린 여러분은 현재의 여러분보다 키도 작고 나이도 적지만 두 사람은 동일한 인물이다. 두 객체의 상태가 다르더라도 식별자가 같다면 두 객체를 같은 객체로 판단할 수 있다. 이처럼 식별자를 기반으로 객체가 같은지를 판단할 수 있는 성질을 동일성(identical)이라고 한다. 상태가 가변적인 두 객체의 동일성을 판단하기 위해서는 상태 변경에 독립적인 별도의 식별자를 이용할 수밖에 없다. > 식별자란 어떤객체를 다른 객체와 구분하는 데 사용하는 객체의 프로퍼티다. 값은 식별자를 가지지 않기 때문에 상태를 이용한 동등성 검사를 통해 두 인스턴스를 비교해야 한다. 객체는 상태가 변경될 수 있기 때문에 식별자를 이용한 동일성 검사를 통해 두 인스턴스를 비교할 수 있다. 대부분의 사람들은 값과 객체의 차이점을 혼란스러워하는데, 대부분의 객체지향 프로그래밍 언어에서 두 개념 모두 클래스를 이용해 구현되기 때문이다. 이런 오해의 소지를 줄이기 위해 객체와 값을 지칭하는 별도의 용어를 사용하기도 한다. 참조 객체(reference object), 또는 엔티티(entity)는 식별자를 지닌 전통적인 의미의 객체를 가리키는 용어다. 값 객체(value object)는 식별자를 가지지 않는 값을 가리키는 용어다. 객체 식별자의 개념은 상속, 캡슐화, 다형성과 같은 좀 더 두드러진 개념에 비해 간과하기 쉽다. 그러나 식별자는 객체지향 패러다임의 표현력을 높이는 데 중요한 역할을 한다. 다음은 지금까지 살펴본 객체의 특성을 간략하게 요약한 것이다. - 객체는 상태를 가지며 상태는 변경 가능하다. - 객체의 상태를 변경시키는 것은 객체의 행동이다. - 행동의 결과는 상태에 의존적이며 상태를 이용해 서술할 수 있다. - 행동의 순서가 실행 결과에 영향을 미친다. - 객체는 어떤 상태에 있더라도 유일하게 식별 가능하다. 이제 앞에서 나열한 객체의 모든 특성을 좀 더 쉽게 이해할 수 있는 한 가지 은유를 살펴보자. ### 기계로서의 객체 객체지향의 세계를 창조하는 개발자들의 주된 업무는 객체의 상태를 조회하고 객체의 상태를 변경하는 것이다. 일반적으로 객체의 상태를 조회하는 작업을 쿼리(query)라고 하고 객체의 상태를 변경하는 작업을 명령(command)이라고 한다. 버트란드 마이어는 ⌜Object-Oriented Software Construction⌟에서 객체를 우리가 친숙하게 알고 있는 한 가지 사물에 비유해서 설명하고 있다. 바로 기계다. 기계의 부품은 단단한 금속 외피 안에 감춰져 있기 때문에 기계를 분해하지 않는 한 기계의 내부를 직접 볼 수는 없다. 대신 사람은 기계의 외부에 부착된 사각형과 원모양의 버튼을 이용해서만 기계와 상호작용할 수 있다. 사각형 모양의 버튼을 누르면 객체의 상태를 변경할 수 있다. 사각형 버튼을 누른 시점에는 변경된 상태를 직접 눈으로 볼 수는 없다. 대신 원하는 시점에 원 모양의 버튼을 눌러 객체의 상태를 조회할 수 있다. 앨리스 기계의 하단부에는 '음료를 마시다', '케이크를 먹다', '부채질하다', '버섯을 먹다', '문을 통과하다'라고 적힌 네 개의 사각형 버튼이 있다. 이 버튼들은 모두 기계의 상태를 변경하는 것으로, 앞의 버튼 4개는 앨리스 기계의 키를, 마지막 버튼은 앨리스의 위치를 변경시킨다. 사각형 버튼 바로 위에는 '키', '위치'라는 라벨이 적힌 둥근 모양의 버튼이 있다. 이 버튼들은 기계의 상태를 우측 상단의 디스플레이 창에 출력한다. 사용자가 객체 기계의 버튼을 눌러 상태를 변경하거나 상태 조회를 요청하는 것은 객체의 행동을 유발하기 위해 메시지를 전송하는 것과 유사하다. 버튼을 누르는 것은 기계의 사용자지만 눌린 버튼에 따라 어떤 방식으로 동작할지는 기계 스스로 결정한다. 객체 기계에서 사각형 버튼은 상태를 변경하는 명령을, 둥근 버튼은 상태를 조회하는 쿼리를 의미한다는 것을 쉽게 알 수 있다. 명령과 쿼리는 객체가 외부에 제공하는 행동이라는 점에 주목하라. 여기서 중요한 것은 명령 버튼과 쿼리 버튼 이외의 다른 방법을 통해서는 앨리스 기계를 사용할 수 없다는 것이다. 이것은 객체에 접근할 수 있는 유일한 방법은 객체가 제공하는 행동뿐이라는 점을 강조한다. 즉, 사용자는 객체가 제공하는 명령 버튼과 쿼리 버튼으로 구성된 인터페이스를 통해서만 객체에 접근할 수 있다. 객체 기계가 제공하는 버튼을 통해서만 상태에 접근할 수 있다는 점은 객체의 캡슐화를 강조한다. 기계 은유를 이용하면 객체의 식별자 역시 효과적으로 설명할 수 있다. 객체 간의 메시지를 통한 협력 역시 기계 은유를 사용하면 직관적으로 이해할 수 있다. 앨리스 기계는 내부적으로 키를 작게 변경한 후 링크를 통해 연결된 음료 기계에 '마셔지다'라는 버튼이 눌려지도록 요청을 전송한다. 객체지향 패러다임 관점에서 이것은 '음료를 마시다'라는 메시지를 수신한 앨리스 객체가 메시지를 처리하던 도중 음료 객체에게 '마셔지다'라는 메시지를 전송한 것과 동일하다. 즉, 링크를 통해 연결된 두 객체가 메시지 전송을 통해 협력하고 있는 것이다. 객체를 기계로 바라보는 관점은 상태, 행동, 식별자에 대한 시각적인 이미지를 제공하고 캡슐화와 메시지를 통한 협력 관계를 매우 효과적으로 설명한다. ### 행동이 상태를 결정한다. 객체지향에 갓 입문한 사람들이 가장 쉽게 빠지는 함정은 상태를 중심으로 객체를 바라보는 것이다. 안타깝게도 상태를 먼저 결정하고 행동을 나중에 결정하는 방법은 설계에 나쁜 영향을 끼친다. 첫째, 상태를 먼저 결정할 경우 캡슐화가 저해된다. 상태에 초점을 맞출 경우 상태가 객체 내부로 깔끔하게 캡슐화되지 못하고 공용 인터페이스에 그대로 노출되버릴 확률이 높아진다. 둘때, 객체를 협력자가 아닌 고립된 섬으로 만든다. 객체가 필요한 이유는 애플리케이션의 문맥 내에서 다른 객체와 협력하기 위해서다. 불행하게도 상태를 먼저 고려하는 방식은 협력이라는 문맥에서 멀리 벗어난 채 객체를 설계하게 함으로써 자연스럽게 협력에 적합하지 못한 객체를 창조하게 된다. 셋째, 객체의 재사용성이 저하된다. 객체의 재사용성은 다양한 협력에 참여할 수 있는 능력에서 나온다. 상태에 초점을 맞춘 객체는 다양한 협력에 참여하기 어렵기 때문에 재사용성이 저하될 수밖에 없다. 협력에 참여하는 훌륭한 객체 시민을 양성하기 위한 가장 중요한 덕목은 상태가 아니라 행동에 초점을 맞추는 것이다. 객체는 다른 객체와 협력하기 위해 존재한다. 객체의 행동은 객체가 협력에 참여하는 유일한 방법이다. 따라서 객체가 적합한지를 결정하는 것은 그 객체의 상태가 아니라 행동이다. 객체지향 설계는 애플리케이션에 필요한 협력을 생각하고 협력에 참여하는 데 필요한 행동을 생각한 후 행동을 수행할 객체를 선택하는 방식으로 수행된다. 행동을 결정한 후에야 행동에 필요한 정보가 무엇인지를 고려하게 되며 이 과정에서 필요한 상태가 결정된다. 따라서 객체의 행동을 결정하고 그 후에 행동에 적절한 상태를 결정하게 된다. 협력 안에서 객체의 행동은 결국 객체가 협력에 참여하면서 완수해야하는 책임을 의미한다. 따라서 어떤 책임이 필요한가를 결정하는 과정이 전체 설계를 주도해야 한다. 이 책에서 살펴볼 책임-주도 설계(Responsibility-Driven Design, RDD)는 협력이라는 문맥 안에서 객체의 행동을 생각하도록 도움으로써 응집도 높고 재사용 가능한 객체를 만들 수 있게 한다. 이 장을 통틀어 가장 중요하고 반드시 기억해야 하는 진실은 바로 이것이다. "행동이 상태를 결정한다". ### 은유와 객체 #### 두 번째 도시전설 이 도시전설은 너무 오랫동안 사람들의 뇌리에 뿌리 깊게 박혀 있었던 탓에 아무도 문제라고 제기하지 않았던 것이다. 그것은 바로 '객체지향이란 현실 세계의 모방'이라는 것이다. 객체지향을 현실 세계의 모방이라고 보는 관점은 객체지향 분석/설계란 현실 세계에 존재하는 다양한 객체를 모방한 후 필요한 부분만 취해 스프트웨어 객체로 구현하는 과정이라고 설명한다. 흔히 객체지향을 현실 세계의 추상화라고도 하는데, 그 안에는 현실 세계를 모방해서 단순화한다는 의미가 숨어 있다. 여기서 추상화(abstraction)란 실제의 사물에서 자신이 원하는 특성만 취하고 필요없는 부분을 추려 핵심만 표현하는 행위를 말한다. 그러나 안타깝게도 객체지향 세계는 현실 세계의 단순한 모방이 아니다. 모방과 추상화라는 개념만으로는 현실 객체와 소프트웨어 객체 사이의 관계를 깔끔하게 설명하지 못한다. #### 의인화 그렇다면 현실 속의 객체와 소프트웨어 객체 사이의 가장 큰 차이점은 무엇일까? 그것은 현실 속에서는 수동적인 존재가 소프트웨어 객체로 구현될 때는 능동적으로 변한다는 것이다. 소프트웨어 객체를 창조할 때 우리는 결코 현실 세계의 객체를 모방하지 않는다. 오히려 소프트웨어 안에 창조하는 객체에게 현실 세계의 객체와는 전혀 다른 특징을 부여하는 것이 일반적이다. 여러분이 객체지향 세계를 구축할 때 현실에서 가져온 객체들은 현실 속에서는 할 수 없는 어떤 일이라도 할 수 있는 전지전능한 존재가 된다. 레베카 워프스브록은 현실의 객체보다 더 많은 일을 할 수 있는 소프트웨어 객체의 특징을 의인화(anthropomorphism)라고 부른다. > 객체는 무생물이거나 심지어는 실세계의 개념적인 개체로 모델링될 수도 있지만, 그것들은 마치 우리가 현실 세계에서 에이전트로 행동하는 것처럼 시스템 안에서 에이전트처럼 행동한다. 객체가 현실 세계의 대상보다 더 많이 안다는 것이 모순처럼 보일 수도 있다. 결국, 인간이라는 에이전트 없이 현실의 전화는 서로에게 전화를 걸지 않으며 색은 스스로 칠하지 않는다. 일상적인 체계에서는 어떤 사건이 일어나기 위해 반드시 인간 에이전트가 필요한 반면 객체들은 그들 자신의 체계 안에서 [능동적이고 자율적인] 에이전트다.<br> > 의인화의 관점에서 소프트웨어를 생물로 생각하자. 모든 생물처럼 소프트웨어는 태어나고, 삶을 영위하고, 그리고 죽는다. 심지어 현실 세계에는 존재조차 하지 않는 것들도 소프트웨어 안에서는 생생한 생명을 가진 존재로 재탄생 한다. 소프트웨어 안에 구축되는 객체지향 세계는 현실을 모방한 것이 아니다. 현실의 모습을 조금 참조할 뿐 궁극적인 목적은 현실과 전혀 다른 새로운 세계를 창조하는 것이다. 또한 객체지향의 세계는 현실의 추상화가 아니다. 오히려 객체지향의 세계의 거리는 현실 속의 객체보다 더 많은 특징과 능력을 보유한 객체들로 넘쳐난다. #### 은유 소프트웨어 객체가 현실 세계의 객체와는 전혀 다르다는 사실은 객체지향 분석/설계에 관한 전통적인 관점을 송두리째 흔들기에 충분하다. 그렇다면 객체지향의 세계와 현실 세계 사이에는 전혀 상관이 없는 것인가? 그렇지는 않다. 다만 모방이나 추상화의 수준이 아닌 다른 관점에서 유사성을 가지고 있을 뿐이다. 현실 세계와 객체지향 세계 사잉의 관계를 좀 더 정확하게 설명할 수 있는 단어는 은유(metaphor)다. 은유란 실제로는 적용되지 않는 한 가지 개념을 이용해 다른 개념을 서술하는 대화의 한 형태다. 은유의 본질은 한 종류의 사물을 다른 종류의 사물 관점에서 이해하고 경험하는 데 있다. 우리는 우리가 모르는 사이에 일상 생활에서 은유를 빈번하게 사용하고 있다. "그 여자는 양 같아요"라는 말은 순한 양을 이용해 여자의 성격을 묘사하고 있다. "그 남자는 사자같아요"라는 말은 사나운 사자의 특성을 이용해 남자의 포악한 성격을 묘사하고 있다. 이 같은 관계는 객체지향 모델링에서 발견되는 현실 객체와 소프트웨어 객체의 관계와 일치한다. 현실 속의 객체의 의미 일부가 소프트웨어 객체로 전달되기 때문에 프로그램 내의 객체는 현실 속의 객체에 대한 은유다. 비록 현실 속의 전화기는 스스로 전화를 걸 수 없다고 하더라도 우리가 익히 알고 있는 현실의 전화기라는 개념을 이용해 소프트웨어 객체를 묘사하면 그 객체가 전화를 걸 수 있다는 사실을 쉽게 이해하고 기억할 수 있게 된다. 은유는 표현적 차이(representational gap) 또는 의미적 차이(semantic gap)라는 논점과 관련성이 깊다. 여기서 차이란 소프트웨어에 대해 사람들이 생각하는 모습과 실제 소프트웨어의 표현 사이의 차이를 의미한다. 은유 관계에 있는 실제 객체의 이름을 소프트웨어 객체의 이름으로 사용하면 표현적 차이를 줄여 소프트웨어의 구조를 쉽게 예측할 수 있다. 따라서 소프트웨어 객체에 대한 현실 객체의 은유를 효과적으로 사용할 경우 표현적 차이를 줄일 수 있으며, 이해하기 쉽고 유지보수가 용이한 소프트웨어를 만들 수 있다. #### 이상한 나라를 창조하라 이상한 나라의 앨리스에 수록된 삽화 하나를 감상하면서 이번 장을 마무리하겠다. ![](https://i.imgur.com/vRBJOGH.png) 이 삽화 속에는 우리에게 친숙한 다양한 트럼프 카드와 채셔 고양이, 토끼가 나온다. 그러나 실제 모습은 우리가 알고 있는 현실 속의 모습과는 거리가 멀다. 트럼프들은 얼굴뿐만 아니라 손발이 달려 있으며 채셔 고양이는 웃고 있고 토끼는 옷을 입은 채 두 발로 서 있다. 그럼에도 트럼프 카드가 쉽게 뒤집힐 것이고 채셔 고양이가 야옹 소리를 내며 울고 토끼가 빠르게 달릴 수 있으리라는 것을 쉽게 예상할 수 있다. 이것이 루이스 캐럴이 현실 속의 객체를 바탕으로 은유를 통해 이상한 나라의 객체를 묘사하고 있기 때문이다. 객체지향 설계자로서 우리의 목적은 현실을 모방하는 것이 아니다. 단지 이상한 나라를 창조하기만 하면 된다. 현실을 닮아야 한다는 어떤 제약이나 구속도 없다. 여러분이 창조한 객체의 특성을 상기시킬 수 있다면 현실 속의 객체의 이름을 이용해 객체를 묘사하라.