devseop08 님의 블로그

[객체지향의 사실과 오해] 6장. 객체 지도 본문

Architecture/객체지향설계

[객체지향의 사실과 오해] 6장. 객체 지도

devseop08 2025. 5. 30. 21:16

"유일하게 변하지 않는 것은 모든 것이 변한다는 사실 뿐이다."

기능을 중심으로 구조를 종속시키는 접근법 = 범용적이지 않고 재사용 불가하고 변경에 취약한 모델을 만든다.

구조를 중심으로 기능을 종속시키는 접근법 = 범용적이고 재사용 가능하고 변경에 유연하게 대처 가능한 모델을 만든다.

객체지향은 자주 변경되는 기능이 아니라 안정적인 구조를 기반으로 시스템을 구조화한다.

기능이 아니라 안정적인 구조를 기반으로 시스템을 분할하는 객체지향적인 접근법은 역할, 책임, 협력을 기반으로 시스템의 기능을 구현하는 책임-주도 설계의 본질을 이해하는 데도 도움이 될 것이다.

기능 설계 대 구조 설계

  • 모든 소프트웨어 제품의 설계에는 두 가지 측면이 존재한다.
  • 하나는 기능 측면의 설계이고, 다른 하나는 구조 측면의 설계다.
  • 설계의 가장 큰 도전은 기능과 구조라는 두 가지 측면을 함께 녹여 조화를 이루도록 만드는 것이다.
  • 훌륭한 기능이 훌륭한 소프트웨어를 만드는 충분 조건이라면, 훌륭한 구조는 훌륭한 소프트웨어를 만들기 위한 필요조건이다.
  • 좋은 설계는 나중에라도 변경할 수 있는 여지를 남겨놓는 설계다.
  • 변경에 대비하고 변경의 여지를 남겨 놓는 가장 좋은 방법은 자주 변경되는 기능이 아닌 안정적인 구조를 중심으로 설계하는 것이다.
  • 전통적인 기능 분해는 자주 변경되는 기능을 중심으로 설계한 후 구조가 기능에 따르게 한다.
  • 기능 분해 방법의 경우, 각 기능은 서로 밀접하게 관련된 하나의 덩어리를 이루기 때문에, 기능이 변경될 경우 기능의 축을 따라 설계된 소프트웨어가 전체적으로 요동치게 된다.
  • 객체지향 접근 방법은 자주 변경되지 않는 안정적인 객체 구조를 바탕으로 시스템 기능을 객체 간의 책임으로 분배하여 기능이 변경되더라도 객체 간의 구조는 그대로 유지된다.
  • 이것이 객체를 기반으로 책임과 역할을 식별하고 메시지를 기반으로 객체들의 협력 관계를 구축하는 이유다.

두 가지 재료: 기능과 구조

일반적으로 기능을 수집하고 표현하기 위한 기법을 유스케이스 모델링이라고 하고
구조를 수집하고 표현하기 위한 기법을 도메인 모델링이라고 한다.

안정적인 재료: 구조

도메인 모델

  • 도메인 모델이란 사용자가 프로그램을 사용하는 대상 영역에 관한 지식을 선택적으로 단순화하고 의식적으로 구조화한 형태이다.
  • 도메인 모델은 소프트웨어가 목적하는 영역 내의 개념과 개념 간의 관계, 다양한 규칙이나 제약 등을 주의 깊게 추상화한 것이다.
  • 도메인 모델은 소프트웨어 개발과 관련된 이해관계자들이 도메인에 대해 생각하는 관점이다.
  • 도메인 모델은 단순히 다이어그램이 아니다. 도메인 모델은 이해관계자들이 바라보는 멘탈 모델이다.
  • 멘탈 모델이란 사람들이 자신들이 상호작용하는 사물들에 대해 갖는 모형이다.
  • 멘탈 모델은 사용자 모델, 디자인 모델, 시스템 이미지 의 세 가지로 구분되며 설계자는 디자인 모델을 기반으로 만든 시스템 이미지가 사용자 모델을 정확하게 반영하도록 노력해야 한다.

