본문 바로가기
SW core/객체지향

객체지향의 사실과 오해 - 협력하는 객체들

by ocwokocw 2021. 8. 8.

- 이 글은 조영호의 객체지향의 사실과 오해를 기반으로 작성되었습니다. (가능하면 꼭 읽어보는것을 추천드립니다.)

- God Object: https://en.wikipedia.org/wiki/God_object

- 개요

개발자나 설계자는 실세계의 사물이나 상황을 소프트웨어로 구현하고 사물의 속성과 행동을 클래스의 속성과 메소드로 구현하는것이 "객체지향적"이라고 생각하지만 실상은 소프트웨어와 실세계 사물간의 거리가 먼 것이 일반적이다.

 

그렇다면 컴퓨터공학을 전공하면서 지겹도록 듣던 붕어빵틀과 붕어빵은 도대체 뭘까? 엄청나게 똑똑해서 박사과정을 수료 하고 전공서적을 쓴 사람들은 헛소리를 한 것일까? 그것은 실세계의 모방이라는 관점으로 설명하는것이 객체 지향의 첫 발을 들여놓는 입문자들에게 객체 지향의 개념을 이해시키기 수월하기 때문일 것이다.


- 협력

아침 9 시와 오후 3시가 되면 커피를 마시는게 회사원의 국룰이다. 손님은 캐시어에게 커피를 주문하면 캐시어는 바리스타에게 만들어 달라고 요청한다. 바리스타가 커피를 다 만들면 캐시어는 손님에게 커피가 나왔다고 알려준다.

 

손님 역할을 맡은 사람은 커피를 주문할 책임이 있다. 캐시어 역할을 수행하는 사람은 주문을 받고 커피가 나오면 손님에게 알려주며 바리스타에게 어떤 커피를 제조해야하는지 알려줄 책임이 있다. 바리스타 역할은 커피를 제조하여 캐시어에게 건네주어야 한다. 그리고 커피 1 잔을 주문하는데 손님, 캐시어, 바리스타는 이런 방식으로 협력한다.


- 역할, 협력, 책임

위의 다이어그램은 커피 주문과정을 Collaboration Diagram (Role) 로 그린것이다. (Tool 은 무료인 StarUML 5.0). UML 문법적인 관점에서 오류가 있을 수 있지만 UML 의 문법을 실용적인 측면보다 너무 엄격하게 적용하면 사용 목적의 주객이 전도될 가능성이 있다. 또한 위의 다이어그램은 직관적으로 알아보는데에 전혀 무리가 없다.

 

Collaboration Diagram 은 말 그대로 협력을 나타낸것이다. 손님, 캐시어, 바리스타의 역할들이 커피 주문이라는 협력을 하는데 서로 요청을 하면 그의 반대되는 방향으로 응답이 발생하는것을 알 수 있다.

 

역할 이라는 단어자체는 책임을 수반한다. 만약 이 글을 보는 당신이 회사에서 개발자라는 역할을 맡고 있다면 내일 아침 출근해서 서버 혹은 클라이언트쪽을 구현해야할 책임이 있다는 말이 된다.

 

역할에는 몇 가지 특징이 있다. 역할을 꼭 1 명의 사람이 수행하진 않는다. 작은 규모의 매장이라면 1 명의 직원이 캐시어와 바리스타 역할을 동시에 수행할 수 있다. 또한 철수가 어제 캐시어를 그만두었다면 영희를 알바생으로 채용해서 캐시어를 시킬 수 있다. 즉 대체도 가능하다.

 

위의 커피주문과정에서 사람을 객체로, 사람간의 오가는 요청을 메시지로 해당 요청에 대해 처리하는 방법(ex - 바리스타가 커피를 제조하는 법)을 메소드로 치환하면 대부분을 객체지향적인 측면에서 설명할 수 있다. 하나의 시스템은 더 작은 역할과 책임을 수행하는 객체들로 분할된다. 그리고 이런 객체들이 요청과 응답을 주고 받으면서 협력한다.


- 객체와 협력

협력안에서 객체는 두 가지 중요한 자질을 갖추어야 한다.

 

우선 협력적이어야 한다. 객체는 다른 객체에게 요청을 하거나 다른 객체가 한 요청에 대해 충실히 응답해야 한다. 다른 객체와 협력하지 않고 혼자서 모든것을 처리하는 객체를 "god object"(https://en.wikipedia.org/wiki/God_object) 라고 한다. god object 가 되면 복잡도가 너무 커져서 초기에는 해당 객체의 행동을 모두 기억할 수 있지만 다른사람이 코드를 보거나 혹은 시간이 지나서 변경사항이 생기면 건드릴 수가 없게 된다. 이런 방식으로 코딩하면 메소드 혹은 클래스가 비대해지는 현상으로 나타난다.

 

또한 자율적이어야 한다. 메시지를 수신받은 객체는 일을 자율적으로 처리한다. 바리스타가 캐시어로부터 커피를 제조하라는 메시지를 수신받을 때 "어떻게"에 관한 정보는 수신받지 않는다. 오직 "무엇을"에 관한 정보만 수신받는다. 객체는 상태와 행동을 지니고 있다. 바리스타가 커피를 어떻게 제조하는지 알고 있는 레시피들을 상태라고 표현한다면 커피를 제조하는것은 행동이라고 볼 수 있다. 특별한 요구사항이 없다고 한다면 바리스타는 자신의 레시피를 외부에 공개할 필요는 없다. 즉 외부 객체와 협력시에 필요한 사항 외에 내부사항을 굳이 공개적으로 선언할 필요가 없다는 얘기다. 접근제어자와 연관지어 생각해보면 그 뜻을 알 수 있을것이다.

 

객체는 다른 객체와 협력하기 위해 메시지를 전송하고 수신한다. 바리스타는 커피를 제조하라는 메시지를 받아서 커피를 만들 때 손으로 만들지 커피 머신을 이용할지 구애받지 않는다. 위의 문장에서 커피를 제조하라는 것은 메시지이며 커피를 만드는 방법이 메소드가 된다. 즉 메소드라는것은 객체가 메시지를 수신받을 때 이를 처리하는 방법이라고 볼 수 있다.


- 객체지향의 중심

만약 팀원이 찾아와서 UML 다이어그램좀 볼까요? 라고 물어본다면 백이면 백 모두 클래스 다이어그램을 보여줄것이다. 객체지향에서의 핵심이 무엇이냐 라고 한다면 모두 클래스라고 답할 것이다.

 

우리가 프로그램을 구현하는 과정을 생각해보자. 클래스를 만들고 DB 의 컬럼을 속성으로 만들고 시스템에서 제공해야 할 기능을 메소드로 만든다. 이렇게 우리는 보통 클래스를 중심으로 놓고 설계한다.

 

하지만 객체지향에서 중요한것은 협력에서 객체들이 어떻게 메시지를 주고 받는지를 생각해보는것이다. 이 과정에서 다수의 객체가 동일한 패턴으로 메시지를 주고 받는다면 이를 하나의 역할과 책임으로 도출해볼 수 있을것이다.

 

객체 지향에서 클래스 다이어그램은 당연히 중요하다. 하지만 우선적으로 중요시 되어야 할 사항은 협력안에서 객체들의 어떻게 메시지를 주고 받는지가 되어야 할 것이다.

댓글