Chapter 6

객체 지도

  • 기능과 구조
  • 기능 설계 vs 구조 설계
  • 도메인 모델
  • 유스케이스
  • 기능과 구조의 통합

소프트웨어의 큰 그림을 어떻게 그릴 것인가에 대한 이야기야. 5장까지가 개별 객체와 객체 간 메시지에 집중했다면, 이번엔 한 단계 위로 올라가서 시스템 전체의 구조와 기능을 어떻게 설계할 것인가를 다루지. 저자가 사용하는 비유는 객체 지도 — 지도처럼 안정적인 구조 위에 기능을 올려놓아야 한다는 거야.

소프트웨어를 만드는 이유는 기능을 제공하기 위해서잖아. 사용자는 소프트웨어의 내부 구조에 관심이 없어. 그냥 원하는 걸 할 수 있으면 되거든.

하지만 기능만 생각하고 구조를 무시하면 큰 코를 다쳐. 기능은 끊임없이 바뀌기 때문이야. 요구사항이 추가되고, 변경되고, 삭제되지. 구조가 엉망이면 기능 하나 바꾸는 데 시스템 전체를 뒤집어야 하는 사태가 벌어져.

저자의 핵심 통찰: 기능은 변하지만 구조는 상대적으로 안정적이야. 그래서 안정적인 구조 위에 변화하는 기능을 올려놓아야 하지. 지도가 그렇듯이 — 도로와 건물의 위치(구조)는 잘 안 바뀌지만, 그 위에서 사람들이 하는 일(기능)은 계속 바뀌잖아.

저자는 전통적인 소프트웨어 설계 방식과 객체지향 설계 방식을 대비시켜.

기능 중심 설계는 기능 분해(functional decomposition)로 시작해. 시스템이 해야 할 일을 큰 기능 단위로 나누고, 각 기능을 다시 하위 기능으로 나누고, 이걸 반복해서 쪼개지. 최종적으로 각 하위 기능이 프로시저나 함수가 돼.

문제는 뭐냐면 — 기능은 자주 바뀐다는 거야. 기능을 중심으로 시스템을 구조화하면, 기능이 바뀔 때마다 구조가 흔들려. 하나의 기능을 수정하면 관련된 다른 기능들이 연쇄적으로 영향을 받지. 이게 절차지향적 코드가 유지보수하기 어려운 근본적인 이유거든.

객체지향은 반대로 접근해. 기능이 아니라 구조를 먼저 잡지. 문제 도메인의 구조를 파악하고, 그 구조에 맞춰 객체를 배치하고, 기능은 그 객체들의 협력으로 구현하는 거야.

왜 구조가 기능보다 안정적인가? 비즈니스 도메인의 핵심 개념은 잘 안 바뀌기 때문이야. "주문", "상품", "고객" 같은 개념은 사업을 접지 않는 한 계속 존재하잖아. 변하는 건 이 개념들 사이의 세부적인 규칙이나 새로운 기능이지, 개념 자체가 사라지는 경우는 드물거든.

**도메인 모델(domain model)**은 "구조 중심 설계"의 출발점이야.

도메인 모델이란, 사용자가 프로그램을 사용하는 대상 영역에 대한 지식을 선택적으로 단순화하고 의식적으로 구조화한 형태지. 쉽게 말하면, 이 비즈니스가 어떻게 돌아가는지를 모델로 정리한 거야.

예를 들어 온라인 서점의 도메인 모델이라면:

  • 고객이 있고
  • 고객은 주문을 하고
  • 주문에는 주문 항목이 포함되고
  • 각 주문 항목은 상품을 참조하고
  • 상품에는 가격이 있지

이 구조가 도메인 모델이야. 여기에는 "주문 총액을 계산한다"거나 "할인을 적용한다" 같은 기능이 빠져 있어. 도메인 모델은 기능이 아니라 개념과 관계만 포착하거든.

