# LARGE SCALE STRUCTURE(대규모 구조) ### 위성통신 시스템 사례 * 네트워크 시뮬레이팅 소프트웨어 * 설계를 관리 가능한 크기의 응집력 있는 모듈로 분해하자 **너무 많은 모듈**이 생겨났다. * *"기능의 특정 측면을 보려면 어떤 패키지의 어떤 모듈을 보아야 하지?"* * *"새 클래스는 어디에 넣으면 되지?"* * 너무 많은 모듈로 인한 인지 과부하가 발생했다. * 프로젝트 리더의 고민 * 앞으로 설계가 더 복잡해질 때 **기존 설계를 이해하고 쉽게 변경할 수 있는 방법**이 필요하다. * 아이디어: 패키지 구조 변경, 시스템의 전체적인 개요를 보여주는 문서 작성, 모델링 도구로 클래스 다이어그램 생성, 작동 방식 설명 * *'아... 이걸로는 충분하지 않은데...'* * 프로젝트 리더의 결정 * 기존 설계에 **계층 구조**를 도입한다! * ex) 물리적 인프라 계층, 라우팅 계층, ... * 모듈이 여러 계층에 걸치지 않도록 다시 정의한다. * 한 객체는 한 계층에만 속하게 만든다. * 전체 설계가 이러한 계층적 구조가 될 때까지 리팩터링한다. * 결과 * 계층은 **모듈이나 객체, 다른 시스템과의 인터페이스에 대한 경계와 관계를 제약하는 규칙의 집합**이 되었다. * *"특정 기능을 어디서 찾아야 할 지 이제 좀 알겠다!"* * *"계층이 이렇게 나눠져 있으니깐 이 기능은 이 계층에 속하면 되겠다!"* * 계층을 도입하자 복잡성이 줄어들었다. ### 모듈화의 한계 * 큰 모델은 모듈로 분해해도 너무 복잡해서 파악하기 어려울 수 있다. * 관리 가능한 단위의 모듈로 설계를 계속 나누다보면 모듈이 너무 많아진다. * 모듈화 자체로 설계에 균일함이 생기지는 않는다. ### 업무의 독립성 * 프로젝트 규모 크든 작든 사람들은 시스템의 각기 다른 부분에서 어느 정도 독립적으로 일해야 한다. * **조율과 규칙**이 없다면? * 동일한 문제에 대해서도 다양한 형식과 별개의 해법 때문에 혼동이 일어난다. * 각 부분을 어떻게 맞춰야 할지 이해하기 힘들어진다. * 큰 그림을 보기가 불가능해진다. * 설계의 한 부분에 관해 학습한 바가 다른 부분으로 전해지지 않는다. * 결과적으로 서로 도움을 주지 못하고 각 모듈의 전문가만 남는다. * 지속적 통합은 실패하고 바운디드 컨텍스트는 단편화된다. * **결론: 조율과 규칙이 반드시 필요하다!** * 시스템의 특정 요소를 전체 설계 패턴 관점에서 해석할 수 있는 **지배적인 원칙**이 필요하다! * 지배적인 원칙이 없다면 나무만 보고 숲은 보지 못한다. * 디테일을 깊이 파고들지 않고도 각 부분이 담당하는 역할을 이해할 수 있어야 한다. ## 대규모 구조 * **대규모 구조**: 고수준의 개념, 규칙, 관계로 이루어진 **전체 시스템에 대한 설계 패턴**을 확립하는 것 * 대규모 구조를 통해 다양한 부분의 역할이 어떻게 전체적인 모습을 형성하는지 큰 그림으로 볼 수 있게 된다. * 각 부분의 책임을 디테일하게는 몰라도 된다. * 전체적인 관점에서 해당 부분의 위치를 대략적으로 알 수 있으면 된다. * 독립적인 업무를 조율하는데 도움이 된다. ![스프링 프레임워크 아키텍처](https://docs.spring.io/spring-framework/docs/3.0.x/spring-framework-reference/html/images/spring-overview.png) * 대규모 구조는 한 바운디드 컨텍스트에 한정될 수도, 여러 바운디드 컨텍스트에 걸쳐 있을 수도 있다. * 프로젝트에 관련된 모든 팀과 하위 시스템을 하나로 묶는 개념적 구성을 제공한다. * 대규모 구조는 UML로 표현할 수도 없고, 그럴 필요도 없다. * 리스크: 프로젝트에 어울리지 않는 구조는 개발에 장애물이 될 수도 있다. ## EVOLVING ORDER (발전하는 질서) > 구조를 발견/정제 * 구조화되지 않은 설계에서는 비용이 발생한다. * 개발자들은 이를 해결하고자 **개발을 제약하는 아키텍처**를 부과한다. * 하지만 요구사항이 바뀌고 이해가 깊어짐에 따라 아키텍처는 **속박**으로 작용할 수 있다. ### 대규모 구조는 사전에 확정 짓지 마라 * 대규모 구조를 사전에 확정 짓는 것은 비용이 많이 들 수 있다. * 왜? 개발이 진행됨에 따라 더 적합한 구조를 찾게 되기 때문이다. * 미리 규정해둔 구조 탓에 더 좋은 설계를 택할 수 없을 수도 있다. * 관리자는 아키텍처가 완성되었다고 생각한다. * *"아키텍처 확정됐다면서? 이제 애플리케이션에 관련한 업무를 하면 될텐데 왜 아직 아키텍처 문제를 붙잡고 있어?"* ### 대규모 구조는 양날의 검이다 * 아무나 설계할 수 있다면 전체적으로 이해하기 어렵고 유지보수도 어려운 시스템이 만들어진다. * 아키텍처는 사전 설계와 관련한 가정을 둠으로써 일관성을 확보할 수 있다. * 하지만 동시에 특정 부분에서 개발자와 설계자의 권한을 너무 많이 앗아갈 수도 있다. #### 순응이냐 혁멱이냐 1. 애플리케이션의 수준이 떨어지든 말든 어떻게든 구조에 맞추어 개발한다. (*될대로 되라..*) 2. 구조를 무시하고 애플리케이션을 뒤엎어 아무런 구조도 없게 만든다. (*혁명이다!!*) ### 설계를 관장하는 규칙 * 설계를 관장하는 규칙은... 1. 방해가 되지 않아야 한다. 2. 일관성이 있어야 한다. 3. 실질적으로 도움이 되는 방향으로 개발을 이끌어야 한다. ### 발전하는 대규모 구조 * 대규모 구조는 애플리케이션과 함께 발전해야 한다. * 발전 과정에서 전혀 다른 형식의 구조로도 변화할 수 있어야 한다. * 디테일한 설계 및 모델과 관련된 의사결정을 과도하게 제약해서는 안 된다. ### 구조의 단일화 VS 개별 컴포넌트의 최적화 * 개별 부분에는 전체에 적용되지는 않지만 자연스럽고 유용한 구성 및 표현 방법이 있을 수 있다. * 개별 부분에 전역적인 규칙을 부과하면 이러한 이점을 취할 수 없다. * 대규모 구조를 쓴다는 것: 개별 부분을 최적화된 방법으로 구성하기보다 전체적인 모델의 관리에 집중한다는 것 * 구조의 단일화와 개별 컴포넌트의 최적화 사이의 트레이드 오프를 적절히 선택해야 한다. * 도메인에 대한 실제 경험과 지식을 바탕으로 구조를 선택하고 너무 속박된 구조를 피해야 한다. ### 대규모 구조와 바운디드 컨텍스트 * 대규모 구조는 여러 바운디드 컨텍스트에 걸쳐 적용할 필요가 있다. * 구조는 개별 컨텍스트의 개발팀에 해당 팀에만 해당하는 요구사항을 다룰 수 있는 방식으로 다양하게 모델을 취할 자유를 부여해야 한다. ### 대규모 구조와 실질적인 제약조건 * 대규모 구조는 개발 과정에서 실질적인 제약조건을 수용해야 한다. * 설계자는 시스템의 특정 부분의 모델이나 외부 시스템, 레거시 하위 시스템 등을 통제하지 못할 수 있다. #### 설계자가 외부 요소를 통제하지 못할 때 해결법 1. 구조를 어떤 외부 요소에 더 잘 맞는 구조로 변경한다. 2. 애플리케이션이 외부와 관계를 맺는 방법을 명시한다. 3. 구조를 충분히 느슨하게 만든다. ### 대규모 구조는 선택 사항이다 * 비용과 편익 측면에서 대규모 구조가 존재하는 것이 유리하고 알맞은 경우에만 시스템에 적용해야 한다. * 모델을 개발하는 데 부자연스러운 제약조건을 강제하지 않고도 시스템을 명확하게 만들 수 있을 때만 적용해야 한다. * **맞지 않는 구조는 차라리 없느니만 못하다!** * 모듈로 분해했을 때 충분히 이해할 수 있을 정도로 시스템이 간단하다면 대규모 구조는 필요 없다. * 종합적인 구조를 얻으려 애쓰지 말고, 발생한 문제를 해결하는 최소한의 집합을 찾아라! #### 대규모 구조에 예외가 발생하면? * 대규모 구조에 예외가 발생하면 이를 손쉽게 파악할 수 있게 해두어야 한다. * 예외가 많아지면 구조를 변경하거나 폐기해야 한다. ### 결론 * **개발자들에게 필요한 자유를 주는 동시에 혼란을 방지하는 구조를 만들어야 한다.** #### 앞으로 살펴볼 대규모 구조의 패턴 4가지: 1) SYSTEM METAPHOR (시스템 은유) 2) RESPONSIBILITY LAYER (책임 계층) 3) KNOWLEDGE LEVEL (지식 수준) 4) PLUGGABLE COMPONENT FRAMEWORK (착탈식 컴포넌트 프레임워크) ## SYSTEM METAPHOR (시스템 은유) > 사고를 이끄는 수단 * XP의 은유 실천법: 은유를 써서 전체 시스템 개발에 질서를 부여한다. * 은유는 우리의 사고방식을 특정한 방향으로 유도한다. ### 방화벽 은유 ![전기시설 방화벽](https://upload.wikimedia.org/wikipedia/commons/9/9a/Power_systems_in_Toppila_Jun2008.jpg) * 실제 방화벽: 외부의 화재로부터 건물이나 시설을 보호한다. * 소프트웨어의 방화벽: 외부 네트워크의 위험으로부터 지역 네트워크를 보호한다. #### 방화벽 은유의 양면성 * 긍정적 효과: 방화벽 은유는 네트워크 아키텍처에 영향을 주고, 독자적인 제품군을 형성했다. * 부정적 효과: 방화벽 은유로 인해 내부의 위협 요소에 대해서는 간과하게 되었다. * ex) 무선랜의 취약한 보안: 외부 네트워크의 단일 진입점까지만 방화벽이 존재하면 된다는 생각을 무의식적으로 하게 된다. 내부에서는 어떤 식으로 데이터를 주고 받는지는 별 상관 안하게 되어 버렸다. ### 은유의 장점 * 소프트웨어 설계는 매우 추상적이고 파악하기 힘들다. * 은유는 개발자와 사용자가 전체 시스템을 쉽게 이해하고, 전체적으로 바라보는 시각을 공유할 수 있는 수단이 될 수 있다. * 개발자는 은유를 통해 일관성 있는 설계 결정을 내린다. * 은유는 객체 패러다임과 조화를 이루는 느슨하고 쉽게 이해할 수 있는 대규모 구조다. * 적절한 시스템 은유는 여러 바운디드 컨텍스트에 적용되어 서로의 업무를 조율하는 데 도움을 줄 수 있다. * 유용한 은유는 시스템에 관한 의사소통을 촉진하고 개발을 이끈다. * 성공적인 은유는 시스템의 여러 부분과 여러 바운디드 컨텍스트에 걸쳐 일관성을 증대한다. ### 은유의 단점 * 은유는 본질적으로 **부정확한 유추**이다. * 은유는 도메인에 대한 일종의 비유에 불과하다. * 실제로 유용한 은유를 찾아내는 경우는 거의 없다. * 도메인에 억지로 은유를 적용해서 역효과만 내는 경우가 많다. * 매력적이긴 하나 당면한 문제에는 적합하지 않을 수도 있다. ### 은유 도입 가이드라인 * 은유가 유용하다면 대규모 구조로 채택하라. * 은유를 중심으로 설계를 구성하고 이를 보편 언어로 흡수하여 보편 언어를 확대하라. * 하지만 모든 은유는 부정확하므로 은유가 지나치거나 적절치 못하다면 버려라. ### 미숙한 은유 * 성숙한 도메인 모델은 결코 미숙하지 않다. * 모델은 수많은 반복주기를 거친 도메인 전문가와의 지식 탐구의 산물이며, 동작하는 애플리케이션의 구현에 긴밀하게 엮이면서 입증된 것이다. ## RESPONSIBILITY LAYER (책임 계층) > 계층화의 대상 ### 개별 객체에 손수 만든 책임이 할당되어 있다면 1) 가이드라인도 없다 2) 균일함도 없다 3) 넓은 범위에 걸친 도메인을 동시에 다룰 능력도 없다. ### 큰 규모에서의 책임 주도 설계 * 큰 모델에 응집력을 부여하려면 책임 할당에 특정 구조를 도입하는 것이 도움이 된다. ### 계층화 * 도메인을 깊이 있게 이해하면 모듈 간 의존성에 따라 자연적인 층이 보이는 경우가 있다. * 이러한 자연적인 층을 토대로 계층을 나눌 수 있다. #### 계층화의 특징 * 아래에 있는 계층의 서비스는 알고 이용할 수 있다. * 위에 있는 계층은 알지 못하고 독립적으로 존재한다. * 의존성 화살표는 언제나 아래를 향한다. * A가 B에 의존한다면, A를 위에, B를 아래에 놓는다. ![OSI 7 계층 예시](https://lh3.googleusercontent.com/Mn5UKGeWOhDRwTr16RCTN6MDfy1_u3bhzWJxa-jYgJd_xRvalV5IdKreSXWsI9ia_4Td89HApvz2XTsKWkyOstGbrJbcjOoJ3n6uHErwHQyRbOlraPiIa_BTDm-pTeQTD6UiGkty) #### RELAXED LAYERED SYSTEM(느슨한 계층화 시스템) * 느슨한 계층화 시스템에서는 한 계층의 구성요소가 자신의 바로 아래에 있는 계층뿐만 아니라 모든 하위 계층에 접근할 수 있다. ### 계층화와 책임 주도 설계 * 자연적인 층이 나타나는 모델에서는, 계층화와 책임 주도 설계를 묶어서 주요 책임을 기준으로 개념적 계층을 정의하고 여기에 이름을 붙일 수 있다. * 계층의 책임은 개별 객체에 할당하는 책임에 비해 범위가 넓다. * 이름이 있는 책임 그룹은 모듈화 시스템의 이해를 향상시킬 수 있다. #### 계층화 도입 가이드라인 * 모델에 존재하는 개념적 의존성과 도메인의 여러 부분에 대한 다양한 변화율과 변화의 근원을 검토하라. * 도메인에서 자연적인 층을 식별하면 그것을 광범위한 추상적 책임으로 간주하라. * 이러한 책임을 통해 높은 수준에서 시스템의 목적과 설계를 이해할 수 있다. * 각 도메인 객체(애그리거트, 모듈 등)의 책임이 한 계층의 책임 안에 들어맞도록 모델을 리팩터링하라. ### 책임 계층 * 책임으로 계층을 구분하면 각 부분의 역할과 의존성을 더 쉽게 파악할 수 있다. * 시스템은 운영이나 잠재 기능과 같은 계층에 의존한다. | 계층 | 구분 | 상태 변화 | | --- | --- | --- | | 의사결정 지원 | 분석적 메커니즘 | 매우 적음 | | 정책 | 업무상의 목표나 법률 | 느림 | | 계약 | 고객과의 업무 거래와 계약 | 적정 | | 운영 | 실제 업무 활동과 계획 | 신속 | | 잠재 기능 | 실제 업무 자원 | 적정 | #### 잠재 기능 계층 * *무엇을 할 수 있는가?* * 잠재 기능 계층은 운영 계층을 참조하면 안 된다. #### 운영 계층 * *무엇이 행해지는가?* * 바라는 바가 아닌 실제 상황을 반영해야 한다. #### 계약 계층 * *우리가 약속한 바는 무엇인가?* * 향후 운영 방향을 제시할 목표를 명시한다. #### 정책 계층 * *규칙과 목표는 무엇인가?* * 정교한 업무 규칙이나 법적 요구사항. * 수동적이지만 다른 계층의 행위를 제약한다. #### 의사결정 지원 계층 * *어떤 행동을 취하고 어떤 정책을 수립해야 하는가?* * 운영상의 현실이나 계획, 기능에 대한 것이 아니라 계획을 변경하는 결정을 내리는 데 도움을 주는 것 * 대체로 데이터 웨어하우스 기술을 이용해 구현한다. * 의사결정 지원 계층은 운영 소프트웨어와 고객/공급자 관계를 맺은 별도의 바운디드 컨텍스트가 된다. ### 적절한 계층을 선택하자 * 대규모 구조의 가치는 복잡성이 증가할수록 증대된다. * 프로젝트에 참여한 모든 이가 일관된 방식으로 결정을 내린다면 전체적으로 설계가 이해하기 쉬워진다. * 알맞은 책임 계층이나 대규모 구조를 찾을 때는 문제 도메인을 이해하고 실험하는 것이 중요하다. ### 계층이 변경될 때 지켜야 할 몇 가지 특징 1. **스토리 텔링**: 계층은 도메인의 기본적인 실제 상황과 우선순위를 전해줘야 한다. 대규모 구조를 선택하는 것은 기술적 결정이 아니라 업무와 관련된 모델링 결정이다. 계층은 업무의 우선순위를 드러내야 한다. 2. **개념적 의존성**: 상위 계층에 있는 개념은 하위 계층을 배경으로 하는 의미를 지녀야 한다. 동시에 하위 계층의 개념은 독자적인 의미를 지녀야 한다. 3. **개념적 윤곽**: 계층은 변화율이나 변화의 근원이 서로 다른 객체 간에 구획을 짓게 도와준다. ## KNOWLEDGE LEVEL(지식 수준) > 인공적인 행위를 분리하는 대상 ### 지식 수준 * 다른 객체 집단이 어떻게 행동해야 하는지를 기술하는 객체의 그룹 * 구성 가능한 행위를 갖춘 소프트웨어의 요구사항을 다룬다. * 구성 가능하다: 여러 엔티티 간의 역할과 관계를 동적으로 변경할 수 있다 * 도메인을 모델링하기보다 모델을 구조화한다. ### 애플리케이션의 가정 * 애플리케이션은 사용자가 어떻게 사용할 것이라는 가정을 한다. * 사용자가 생각한 가정과 애플리케이션의 가정이 서로 맞지 않으면 사용자는 개발자가 의도한 바와 다른 방식으로 애플리케이션을 사용한다. * 애플리케이션의 가정이 맞지 않기 때문에 사용자는 애플리케이션의 도움을 받지 못한다. * 사용자는 자신의 행위의 효과를 얻기 위해 꼼수를 사용하거나 애플리케이션 상위 수준의 기능을 막을 수도 있다. * 개발자는 나중에서야 해당 시스템의 기능이 보이는 것과는 의미가 다르다는 사실을 알게된다. * 기능은 다른 사용자 집단이나 다른 상황에서는 굉장히 다른 의미를 가질 수 있다. * 의미가 덧씌워진 사용법을 건드리지 않으면서 새로운 시스템으로 데이터를 이전하는 것은 아주 힘들다. > "아... 이거 그렇게 쓰라고 만든거 아닌데..." ### 정적인 모델 VS 동적인 모델 * 너무 정적인 모델은 요구사항을 유연하게 받아들이지 못한다. * 너무 동적인 모델(완전히 유연한 시스템)은 쓰기가 불편하다. ### 커스터마이징 함정 * 엔티티간의 역할과 관계가 상황마다 다양하게 작용하는 애플리케이션에서는 복잡성이 폭발적으로 증가할 수 있다. * 유연함을 추가할수록 소프트웨어는 점점 더 복잡해지기만 한다. * 완전히 커스터마이징이 가능한 소프트웨어는 실용적이지 않다. * 완전히 일반화된 모델이나 고도로 맞춤화가 가능한 모델은 사용자의 욕구를 충족시키지 못한다. * 굉장히 특화된 제약조건이 일반화된 프레임워크보다 더 유용할 수 있다. * 더 단순하고 구체적인 설계자의 의도를 전달하는 것이 가능하기 때문이다. ![커스터마이징 지옥](https://pbs.twimg.com/media/DzXFezjXcAEaoHD.png) * 설정보다 관례(CoC, Convention over Configuration)식 접근이 이러한 복잡성을 해결하기 위한 방법이 아닐까? ### 지식 수준과 반영 패턴 * 지식 수준은 모델에서 자기 규정적인 측면을 분리해서 제약조건을 명시적으로 만든다. * 지식 수준은 반영 패턴의 도메인 계층을 응용한 것이다. * 메타 수준(Meta Level): 소프트웨어의 구조와 행위에 대한 지식 (지식 수준) * 기반 수준(Base Level): 애플리케이션의 운영적 책임을 수행 (운영 수준) * 지식 수준은 반영 패턴과 달리 애플리케이션 도메인에 초점을 맞춘다. * 지식 수준은 완전한 보편성을 달성하려고 애쓰지 않는다. * 지식 수준은 계층화가 아니다 * 왜? 지식 수준 간에는 상호의존성이 있지만, 계층 간에는 의존성이 상위 계층에서 하위 계층으로 일방향이다. ### 지식 수준이 복잡해지면? * 사용자(개발자 포함)들이 시스템의 행위를 이해하기가 힘들어진다. * 시스템을 구성하는 사용자(또는 관리자)가 메타 수준의 프로그래머가 되어야 한다. * 혹시 실수라도 하면 애플리케이션이 뻗을 수도 있다. > "그럴 바엔 내가 개발자 하지!" ### 지식 수준 도입 가이드라인 * 설계는 개발 과정에서 제시된 시나리오뿐 아니라 향후 사용자가 소프트웨어를 구성해서 처리할 수도 있을 어떠한 시나리오도 처리할 정도로 강건해야 한다. * 커스터마이징이 효과적이면서도 설계를 왜곡하지 않을 정도로 신중하게 적용해야 한다. ## PLUGGABLE COMPONENT FRAMEWORK (착탈식 컴포넌트 프레임워크) > 개별 기여도를 분리 ### 통합의 어려움 * 같은 추상화에 기반을 두지만 서로 독립적으로 설계되어 있는 다양한 종류의 애플리케이션이 상호운용되어야 할 때, 여러 바운디드 컨텍스트 사이의 번역 때문에 통합이 힘들어진다. * 중복과 단편화는 개발과 설치 비용을 높이고 상호운영성은 달성하기 어려워진다. ### 중앙 허브 * 모든 컴포넌트는 각자 특정 기능을 제공하며, 중앙 허브에 연결된다. * 중앙 허브는 연결된 컴포넌트가 제공하는 인터페이스와 통신하는 방법을 알고 있다. ### 추상 핵심 * 추상 핵심 = 고수준 추상화 * 인터페이스와 상호작용에 대한 추상 핵심을 정제하라. * 인터페이스의 다양한 구현이 자유롭게 대체될 수 있는 프레임워크를 만들어라. * 중앙 허브는 공유 커널 안의 추상 핵심에 해당한다. * 특수화는 모듈에서 일어난다. * 바운디드 컨텍스트는 캡슐화된 컴포넌트 인터페이스 너머로 숨길 수 있다. ### PCF의 장점 * 애플리케이션이 추상 인터페이스를 엄격히 준수한다면 애플리케이션은 구현과 무관하게 인터페이스가 약속한 서비스에 의지할 수 있다. * 즉, 서로 독립적으로 개발한 소프트웨어를 거대한 시스템에 매끄럽게 통합할 수 있다. * 시스템의 디테일은 몰라도 큰 그림은 쉽게 이해할 수 있다. ### PCF의 단점 * 매우 적용하기 힘든 패턴이다. * 추상 핵심의 인터페이스를 설계할 때 충분히 심층적인 모델이 필요하다. * 한 마디로, 애플리케이션을 다 개발하고 나서야 좀 괜찮은 PCF를 만들 내공이 생긴다. ### 에이즈 추모 퀼트 사례 > 이거 하지마 저거 하지마 이거 해 저거 해 * "완성된 패널의 크기는 90cm x 180cm여야 합니다. 더 커도 안 되고 더 작아도 안 됩니다" * "천을 자를 때는 단에 쓸 수 있게 측면마다 2~3인치 정도 남기세요" * "안감은 넣을 수 있으면 넣으세요" * "접착제는 쓰지 마세요" * "직물 페인트나 빛이 바래지 않는 도료로 칠하거나 안 지워지는 잉크 펜을 사용하세요" * "제발 볼록 페인트는 쓰지 마세요" * "천 위에 연필로 디자인 윤곽을 그리고 스텐실을 올리고 붓으로 직물 페인트나 안 지워지는 마커를 칠하세요" * "천이 찢어지지 않게 하기위해서 유리나 금속 조각, 부피가 큰 물체는 쓰지 마세요" * "사진이나 글자를 넣을 때는 전사용지에 사진이나 글자를 사진복사하고 100% 순면 천 위에 다림질한 다음 그 천을 패널에 꿰매세요. 아니면 깨끗한 플라스틱 비닐에 사진을 넣고 패널에 꿰매세요." ## 구조는 얼마나 제약성을 지녀야 하는가?? > (매우 느슨) 시스템 은유 <-------> PCF (제약적) ### 하위 계층의 신호 전달 * 하위 계층에서 일어난 예외적인 상황은 상위 계층에 전달되어야 한다. * 하위 계층은 상위 계층에 관해 아무것도 알지 못한다. * 따라서 통신은 하위 계층에서 상위 계층으로 양방향 의존성을 만들어내지 않는 방식으로 일어나야 한다. * 신호 전달은 일반적으로 이벤트 메커니즘을 통해 이뤄진다. * 하위 계층의 객체는 상태가 변경될 때마다 이벤트를 발생시킨다. * 상위 계층의 객체는 하위 계층으로부터 이벤트를 기다린다. ### 제약은 과해서는 안 된다 * 제약은 개발자가 필요로 하는 유연함을 앗아갈 수도 있다. * 프레임워크를 만들고 대규모 구조의 구현을 엄격히 통제하고자 하는 유혹을 이겨내야 한다. * 대규모 구조의 가치: 개념적 응집성과 도메인에 대한 통찰력을 주는 것 * 각 구조적 규칙은 개발을 용이하게 해야 한다. ### 답은 끊임없는 반복뿐 * 유용한 구조가 발견되는 유일한 방법: 도메인과 문제를 매우 심층적으로 이해하는 것 * 그러려면? 반복적인 개발 과정뿐 * 프로젝트 라이프사이클 내내 대규모 구조를 재고해야 한다. * 초기에는 도메인이나 요구사항을 잘 이해하는 사람이 아무도 없다. * 초기에 구상한 구조는 도메인과 맞지 않는 구조일 가능성이 높다. * 최종 구조는 처음에는 가용하지 않다. * 계속해서 리팩터링을 거쳐서 그러한 구조가 나오게 해야 한다. ### 비용을 통제하고 이익을 극대화하는 방법 #### 최소주의 * 구조를 간단하고 가볍게 유지한다. * 포괄적인 구조로 만들지 마라. * 가장 중요한 관심사만 다루고 나머지는 케바케로 처리한다. * 초반에는 시스템 은유나 몇 가지 책임 계층과 같은 느슨한 구조를 택한다. #### 의사소통과 자기 훈련 * 모든 팀원은 새로운 개발과 리팩터링 시 반드시 구조를 이해하고 구조에 따른다. * 용어와 관계는 반드시 보편 언어에 들어가야 한다. * 대규모 구조는 시스템을 폭넓게 다루고 다양한 사람들이 독립적으로 조화로운 결정을 내릴 수 있게 어휘를 제공할 수 있다. * 대부분의 대규모 구조는 느슨한 개념적 지침이므로 팀은 반드시 자기 훈련을 수행해야 한다. * 많은 사람들이 일관되게 따르지 않으면 구조는 쇠퇴한다. * 팀 내 대화는 시스템 내의 대규모 구조를 일관되게 유지하기에 충분하지 않다. * 대화는 프로젝트의 보편 언어에 통합해서 모든 팀원이 끊임없이 해당 언어를 연습하게 만들어야 한다. #### 재구조화가 유연한 설계를 낳는다. * 구조를 변경하다 보면 상당한 양의 리팩터링이 필요할 수 있다. * 구조는 시스템의 복잡성이 증가하고 이해가 깊어질수록 발전한다. * 구조가 바뀔 때마다 전체 시스템은 새로운 질서를 따르도록 바뀌어야 한다. * 구조가 있는 설계가 구조가 없는 설계보다 변경하기 쉽다. * 현재 배치를 이해할 수 있어야 재배치하기가 쉽다. * 여러 번에 걸친 올바른 변형을 거쳐 반복적으로 변형된 모델: * 안정적인 측면은 단순화된다. * 늘어나는 지식은 모델에 녹아들고 변화의 중심축이 식별되어 유연해진다. #### 디스틸레이션은 부하를 줄인다. * 지속적인 디스틸레이션은 구조 변경의 어려움을 덜어준다. * 처음에는 도메인에 대한 피상적 이해에 근거해 계층을 선택할 수도 있다. * 계층은 점차 시스템의 근본적인 책임을 표현하는 추상화로 대체되어 명료해진다. * 시스템의 근본적인 책임이 명료해지면 사람들은 설계를 심층적으로 들여다 볼 수 있다. (목표) * 그 결과 시스템의 대대적인 조작이 쉽고 안전해진다.