✏️, 💡,❓ 해당 이모지는 저의 생각임을 나타냅니다.
객체지향 패러다임 관점에서 핵심은 역할(role), 책임(responsbility), 협력(collaboration)이다.
클래스와 상속은 객체들의 책임과 협력이 어느 정도 자리를 잡은 후에 사용하라 수 있는 구현 메커니즘일 뿐이다.
01 협력
객체들이 애플리케이션의 기능을 구현하기 위해 수행하는 상호작용을 협력이라고 한다.
객체가 협력에 참여하기 위해 수행하는 로직은 책임이라고 부른다.
객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성한다.
협력이 설계를 위한 문맥을 결정한다
메시지 전송은 객체 사이의 협력을 위해 사용할 수 있는 유일한 커뮤니케이션 수단이다. 메시지를 수신한 객체는 메서드를 실행해 요청에 응답한다.
객체란 상태와 행동을 함께 캡슐화하는 실행 단위다. 그렇다면 객체가 가질 수 있는 상태와 행동을 어떤 기준으로 결정해야 할까?
어떤 객체도 섬이 아니다. 애플리케이션에 어떤 객체가 필요하다면 그 객체가 어떤 협력에 참여하고 있기 때문이다. 그리고 객체가 협력에 참여할 수 있는 이유는 협력에 필요한 적절한 행동을 보유하고 있기 때문이다.
협력 => 객체가 필요한 이유와 객체가 수행하는 행동의 동기를 제공한다.
Movie라는 객체를 보았을 때 대부분의 사람들은 play 행동을 수행할 것이라 생각할 것이다. 그러나 요금을 계산하는 행동과 관련된 메서드가 대부분이다. 이것은 Movie가 영화를 예매하기 위한 협력에 참여하고 있고 그 안에서 요금을 계산하는 책임을 지고 있기 때문이다. 협력이라는 문맥을 고려하지 않고 Movie의 행동을 결정하는 것은 아무런 의미가 없다.
💡 객체를 볼 때 객체를 보고 -> 이런 행동을 수행할 것이다라는 게 예상되어야 한다고 생각했다. 그런데 그것보다 더 중요한 건 협력이라고 말하는 것 같다. 객체를 볼 때 그냥 객체만 보는 게 아니라, '협력에서의 객체'를 봐야 한다.
❓ 근데 그러면... 객체가 협력에 참여할 수 있는 이유가 적절한 행동을 보유하고 있기 때문이 아니고, 협력 -> 행동 -> 객체 순으로 찾게 되는 거 아닌가?! 설계를 할 때 (1) 어떤 협력이 있을지 생각하고 (2) 어떤 행동들이 있을지 생각하고 (3)그에 따른 객체들을 만들어내야 순서가 맞는 거 아닌가...?
💡 위 순서가 맞는 것 같다. 책임 주도 설계의 방식이 협력 -> 행동(책임) -> 객체 순으로 이뤄진다.
객체의 행동을 결정하는 것이 협력이라면 객체의 상태를 결정하는 것은 행동이다.
상태는 객체가 행동을 수행하는 데 필요한 정보가 무엇인지로 결정된다.
02 책임
객체를 설계하기 위해 필요한 문맥인 협력이 갖춰졌다고 하자. 다음으로는 협력에 필요한 행동을 수행할 수 있는 객체를 찾는 것이다.
책임이란 객체가 유지해야 하는 정보와 수행할 수 있는 행동에 대해 개략적으로 서술한 문장이다.
1) 객체가 무엇을 알고 있는가 (doing)
- 객체를 생성하거나 계산을 수행하는 등의 스스로 하는 것
- 다른 객체의 행동을 시작하는 것
- 다른 객체의 활동을 제어하고 조절하는 것
2) 객체가 무엇을 할 수 있는가 (knowing)
- 사적인 정보에 관해 아는 것
- 관련된 객체에 관해 아는 것
- 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것
일반적으로 책임과 메시지의 크기는 다르다. 처음에는 단순한 책임이라고 생각했던 것이 여러 개의 메시지로 분할되기도 하고 하나의 객체가 수행할 수 있다고 생각한 책임이 커다란 책임이 되는 것이 일반적이다.
💡 중요한 포인트인 것 같다. 책임 = 메시지라고 생각해선 안된다.
협력이 중요한 이유는 객체에게 할당할 책임을 결정할 수 있는 문맥을 제공하기 때문이다. 적절한 협력이 적절한 책임을 제공하고, 적절한 책임을 적절한 객체에게 할당해야 한다.
❓ 위에서도 그랬지만 자꾸 헷갈리는 점이 '적절한 객체'가 이미 있다고 생각하고 설명하기 때문인 것 같다. 객체에게 할당할 책임 <- 이라는 말이 객체는 이미 정해져있고, 맞는 책임을 할당한다는 말로 들린다. 그런데 나는 현재 책임에 따라 어떤 객체가 와야할지 결정된다고 이해중이라 혼란스러운 것 같다.
💡 !...! 나는 대체 객체를 무엇이라고 생각한 것인가. 아래 책임 할당 챕터를 읽고 깨달았다. 객체는 그냥 존재한다. 우리 주변에 있는 게 객체이다. 그런데 나는... 바보같게도, 위 의문을 가질 때의 나는 객체를 '클래스' 등으로 생각했던 것 같다.
책임 할당
책임을 수행하는 데 필요한 정보를 가장 잘 알고 있는 전문가에게 책임을 할당하는 것을 정보 전문가 패턴(INFORMATION EXPERT)이라고 부른다.
정보 전문가 패턴으로 책임 할당 방법
영화 예매 기능
1) '예매하라'는 메시지로 협력 시작
2) 메시지 처리할 적절 객체 선택 - Screening
영화를 예매하기 위해선 상영 시간과 기본 요금을 알아야 한다. 이 정보를 소유하고 있는 전문가는 누구인가? -> Screening
3) 예매를 위해선 예매 가격을 계산해야 함 - 새로운 메시지 '가격을 계산하라'
Screening은 예매 가격 계산에 필요한 정보를 모른다. 새로운 메시지가 필요하다.
4) 가격 계산 정보 전문가 선택 - Movie
가격과 할인 정책이 필요하다. 이 모든 정보를 알고 있는 정보 전문가는 Movie다.
...
어떤 경우에는 응집도와 결합도의 관점에서 정보 전문가가 아닌 다른 객체에게 책임을 할당하는 것이 적절한 경우도 있다. 하지만 기본적 전략은 정보 전문가를 찾는 것이며, 정보 전문가에 책임을 할당하는 것만으로도 자율적 객체를 만들 가능성이 높아진다.
책임 주도 설계
이처럼 책임을 찾고 책임을 수행할 적절한 객체를 찾아 할당하는 방식으로 협력을 설계하는 방법을 책임 주도 설계(RDD)라고 부른다.
다음은 책임 주도 설계 방법의 과정이다.
- 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
- 시스템 책임을 더 작은 책임으로 분할한다.
- 분할된 책임은 더 작은 책임으로 분할한다.
- 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
- 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.
협력은 문맥을 제공한다. 협력이 책임을 이끌어내고, 책임이 협력에 참여할 객체를 결정한다.
메시지가 객체를 결정하고, 행동이 상태를 결정한다는 게 책임을 할당할 때 고려해야 하는 주요 요소이다.
✏️ 행동이 상태를 결정한다 = 행동을 수행하기 위해 필요한 정보만 상태로 가진다.
메시지가 객체를 결정한다
객체가 메시지를 선택하는 것이 아니라 메시지가 객체를 선택하게 하는 게 중요하다.
1) 객체가 최소한의 인터페이스를 가질 수 있게 된다.
2) 객체는 충분히 추상적인 인터페이스를 가질 수 있게 된다. 인터페이스는 무엇(what)을 하는지는 표현해야 하지만 어떻게(how) 수행하는지를 노출해서는 안된다.
영화 예매 시스템의 경우 '예매하라' 메시지를 선택하고 그 메시지를 수신할 객체를 선택했다는 사실을 기억하라.
행동이 상태를 결정한다
객체를 객체답게 만드는 것은 객체의 상태가 아니라 행동이다. (객체가 존재하는 이유는 협력에 참여하기 위해서다.)
객체지향 입문자가 쉽게 빠지는 실수는 객체의 행동이 아니라 상태에 초점을 맞추는 것이다.
❓ 그런데 위에 정보 전문가 패턴 책임 할당 방법에서는 객체가 어떤 상태를 가지고 있는지 생각하고 객체를 선택하잖아.... 그건 상태에 초점을 맞춰서... 책임을 할당하는 거 아닌가?
객체에 필요한 상태를 결정하고, 그 후에 상태에 필요한 행동을 결정한다. 이는 내부 구현이 인터페이스에 노출되도록 하기 때문에 캡슐화를 저해한다. (데이터 주도 설계)
중요한 것은 객체의 상태가 아니라 행동이다. 상태는 행동을 결정하고 비로소 결정할 수 있다. 협력이 객체의 행동을 결정하고 행동이 상태를 결정한다. 그 행동이 바로 객체의 책임이 된다.
❓ 오 대박.... 완전 헷갈린다.
❓⭐️ 객체를 설계할 때, 객체에 필요한 행동을 먼저 결정하고 상태를 결정해야 하는 이유는 알겠다. 그런데 협력이랑 엮인 순간부터 전후관계를 모르겠다. 이런 협력이 필요하다 -> 이런 책임이 필요하다 -> 메시지 도출 -> (상태-알고 있는정보를 기준으로) 메시지에 해당하는 객체 찾기 -> 객체에 메시지에 해당하는 행동 넣기 식으로 이해하고 있는데... 그게 아닌 것 같다. 객체 설계는 협력 전에 진행되어야 하는건가?
💡 GPT 답변:
정보 전문가 패턴도 '행동 중심'이다. 이 책임을 수행하기 위해 필요한 정보를 가장 많이 알고 있는 객체에게 책임을 할당하라. -> 상태가 아니라 행동이 출발점.
객체를 설계하는 타이밍은 협력 후에 설계해야 한다. 협력 전 객체가 설계되어 있으면 그 객체에 협력이 종속된다.
❓ 메시지에 해당하는 객체를 찾을 때 객체는 설계가 안되어있는 상태. 그런데 '가장 많은 정보를 알고있다.'라는 것은 어떻게 아는가?
💡 GPT 답변:
협력 시나리오를 만든다 -> 책임(행동)을 도출한다 -> 이 행동을 수행하기 위한 정보를 파악한다 ->이 정보들을 누가 알고있을 법한지 문맥에서 유추한다
이건 이미 만들어진 객체 중에서 정보를 많이 아는 객체를 고르는 게 아니고, 협력 시나리오에 따라 디자이너가 판단하는 것이다.
💡 이렇게 정리해보니 확실히 이해가 되었다.
03 역할
객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합을 역할이라 부른다. 실제로 협력을 모델링 할 때는 특정한 객체가 아니라 역할에게 책임을 할당한다고 생각하는 게 좋다.
예를 들어 '예매하라'라는 메시지를 처리하는 객체로 Screening을 선택했다. 하나의 단계처럼 보이지만 영화를 예매할 수 있는 적절한 역할이 무엇인가를찾고, 역할을 수행할 객체로 Screening 인스턴스를 선택하는 과정이 있었다. 역할에 특별한 이름을 부여하지는 않았지만 실제로는 익명의 역할을 찾고, 그 역할을 수행할 수 있는 객체를 선택하는 방식으로 설계가 진행되었다고 생각한 것이 자연스럽다.
유연하고 재사용 가능한 협력
역할이 중요한 이유는 역할을 통해 유연하고 재사용 가능한 협력을 얻을 수 있기 때문이다.
예를 들어 '할인 요금을 계산하라'는 행위를 수행하는 객체를 찾는데, 할인 요금 계산 방법이 2개이다. 그럴 때는 두 종류의 객체가 참여하는 협력을 개별적으로 만들어야 할까?
문제를 해결하기 위해선 객체가 아닌 책임에 초점을 맞춰야 한다. 순수하게 책임의 관점에서 바라보면 a할인요금 계산도, b할인요금 계산도 모두 '할인 요금 계산'이라는 동일한 책임을 수행한다.
따라서 객체라는 존재를 지우고 '할인 요금을 계산하라'는 메시지에 응답할 수 있는 대표자를 생각한다면 두 협력을 하나로 통합할 수 있을 것이다.