도메인의 모습을 담을 수 있는 객체지향

  • 최종 코드는 사용자가 도메인을 바라보는 관점을 반영해야 한다. => 이것은 곧 애플리케이션이 도메인 모델을 기반으로 설계돼야 한다는 것을 의미한다.
  • 객체지향을 사용하면 사용자들이 이해하고 있는 도메인의 구조와 최대한 유사하게 코드를 구조화할 수 있다.
  • 객체지향의 이러한 특징을 연결완정성, 또는 표현적 차이라고 한다.

표현적 차이

  • 소프트웨어 객체는 현실 세계를 모방한 것이 아니라 은유를 기반으로 재창조한 것이다.
  • 핵심은 은유를 통해 현실 객체와 객체 사이의 차이를 최대한 줄이는 것이다.
  • 은유를 통해 투영해야 하는 대상은 바로 사용자가 도메인에 대해 생각하는 개념들이다.
  • 즉, 소프트웨어 객체를 창조하기 위해 은유해야 하는 대상은 바로 도메인 모델이다.
  • 소프트웨어 객체는 그 대상이 현실적인지, 비현실적인지에 상관없이 도메인 모델을 통해 표현되는 도메인 객체들을 은유해야한다.
  • 도메인 모델을 기반으로 설계하고 구현하는 것은 사용자가 도메인을 바라보는 관점을 그대로 코드에 반영할 수 있게 하고 결과적으로 표현적 차이는 줄어들 것이다.
  • 이것이 도메인 모델이 중요한 이유다.
  • 표현적 차이가 중요한 이유는 소프트웨어를 이해하고 수정하기 쉽게 만들어주기 때문이다.

불안정한 기능을 담는 안정적인 도메인 모델

  • 도메인 모델을 기반으로 코드를 작성하는 두 번재 이유는 도메인 모델이 제공하는 구조가 상대적으로 안정적이기 때문이다.
  • 도메인에 대한 사용자의 관점을 반영해야 하는 이유는 사용자들이 누구보다도 도메인의 본질적인 측면을 가장 잘 이해하고 있기 때문이다.
  • 사용자 모델에 포함된 개념과 규칙은 비교적 변경될 확률이 적기 때문에 사용자 모델을 기반으로 설계와 코드를 만들면 변경에 쉽게 대처할 수 있을 가능성이 커진다.

불안정한 재료: 기능

유스케이스

  • 사용자의 목표를 달성하기 위해 사용자와 시스템 간에 이뤄지는 상호작용의 흐름을 텍스트로 정리한 것을 유스케이스라고 한다.
  • 유스케이스의 가치는 사용자들의 목표를 중심으로 시스템의 기능적인 요구사항들을 이야기 형식으로 묶을 수 있다는 점이다.

유스케이스 특성

  • 유스케이스는 사용자와 시스템 간의 상호작용을 보여주는 텍스트다. 유스케이스는 다이어그램이 아니다.
  • 중요한 것은 유스케이스에 담겨있는 이야기다.
  • 유스케이스는 하나의 시나리오가 아니라 여러 시나리오들의 집합이다.
  • 유스케이스는 단순한 기능 목록과 다르다. 유스케이스의 강점은 유스케이스가 단순히 기능을 나열하는 것이 아니라 이야기를 통해 연관된 기능들을 함께 묶을 수 있다는 것이다.
  • 유스케이스는 사용자 인터페이스와 관련된 세부 정보를 포함하지 말아야 한다.
  • 유스케이스는 내부 설계와 관련된 정보를 포함하지 않는다.

유스케이스는 설계 기법도, 객체지향 기법도 아니다.

  • 유스케이스에는 단지 사용자가 시스템을 통해 무엇을 얻을 수 있고 어떻게 상호작용할 수 있느냐에 관한 정보만 기술된다.
  • 유스케이스는 객체의 구조나 책임에 대한 어떤 정보도 제공하지 않는다.
  • 유스케이스 안에는 영감을 불러일으킬 수 있는 약간의 힌트만 들어있을 뿐이다.

재료 합치기: 기능과 구조의 통합

