Book Review - 객체지향의 사실과 오해 1장 리뷰
객체지향의 사실과 오해 1장 리뷰
- STEP 1. 객체지향은 실세계의 모방이다?
- STEP 1.1 실세계 예시를 통한 객체지향 들여다보기
- STEP 1.1.1 요청과 응답으로 구성된 협력
- STEP 1.1.2 역할과 책임
- STEP 1.2 중간 정리
- STEP 1.1 실세계 예시를 통한 객체지향 들여다보기
- STEP 2. 협력 속에 사는 객체
- STEP 2.1 상태와 행동을 함께 지닌 자율적인 객체
- STEP 2.2 협력과 메시지
- STEP 2.3 메서드와 자율성
- STEP 3. 객체지향의 본질
- STEP 4. 객체를 지향하라
개요
이 책을 보고 나서 많은 것들을 깨닫고, 많은 생각을 하게 되었다. 정말 객체지향이란 무엇인지? 에 대해서 가슴에 와닿게 설명해준 책이라 생각한다. 특히 나와 같은 초보들에게 말이다.
이번 포스팅은 이 책을 읽고 같이 OOP에 대해서 좀 더 깊게 들어가고자 조영호님의 “객체지향의 사실과 오해”라는 책의 1장을 리뷰해보자 한다.
STEP 1. 객체지향은 실세계의 모방이다?
객체지향은 실세계를 직접적이고 직관적으로 모델링 할 수 있다.
위의 말을 다시 풀어보자면, 객체지향 세계는 실세계의 모방이라는 뜻이다.
객체지향을 위와 같은 말로 설명할 수 있을까? 이 책의 저자 조용호님은 다음과 같이 말한다.
이러한 설명은 철학적인 개념을 설명하는 데 적합하지만, 유연하고 실용적인 관점에서는 적합하지 않다.
그렇다면? 객체지향과 실세계의 연관성은 어떻게 될까? 이 책에 나온 예를 들어보자.
-
건물의 방화벽과 네트워크의 방화벽
→ 건물의 방화벽은 말 그대로 건물 내에 불이 번지는 것을 막기 위한 방화벽이다.
→ 네트워크의 방화벽은 네트워크 침입을 막는 것이다.
일단, 의미적 거리만큼이나 소프트웨어 객체와 실세계 사물 사이에 존재하는 연관성은 희미하다.
그렇다면 객체지향은 무엇일까?
→ 객체지향의 목표는 실세계를 모방하는 것이 아니다! 오히려 새로운 세계를 창조하는 것이다.
하지만, 실세계의 모방이라는 말은 객체지향의 철학적인 개념을 설명하는 데 적합하다하였다.
나는 실세계의 예시를 통하여, 객체지향이 담고 있는 철학적인 개념 무엇인지? 설명하고자 한다.
STEP 1.1 실세계 예시를 통한 객체지향 들여다보기
출근길은 항상 고되다 현대인들은 이러한 고됨을 덜기 위해 카페를 찾아 커피를 구매한 뒤 본격적인 오전 업무를 진행하기 전 커피 한잔의 여유를 즐기곤 한다. 실세계의 예를 통해서 객체지향을 비교해볼 예시는 바로 출근길의 카페이다.
대부분의 카페는 아래와 같이 주문이 처리될 것이다.
- 손님은 커피를 주문한다.
- 캐시어는 주문을 받는다.
- 바리스타는 커피를 제조한다.
- 바리스타는 제조한 커피를 캐시어에게 전달한다.
- 캐시어는 전달받은 커피를 손님에게 전달한다.
- 손님은 완성된 커피를 받는다.
물론, 캐시어가 바리스타의 역할을 해서 주문을 받고 커피를 제조할 수도 있으며, 반대도 가능할 것이다.
이 내용은 아래서 다뤄 볼 예정이다. 하지만 위의 예시(1~6)를 토대로 설명해보고자 한다.
위와 같이 실세계에서 단순한 커피를 주문하는 작은 이벤트를 완성하는 데도 여러 사람의 조율과 조화가 필요한 것을 볼 수 있다.
모든 음료 주문은 손님이 커피를 주문하고, 캐시어가 주문을 받고, 바리스타가 커피를 제조함으로서 이뤄진다.
이 과정은 역할, 책임, 협력이라는 세 가지 개념이 한데 어울려 조화를 이루며 만들어 낸 것이다.
-
역할
- 주문하는 손님
- 주문을 받는 캐시어
- 커피를 제조하는 바리스타
-
책임
- 손님은 주문할 책임을 수행
- 캐시어는 주문을 받는 책임을 수행
- 바리스타는 주문된 커피를 제조하는 책임을 수행
역할과 책임은 위와 같이 구성된 것을 볼 수가 있다. 그렇다면? 협력은 무엇일까?
위와 같은 역할과 책임 속에 암묵적인 협력이 존재한다. 우리는 이 협력관계가 무엇인지 파악하고자 한다.
STEP 1.1.1 요청과 응답으로 구성된 협력
실세계에서 우리는 스스로 해결하지 못하는 문제와 마주치면 문제 해결에 필요한 지식을 알고 있거나 서비스를 제공해줄 수 있는 사람에게 도움을 **요청(Request)**한다.
위의 예시는 출근길 카페에 대한 요청 예시이다. 하나의 문제를 해결하기 위해서 다 수의 요청이 발생하는 것이 일반적이며, 따라서 요청은 연쇄적으로 발생한다. 응답 또한, 요청의 방향과 반대 방향으로 연쇄적으로 전달 되는 것을 알 수가 있다.
- 손님은 커피를 제조하여 먹고싶은 문제를 해결하고자 함. → 카페에 들러서 커피 주문을 한다.
- 캐시어는 주문을 해결할 수 있으나 커피 제조라는 문제를 해결하지 못한다 → 바리스타에게 커피 요청
- 바리스타는 완성된 커피를 전달한다.
이렇게 요청과 응답을 통해 다른 사람과 협력 할 수 있는 것은 복잡한 문제를 해결할 수 있는 공동체를 형성한다.
STEP 1.1.2 역할과 책임
사람들은 다른 사람들과 협력하는 과정 속에서 특별한 역할(Rule)을 부여받는다.
역할은 어떤 협력에 참여하는 특정한 사람이 협력 안에서 차지하는 책임이나 임무를 의미한다.
위의 예시를 들어서 설명하면, 어떤 사람이 손님이라는 역할을 맡았다면 커피를 주문하는 임무를 맡게되며, 캐시어라는 역할을 맡았으면 손님으로부터 주문을 받아야하는 임무를 맡게된다. 바리스타의 역할을 맡은 사람은 주문된 커피를 제조할 책임이 있다.
위에서 “바리스타는 커피를 제조할 책임이 있다”라 하였는데 즉, 역할은 책임이라는 개념을 내포함을 알 수가 있다.
이러한 사실들은 몇가지 중요한 개념을 제시한다.
- 여러 사람이 동일한 역할을 수행할 수 있다.
- 역할은 대체가능성을 의미한다.
- 책임을 수행하는 방법은 자율적으로 선택할 수 있다.
- 한 사람이 동시에 여러 역할을 수행할 수 있다.
1. 여러 사람이 동일한 역할을 수행할 수 있다.
손님은 단지 커피를 받기만 하면 된다. 바리스타가 누군지 캐시어가 누군지는 신경쓰지 않는다. 만일, 캐시어가 그만둔다하더라도 캐시어라는 역할에 따르는 책임을 수행할 수 있는 다른 사람을 고용하면 된다.
즉, 손님 입장에서는 캐시어가 주문을 받고 커피가 완성됐다는 사실을 통보하는 책임을 성실히 이행할 수 있다면 그만이다.
2. 역할은 대체 가능성을 의미한다.
손님 입장에서 캐시어는 **대체 가능(Subsittutable)**하다. 만약 두 명이 캐시어의 역할을 수행할 수 있다면, 손님 입장에서는 둘 중 어느누가 역할을 수행하더라도 문제가 되지않는다.
3. 책임을 수행하는 방법은 자율적으로 선택할 수 있다.
요청을 받은 사람들은 요청을 처리하는 방법을 자유롭게 선택할 수 있다. 즉, 바리스타가 카페라떼의 주문이 들어온 경우 어떠한 바리스타는 라떼아트를 할 수 있을 것이며, 어떤 바리스타는 풍미를 돋우기 위해 노력할지 모른다.
즉, 바리스타의 역할을 수행하는 사람들마다 서로 다른 방식으로 요청을 처리한다는 것이다.
그러나 그 결과 나오는 “카페라떼”는 변하지 않는다.
이처럼 동일한 **요청에 대해 서로 다른 방식으로 응답할 수 있는 능력을 다형성(Polymorphism)**이라 한다.
4. 한 사람이 동시에 여러 역할을 수행할 수 있다.
처음 예시를 들 때 바리스타가 캐시어의 역할을 수행할 수 있을 수 있으며, 반대도 가능하다하였다.
우리 주변의 카페도 그런 경우가 많다. 위의 예시는 캐시어와 바리스타라는 개별적인 역할을 이용해 협력관계를 묘사했지만, 한 사람이 캐시어와 바리스타의 역할을 동시에 수행하는 것도 가능하다.
즉, 한 사람이 동시에 둘 이상의 역할을 수행하는 것이 가능하다.
이는 다형성의 개념으로도 볼 수 있는데 학교에 등교할 때는 학생이라는 역할을 수행하며, 집에 돌아와서는 부모님의 막내아들이라는 역할을 수행하는 나와 같다고 볼 수 있다.
STEP 1.2 중간 정리
출근길 카페 예시를 통해서 알게 된 내용은 다음과 같다.
협력(collaboration) : 문제를 해결할 수 있는 다른 사람에게 요청과 응답을 통해 문제를 해결하는 것
역할(Rule) : 어떤 협력에 참여하는 특정한 사람이 협력 안에서 차지하는 책임이나 임무
책임(Responsiblilty) : 협력하는 과정에서 문제를 해결하기 위해 자신에 임무를 성실히 수행하는 것
또한, 역할은 의미적으로 책임이라는 개념을 내포한다하였다.
그리고 역할과 책임은 다음과 같은 특성을 갖는다.
- 여러 사람이 동일한 역할을 수행할 수 있다.
- 역할은 대체 가능성을 의미한다.
- 책임을 수행하는 방법은 자율적으로 선택할 수 있다.
- 한 사람이 동시에 여러 역할을 수행할 수 있다.
그렇다면 출근길 카페 예시를 객체지향 세계로 옮기면 어떻게 될까?
- 손님, 캐시어, 바리스타 → 객체(Object)
- 손님이 캐시어에게 주문을 요청, 캐시어가 바리스타에게 커피 제조를 요청 → 메시지(Message)
- 캐시어가 주문 요청을 처리하는 방법, 바리스타가 제조 요청을 처리하는 방법 → 메서드(Method)
위와 같이 실세계의 예를 들어 객체지향 세계가 어떻게 이뤄지는지 철학적인 개념을 알게 되었다.
이제 좀 더 실용적인 관점에서 이를 보고자 한다.
STEP 2. 협력 속에 사는 객체
“어떤 객체도 섬이 아니다.” - Ward Cunningham, Kent Beck (1989)
내가 가장 인상이 깊었던 말이었다. 객체지향의 본질을 밑에서 또 정리하겠지만, 여기까지 읽었을 때 객체지향이 무엇인가에 대해서 감이 오는가?
나는 이렇게 생각한다.
“복잡하고 거대한 문제를 해결하기 위해서 역할과 책임을 성실히 수행하며 자율적으로 협력하는 객체들을 만들어 내는 것”
사람들이 어떠한 문제를 해결하기 위해서 협력하듯이 객체들은 애플리케이션의 기능을 구현하기 위해서 협력한다.
객체지향 세계에서 협력에 참여하는 주체는 **객체(Object)**이다. 실세계에서 인간이라는 것이 없으면 역할, 책임, 협력은 아무런 의미가 없는 것 처럼 객체지향도 마찬가지이다.
따라서, 객체는 다음 두 가지를 갖춰야한다.
- 객체는 충분히 ‘협력적’이어야 한다.
- 객체는 충분히 ‘자율적’이어야 한다.
- 객체는 충분히 ‘협력적’이어야 한다.
“어떤 객체도 섬이 아니다”라는 말처럼 객체지향에서 꼭 잊으면 안되는 것이 협력이다. 객체지향 세계에서 객체는 다른 객체의 요청에 충실히 귀를 기울이고, 다른 객체에게 적극적으로 도움을 요청해야한다는 것이다.
혼자서 모든 것을 처리하는 전지전능한 객체는 내부적인 복잡도에 의해 스스로 자멸한다.
→ 이는 SOILD 원칙 중 **단일 책임 원칙(Single Responsibility Principle)**과 관련이 있다고 볼 수 있다.
여기서 협력적이라는 말은 다른 객체의 명령에 수동적으로 움직이는 객체들을 말하는 것이 아니다.
객체는 요청이 들어온 객체의 명령에 복종하는 것이 아니라 자율적으로 처리한다. 단순하게 말하면 요청에 응답을 주는 것일 뿐 내부적으로 어떠한 방식으로 응답을 생성 했는지는 외부 객체가 관여하지 않는다.
→ 이는 객체지향의 특성 중에 하나인 **캡슐화(Encapsulation)**과 관련이 있다.
- 객체는 충분히 ‘자율적’이어야 한다.
잠깐 설명했던 것 처럼 요청을 한 객체는 응답을 주는 객체에게 내부적으로 어떻게 응답을 생성하라 간섭을 하지 않는다. 단순하게 요청을 하고 해당 응답을 기다릴 뿐이다.
잠깐 다시 출근길 카페로 돌아가보자.
우리가 만약 캐시어라면 손님이 주문하면 행동을 시작하지만 손님이 주문하는 절차나 바리스타에게 접수한 것을 전달하는 방법은 스스로 결정한다.
즉, 캐시어는 요청에 대해 스스로 판단하고 행동하는 자율적 존재이다.
객체지향 세계에서도 마찬가지이다. 객체는 협력에 참여하지만 스스로의 결정과 판단에 따라 행동하는 자율적인 존재이다. 그렇다면 어떻게 충분히 협력적이고, 자율적인 객체를 만들 수 있을까?
STEP 2.1 상태와 행동을 함께 지닌 자율적인 객체
이 장에서는 어떻게 충분히 협력적이고, 자율적인 객체를 만들 수 있을까?에 대한 해답을 내놓으려고 한다.
힌트는 사실 위에서도 설명했지만, **캡슐화(Encapsulation)**랑 관련이 깊다.
“객체는 **상태(state)와 행위(behavior)**를 갖는다”라는 말을 많이 들어 봤을 것이다. 객체가 협력에 참여하기 위해서 어떤 행동을 해야 한다면 그 행동을 하는 데 필요한 상태도 함께 지니고 있어야 한다는 것을 의미한다.
객체의 자율성은 객체의 내부와 외부를 명확하게 구분하는 것으로부터 나온다. 즉, 무엇(What)을 수행하는지 알 수 있지만 어떻게(How) 수행하는지에 대해서 알 수 없다.
그렇기에 객체의 자율성은 캡슐화와 관련이 깊다는 것이다.
STEP 2.2 협력과 메시지
인간 세계와 달리 객체지향 세계에서는 한 가지 의사소통 수단만이 존재한다. 바로 그것이 메시지이다.
객체는 협력을 위해 다른 객체에게 메시지를 전송하고 다른 객체로 부터 메시지를 수신한다.
객체지향 세계에서의 협력은 메시지를 전송하는 객체(Sender)와 수신하는 객체(Receiver) 사이에서 이뤄진다.
STEP 2.3 메서드와 자율성
어떤 객체가 협력을 위해 메세지를 수신하면 자신이 처리할 수 있는지 판단한 뒤 미리 정해진 자신만의 방법으로 메세지를 처리한다. 이 처리하는 방법을 메서드라고 부른다.
그렇다면 메서드와 자율성은 무슨 연관성이 있을까?
객체는 메시지를 수신하면 이를 수신할 수 있는지 판단하는데 이때, 판단할 수 있으면 위에서 얘기한 바와 같이 어떻게 처리하는 부분이 바로 메서드일 것이다.
예를 들면 동일한 커피 제조 요청에도 바리스타는 커피머신으로 커피를 내릴 수도 있으며, 어떤 경우에는 핸드 드립으로 커피를 내릴 수도 있을 것이다.
객체지향 세계에서는 협력에 참여하는 객체들 간의 메세지와 메서드의 분리를 통하여 자율성을 증진시킨다.
좀 더 깊게 말하면, 외부의 요청이 무엇인지를 표현하는 메시지와 요청을 처리하기 위한 구체적인 방법인 메서드를 분리하는 것이 객체의 자율성을 높인다. 이것 또한 캡슐화와 아주 깊은 연관 관계를 갖는다.
STEP 3. 객체지향의 본질
이번 포스팅에서 설명한 내용을 종합하여 객체지향의 본질을 정리하면 다음과 같다고 볼 수 있다.
-
객체지향이란 시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법이다.
-
자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.
-
객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다.
→ 각 객체는 협력 내에서 정해진 역할을 수행하며, 역할은 관련된 책임의 집합이다.
-
객체는 다른 객체와 협력하기 위해 메시지를 전송하며, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다.
STEP 3. 객체를 지향하라
항상 우리는 객체지향 프로그래밍 혹은 객체지향 설계를 이야기할 때 항상 중점으로 바라봤던 것은 객체가 아니라 클래스였다.
돌이켜 생각해보자, 학부시절 객체지향 설계를 보면 클래스 다이어그램이 중요하다 배웠었고, 객체지향 프로그래밍에서는 첫 장부터 객체와 클래스란 무엇인가?로 시작하지 않았나라고 말이다.
잘 생각해보자 자바스크립트와 같은 프로토타입(prototype) 기반 언어들은 클래스라는 개념이 없음에도 (ES6 이전을 생각하자) 객체지향 언어라고 불리었다.
우리가 배워야할 것은 클래스 지향 프로그래밍과 설계가 아니다. 객체지향 프로그래밍과 설계이다.
이 책의 저자 조용호님께서는 클래스를 강조하는 프로그래밍 언어적인 관점은 다음과 같은 문제가 있다고 한다.
- 객체의 캡슐화를 저해한다.
- 클래스를 서로 강하게 결합시킨다.
- 협력하는 객체들의 공동체가 아닌 클래스로 구성된 설계도의 관점은 유연하고 확장가능한 애플리케이션 구축을 방해한다.
우리는 이제 객체를 지향해야 한다.
클래스의 관점에서 메시지를 주고받는 객체의 관점으로 사고의 중심을 전환해야 된다는 것을 잊지 말아야 한다.
중요한 것은 어떤 클래스가 필요한가가 아니라 어떤 객체들이 어떤 메세지를 주고받으며 협력하는가이다.