여기서 역할이 두 종류의 규체적인객체를 포괄하는 추상화라는 점에 주목하라. 역할에 추상적인 이름을 부여할 수 있다. 예를 들어 DiscountPolicy가 될 수 있다.
요즘은 동일한책임을 수행하는 역할을 기반으로 두 개의 협력을 하나로 통합할 수 있다는 것이다.
협력이 더 유연해지고, 새로운 할인 정책 추가하기 위해 새로운 협력을 추가할 필요가 없어졌다. -> 책임과 역할을 중심으로 협력을 바라보는 것이 변경과 확장이 용이한 유연한 설계로 나아가는 첫걸음이다.
역할의 구현
역할을 구현하는 가장 일반적인 방법은 추상 클래스와 인터페이스를 사용하는 것이다.
객체 대 역할
그러나 오직한 종류의 객체만 협력에 참여하는 상황에서 역할이라는 개념을 고려하는 것이 유용할까?
객체에 관해 생각할 때 '이 객체가 무슨 역할을 수행해야 하는가?'라고 자문하면 도움이 된다.
객체와 역할의 진짜 차이는 무엇일까?
만약 동일한 종류의 객체가 하나의 역할을 항상 수행한다면 둘은 동일한 것이다. 하지만 하나 이상이ㅡ 객체가 동일한 책임을 수행한다면 역할은 서로 다른 방법으로 실행할 수 있는 책임의 집합이 된다.
협력에 적합한 책임을 수행하는 대상이 한 종류라면 간단하게 객체로 간주한다. 만약 여러 종류의 객체들이 참여할 수 있다면 역할이라고 부르면 된다.
협력은 역할들의 상호작용으로 구성되고, 협력을 구성하기 위해 역할에 적합한 객체가 선택되며, 객체는 클래스를 이용해 구현되고 생성된다.
개인적으로는 설계 초반에는 책임과 협력의 큰 그림을 탐색하는 것이 중요하고 역할과 객체를 명확히 구분하는 건 중요하지 않다는 것이다. 필요한 순간에 객체로부터 역할을 분리해내는 것이 가장 좋은 방법이다.
다양한 객체들이 협력에 참여한다는 것이 확실하다면 역할로 시작하라. 결정을 내리기 어렵다면 객체로 시작하라.
역할과 추상화
추상화의 첫 번째 장점은 세부 사항에 억눌리지 않고도 상위 수준의 정책을 쉽고 간단하게 표현할 수 있다는 것이다.
협력이라는 관점에서는 세부적인 사항을 무시하고 추상화에 집중하는 것이 유용하다. 협력에 참여하는 할인 정책과 할인 조건의 종류는 중요하지 않다.
객체에게 중요한 것은 행동이다. 역할이 중요한 이유는동일한 협력을 수행하는 객체들을 추상화할 수 있기 때문이다.
추상화의 두 번째 장점은 설계가 유연해진다는 것이다. 역할은 다양한 환경에서 다양한 객체들을 수용할 수 있게 해준다.
배우와 배역
배우는 연극이 상영되는 짧은 시간에만 배역의 가면을 쓴다.
- 배역은 연극 배우가 특정 연극에서연기하는 역할이다.
- 배역은 연극이 상영되는 동안에만 존재하는 일시적인 개념이다.
- 연극이 끝나면 연극 배우는 배역이라는 역할을 벗어 버리고 원래의 연극 배우로 돌아온다.
- 서로 다른 배우들이 동일한 배역을 연기할 수 있다.
- 하나의 배우가 다양한 연극 안에서 서로 다른 배역을 연기할 수 있다.
연극 안에서 배역을 연기하는 배우라는 은유는 협력 안에서 역할을 수행하는 객체의 관점을 훌륭하게 담아낸다.
객체는 협력이라는 실행 문맥 안에서 특정한 역할을 수행한다. 객체는 협력이 끝나고 협력에서의 역할을 잊고 원래의 객체로 돌아올 수 있다.
일반적으로 역할은 객체가 협력에 참여하는 잠시 동안만 존재하는 일시적 개념이다. 역할은 객체의 페르소나다.
객체는 여러 협력에 참여하며 다양한 역할을 수행할 수 있다. 그러나 특정한 협력 안에서는 일시적으로 오직 하나의 역할만이 보여진다는 점에 주의하라.
=> 객체는 다양한 역할을 가지지만, 협력 안에서 하나의 역할로 보여진다. 다른 협력에 참여할 때는 다른 역할로 보여진다. 협력의 관점에서 동일한 역할을 수행하는 객체는 대체 가능하다.
마무리하며
객체는 서로 분리된 인스턴스가 아닌 협력하는 파트너라는 점을 강조하며 말했던 챕터인 것 같다.
초반에 '정보 전문가 패턴'에서 책임... 상태... 객체 등의 순서가 헷갈리면서 물음표를 많이 낳았지만 ㅋㅋㅋ 해결 완료...!
곧 새 프로젝트가 들어가는데 해당 방식을 기억하며 설계에 적용해봐야겠다. 같이 스터디하는 분께 서로 설계를 해보고 공유하는 시간을 가지자고 말해도 좋을 것 같다.
'Book' 카테고리의 다른 글
[오브젝트] 챕터 05: 책임 할당하기 (0) | 2025.05.21 |
---|---|
[오브젝트] 챕터 04: 설계 품질과 트레이드오프 (0) | 2025.05.04 |
[오브젝트] 챕터 02: 객체지향 프로그래밍 (0) | 2025.04.22 |
[오브젝트] 챕터 01: 객체, 설계 (0) | 2025.04.20 |
오브젝트, 코드로 이해하는 객체지향 설계: 들어가며 (0) | 2025.04.09 |