도메인 모델, 유스케이스 , 그리고 책임-주도 설계

  • 불안정한 기능을 안정적인 구조 안에 담음으로써 변경에 대한 파급효과를 최소화하는 것은 훌륭한 객체지향 설계자가 갖춰야 할 기본적인 설계 능력이다.
  • 변경에 유연한 소프트웨어를 만들기 위해서는 유스케이스에 정리된 시스템의 기능을 도메인 모델을 기반으로 한 객체들의 책임으로 분배해야 한다.
  • 사용자 관점에서 시스템은 자신이 전송한 메시지에 응답하는 데 필요한 책임을 수행하는 일종의 객체다.
  • 협력의 출발을 장식하는 첫 번째 메시지는 시스템의 기능을 시스템의 책임으로 바꾼 후 얻어진 것이다.
  • 시스템에 할당된 커다란 책임은 이제 시스템 안의 작은 규모의 객체들이 수행해야 하는 더 작은 규모의 책임으로 세분화된다.
  • 유스케이스는 사용자에게 제공할 기능을 시스템의 책임으로 보게 함으로써 객체 간의 안정적인 구조에 책임을 분배할 수 있는 출발점을 제공한다.
  • 도메인 모델은 기능을 수용하기 위해 은유할 수 있는 안정적인 구조를 제공한다.
  • 책임-주도 설계 방법은 시스템의 기능을 역할과 책임을 수행하는 객체들의 협력 관계로 바라보게 함으로써 두 가지 기본 재료인 유스케이스와 도메인 모델을 통합한다.
  • 중요한 것은 객체지향 어플리케이션을 개발하기 위해서는 사용자의 관점에서 시스템의 기능을 명시하고, 사용자와 설계자가 공유하는 안정적인 구조, 즉 도메인 모델을 기반으로 기능을 책임으로 변환하는 체계적인 절차를 따라야 한다는 것이다.
  • 책임 할당의 기본 원칙은 책임을 수행하는 데 필요한 정보를 가진 객체에게 그 책임을 할당하는 것이다.
  • 이러한 책임 할당의 기본 원칙은 관련된 상태와 행동을 함께 캡슐화하는 자율적인 객체를 낳는다.전
  • 유스케이스에서 출발해 객체들의 협력으로 이어지는 일련의 흐름은 객체 안에 다른 객체를 포함하는 재귀적 합성이라는 객체지향의 기본 개념을 잘 보여준다.
  • 객체지향은 모든 것을 객체로 바라보는데, 큰 객체가 작은 객체로 나눠질 수 있다는 사실만 제외하면 객체들 사이에는 차이가 없다.
  • 크기와 상관없이 모든 객체는 메시지를 전송하거나 수신할 수 있고, 메시지에 응답하기 위해 자율적으로 메서드를 선택할 수 있다.
  • 객체에 대한 재귀는 객체지향의 개념을 모든 추상화 수준에서 적용 가능하게 하는 동시에 객체지향 패러다임을 어떤 곳에서든 일관성 있게 적용할 수 있게 한다.

기능 변경을 흡수하는 안정적인 구조

  • 도메인 모델을 기반으로 객체 구조를 설계하는 이유는 도메인 모델이 안정적이기 때문이다.
  • 도메인 모델이 안정적인 이유
    • 도메인 모델을 구성하는 개념은 비즈니스가 없어지거나 완전히 개편되지 않는 한 안정적으로 유지된다.
    • 도메인 모델을 구성하는 개념 간의 관계는 비즈니스 규칙을 기반으로 하기 때문에 비즈니스 정책이 크게 변경되지 않는 한 안정적으로 유지된다.
  • 비즈니스 정책이나 규칙이 크게 변경되지 않는 한 시스템의 기능이 변경되더라도 객체 간의 관계는 일정하게 유지된다.
  • 기능적인 요구사항이 변경될 경우 책임과 객체 간의 대응 관계만 수정될 뿐이다.
  • 도메인 모델링에서 사용한 객체와 개념을 프로그래밍 설계에서의 객체와 클래스(타입)로 매끄럽게 변환할 수 있다. => 연결 완전성
  • 객체지향이 강력한 이유는 연결 완전성의 역방향 역시 성립한다는 것이다.
  • 코드의 변경으로부터 도메인 모델의 변경 사항을 유추할 수 있다. (이것은 객체지향 이전의 대부분의 개발 방법이 대응하지 못하고 쉽게 무너졌던 영역이다.)
  • 코드의 수정이 곧 모델의 수정
  • 코드에서 모델로의 매끄러운 흐름 = 가역성