도메인 모델이 강력한 이유:

  • 안정적이야. 비즈니스의 핵심 개념은 잘 안 바뀌거든
  • 공유 언어가 돼. 개발자, 기획자, 도메인 전문가가 같은 모델을 보면서 소통할 수 있지 (이게 에릭 에반스의 DDD에서 말하는 유비쿼터스 언어와 연결돼)
  • 소프트웨어 구조의 뼈대가 되지. 도메인 모델의 개념이 클래스가 되고, 관계가 연관관계가 돼

저자가 강조하는 포인트: 도메인 모델은 소프트웨어 내부의 구조와 일치해야 해. 도메인에서 "주문"이라 부르는 것이 코드에서도 Order여야 하고, 도메인에서 "주문은 여러 주문 항목을 포함한다"고 하면 코드에서도 OrderOrderItem 리스트를 가지고 있어야 하지. 이 일치가 깨지면, 도메인 전문가와 대화할 때 번역이 필요해지고, 코드를 읽을 때 도메인 지식이 도움이 안 되거든.

도메인 모델이 구조를 포착한다면, **유스케이스(use case)**는 기능을 포착해.

유스케이스란, 사용자(액터)와 시스템 사이의 상호작용 흐름을 기술한 거야. 사용자가 시스템에 어떤 요청을 하고, 시스템이 어떻게 응답하는지를 순서대로 적은 시나리오지.

예를 들어 "주문하기" 유스케이스:

  1. 고객이 상품을 장바구니에 담아
  2. 고객이 주문을 요청해
  3. 시스템이 재고를 확인하지
  4. 시스템이 결제를 처리하고
  5. 시스템이 주문 확인을 보내

유스케이스에서 중요한 건 이거야 — 유스케이스는 시스템의 내부 구조에 대해 아무것도 말하지 않아. 어떤 객체가 재고를 확인하는지, 어떤 클래스가 결제를 처리하는지는 유스케이스의 관심사가 아니거든. 유스케이스는 순수하게 외부에서 본 시스템의 행동만 기술하지.

이게 도메인 모델과의 차이점이야:

  • 도메인 모델 — 시스템 내부의 구조. "무엇이 있는가"
  • 유스케이스 — 시스템 외부의 행동. "무엇을 할 수 있는가"

좋은 객체지향 설계란, 도메인 모델을 기반으로 안정적인 구조를 만들고, 유스케이스의 기능을 그 구조 위에서 객체들의 협력으로 구현하는 것이야.

구체적인 절차:

  1. 도메인 모델로 핵심 개념과 관계를 파악해 (구조)
  2. 유스케이스로 시스템이 제공해야 할 기능을 정리하고 (기능)
  3. 유스케이스의 각 단계를 도메인 모델의 객체들에게 책임으로 할당
  4. 객체들이 메시지를 주고받는 협력으로 유스케이스를 실현하지

이 과정에서 도메인 모델의 개념이 코드의 클래스가 되고, 유스케이스의 시나리오가 객체 간의 메시지 흐름이 돼. 구조(도메인 모델)는 안정적이므로 코드의 뼈대도 안정적이고, 기능(유스케이스)이 바뀌면 협력의 세부사항만 수정하면 되거든.

저자의 핵심 메시지: 기능은 구조를 따라야 해. 구조가 기능을 따르면 기능이 바뀔 때마다 구조가 흔들리지. 반대로 기능이 구조를 따르면, 안정적인 뼈대 위에서 기능을 유연하게 추가하고 변경할 수 있어.


정리

6장 읽고 기억할 거 세 가지:

  1. 기능은 바뀌지만 구조는 안정적이야. 구조 위에 기능을 올려. 기능 중심으로 시스템을 쪼개면 변경에 취약해지거든
  2. 도메인 모델이 구조의 뼈대야. 비즈니스의 핵심 개념과 관계를 코드에 그대로 반영해. 도메인 모델과 코드 구조가 일치해야 유지보수가 쉽지
  3. 유스케이스의 기능을 도메인 모델의 객체들에게 책임으로 할당해라. 이게 기능과 구조를 통합하는 방법이야. 안정적인 구조 위에서 유연한 기능을 구현하는 핵심 전략이지