5장 : 아키텍처
15장 : 아키텍처란?
소프트웨어 아키텍트 : 최고의 프로그래머이며, 앞으로도 계속 프로그래밍 작업을 맡을 뿐만 아니라 동시에 나머지 팀원들이 생산성을 극해화 할 수 있는 설계를 하도록 방향을 이끌어 준다.
아키텍처의 주된 목적은 시스템의 생명주기를 지원하는 것이다. 좋은 아키텍처는 시스템을 쉽게 이해하고, 쉽게 개발하며, 쉽게 유지보수하고, 또 쉽게 배포하게 해준다. 아키텍처의 궁극적인 목표는 시스템의 수명과 관련된 비용은 최소화하고, 프로그래머의 생산성은 최대화하는 데 있다
시스템 아키텍처는 개발팀이 시스템을 쉽게 개발할 수 있도록 뒷받침 해야한다.
배포
한번에 쉽게 배포할 수 있도록 해야한다.
개발 초기 단계에 해당 단계를 진행하기 쉽지 않을 수 있지만 고려해야한다.
운영
시스템을 운영하는데 필요한 요구도 알려준다.
유스케이스, 기능, 시스템의 필수 행위를 일급 엔티티로 격상 시키도, 이들 요소가 개발자에게 주요 목표로 인식 되도록 해야한다.
이를 통해 시스템을 이해하기 위워지며 개발과 유지보수에 큰 도움이 된다.
유지보수
비용이 가장 많은 단계이다.
가장 큰 비용은 탐사 와 이로인한 위험 부담이 있다.
탐사 : 새로운 기능 추가, 결함 수정시에 어디를 고쳐야할지 결정할때 드는 비용
시스템을 컴포넌트로 분리하고 안정된 인터페이스를 두어 격리한다.
선택 사항 열어두기
행위적 가치와 구조적 가치를 소프트웨어는 지닌다.
소프트웨어를 부드럽게 만드는것은 구조적 가치이다.
중요치 않은 세부사항에 대해서는 열어두어야한다.
정책 : 시스템의 진정한 가치가 살아있는것
세부사항 : 사람, 외부시스템 프로그래머가 정책과 소통할때 필요한 요소지만 , 정책이 가진 행위에는 영향을 미치지 않는것
예시 ) DB, 웹 시스템, 프레임 워크 등..
아키텍처는 초기에 정책을 가장 핵심적인 역할로 식별하고 세부사항에는 열어 두어야한다.
웹이나 DB종류 Rest와 같이 세부사항을 연기하고 미뤄서 나중에 결정할 수 있다.
좋은 아키텍트는 결정되지 않은 사항의 수를 최대화한다.
장치 독립성
동일한 프로그램을 아무런 변경없이도 카드에서 읽고 쓰거나 테이프에서 읽고 쓸 수 있게 되었다.
개방 폐쇄 원칙이 탄생한 순간으로 이전의 문제였던 장치 독립성 문제를 해결하였다.
광고 우편 , 물리적 주소할당
세부사항을 분리한 예시
주소할당체계를 변경하여 디스크 드라이브 구조에 대한 결정사항을 애플리케이션으로부터 분리할 수 있게 되었다.
결론
좋은 아키텍트는 세부사항에 대한 결정을 가능한 한 오랫동안 미룰 수 있는 방향으로 정책을 설계한다.
16장 : 독립성 (ME)
좋은 아키텍처가 지원해야할 4가지
시스템의 유스케이스
시스템의 운영
시스템의 개발
콘웨이의 법칙
시스템을 설게하는 조직이라면 어디든지 그 조직의 의사소통 구조와 동일한 구조의 설계를 만들어 낼것이다.
각 팀이 독립적으로 행동하기 편한 아키텍처를 반드시 확보하여 개발하는 동안 팀들이 서로 방해받지 않도록 해야한다.
시스템의 배포
배포용이성을 결정하는데 중요한 역할을 한다.
목표는 즉각적인 배포다.
시스템을 컴포넌트 단위로 적절하게 분할하고 격리시켜야 한다.
선택 사항 열어두기
좋은 아키텍처는 선택사항을 열어 둠으로써, 향후 시스템에 변경이 필요할 때 어떤 방향으로든 쉽게 변경할 수 있도록 한다.
계층 결합 분리
아키텍트는 단일 책임 원칙과 공통 폐쇄 원칙을 적용하여, 그 의도의 맥락에 따라서 다른 이유로 변경되는 것들은 분리하고 동일한 이유로 변경되는 것들은 묶는다.
시스템을 수평적인 게층으로 분리할 수 있는것을 알게되었다.
유스케이스 결합 분리
UI의 일부 , 애플리케이션 특화 업무 규칙의 일부, 애플리케이션 독립적 업무 규칙의 일부, 그리고 데이터베이스 기능의 일부를 사용한다.
시스템에서 서로 다른 이유로 변경되는 요소들의 결합을 분리하면 기존 요소에 지장을 주지 않고도 새로운 유스케이스를 계속해서 추가할 수 있게 된다.
또한 유스케이스를 뒷받침 하는 UI와 데이터 베이스를 서로 묶어서 각 유스케이스와 UI와 데이터 베이스의 서로 다른 관점을 사용하게 되면 새로운 유스케이스를 추가하더라도 기존 유스케이스에 영향을 주는 일은 거의 없을 것이다.
결합 분리 모드
관점을 분리
때때로 컴포넌트를 서비스 수준 까지도 분리해야 한다는 것이다.
개발 독립성
여러 팀이 분리되어도 유스케이스의 결합이 분리된다면 한 시스템의 아키텍처는 그 팀 구조를 뒷받침 해줄것이다.
배포 독립성
배포 측면에서도 고도의 유연성이 생긴다.
실제로 잘 분리되었다면 시스템에서도 계층과 유스케이스를 교채할 수 있다.
jar, 서비스를 추가하는것과 같이 단순한 일이 된다.
중복
진짜 중복 ,거짓된 중복, 우발적 중복
결합 분리 모드 ( 다시 )
소스 수준 부리모드 : 소스코드 모듈사이의 의존성을 제거한다. (모노리틱 구조)
배포 수준 분리 모드 : jar, dll 등으로 분리하는것
서비스 수준 분리모드 : 네트워크 통신으로 소통하게 하는것 ( MSA, 마이크로 서비스 아키텍처 )
어떤것을 겷정하는 것이 초기에는 어렵지만 이후에는 많은 것을 분리해야할 수 있다.
초기에는 컴포넌트 소스코드 수준에서 분리된다.
좋은 아키텍처는 결합 분리 모드를 선택사항으로 남겨두어서 배포 규모에 따라 가장 적합한 모드를 선택해 사용할 수 있게 한다.
17장 : 선 긋기
실패 사례 : 여러개의 서비스 팜을 생성하게 되면서 개발비용을 엄청 가중시킨 사례가 있다.
성공 사례 : 일단 선택사항에 대해서는 열어둔다. 필요한 기능을 우선적 개발하고 추가 요구사항에 대해서 변경했다.
특히 데이터베이스를 사용하지 않음으로 관리비 등으로 부터 벗어날 수 있었다.
어떻게 선을 그을까?
화살표의 방향, 선의 방향에 따라 데이터 베이스는 비즈니스 룰의 영향을 받는것이다. ( 비즈니스 룰 -> 데이터 베이스 )
데이터 베이스는 어떠한 것으로도 변경될 수 있다.
입력과 출력
중요하지 않다.
GUI 는 다른 종류의 인터페이스로 얼마든지 교체할 수 있다.
플러그인 아키텍처
결론
소프트웨어 아키텍처에서 경계선을 그리려면 먼저 시스템을 컴포넌트 단위로 분할해야 한다.
일부 컴포넌트는 핵심 업무 규칙에 해당한다. 나머지 컴포넌트는 플러그인으로, 핵심 업무와는 직접적인 관련이 없지만 필수 기능을 포함한다.
그런 다음 컴포넌트 사이의 화살표가 특정 방향, 즉 핵심 업무를 향하도록 이들 컴포넌트의 소스를 배치한다.
이는 의존성 역전 원칙과 안정된 추상화 원칙을 응용한 것임을 눈치챌 수 있어야 한다. 의존성 화살표는 저수준 세부사항에서 고수준의 추상화를 향하도록 배치된다.
18장 : 경계 해부학
경계 횡단 하기
소스코드 의존성 관리
두려운 단일체
저수준 -> 고수준으로 향하는 함수 호출
고수준 -> 저수준 ( 동적 다형성을 사용 )
배포형 컴포넌트
아키텍처의 경계가 물리적으로 드러나는 경우 : 동적 링크 라이브러리
스레드
단일체 ,배포험 컴포넌트 모두 사용가능
로컬 프로세스
고수준 프로세스의 소스 코드가 저수분 프로세스의 이름, 물리주소, 레지스트리 조회 키를 절대로 포함해서는 안 된다.
저수준 프로세스가 고수준 프로세스의 플러그인이 되도록 만드는것이 아키텍처 관점의 목표라는 사실을 기억하자.
서비스
물리적인 형태를 띠는 가장 강력한 경계
함수 호출에 비해 느리다.
결론
대체로 한 시스템 안에서도 통신이 빈번한 로컬 경계와 지연을 중요하게 고려해야 하는 경계가 혼합되어 있음을 의미한다.
19장 : 정책과 수준 (ME)
소프트웨어 시스템 : 정책을 기술한 것
입력을 출력으로 변환하는 정책을 상세하게 기술한 설명서다.
좋은 아키텍처라면 각 컴포넌트를 연결할 때 의존성의 방향이 컴포넌트의 수준을 기반으로 연결되도록 만들어야 한다. 즉, 저수준 컴포넌트가 고수준 컴포넌트에 의존하도록 설계되어야 한다.
수준
입력과 출력까지의 거리
프로그램을 제대로 설계했다면 소스 코드 의존성은 곧 점선처럼 표시되어야 한다.
데이터 흐름과 소스코드 의존성이 항상 같은 방향을 가리키지는 않는 다는 사실이다.
정책을 컴포넌트로 묶는 기준은 정책이 변경되는 사실에 달려 있다.
모든 소스 코드 의존성의 방향이 고수준 정책을 향할 수 있도록 정책을 분리했다면 변경의 영향도를 줄일 수 있다.
20장 : 업무규칙
엔티티
컴퓨터 시스템 내부의 객체로서 핵심 업무 데이터를 기반으로 동작하는 일련의 조그만 핵심 업무 규칙을 구체화한다.
엔티티 객체는 핵심 업무 데이터를 직접 포함하거나 핵심 업무 데이터에 매우 쉽게 접근할 수 있다.
유스케이스
자동화된 시스템이 사용되는 방법을 설명한다.
엔티티 내의 핵심 업무 규칙과는 반대로 유스케이스는 애플리케이션에 특화된 업무 규칙을 설명한다.
엔티티는 자신을 제어하는 유스케이스에 대해 알지 못한다. (DIP)
저수준인 유스케이스는 고수준인 엔티티에 대해 알고있다.
유스케이스는 단일 애플리케이션에 특화되어 있으며 따라서 해당 입력과 출력보다 가깝게 위히하기 떄문에 저수준이다.
하지만 엔티티는 유스케이스에 의존하지 않는다.
결론
업무 규칙은 사용자 인터페이스나 데이터베이스와 같은 저수준의 관심사로 인해 오염되어서는 안 되며, 원래 그대로의 모습으로 남아 있어야 한다.
이상적으로는 업무 규칙을 표현하는 코드는 반드시 시스템의 심장부에 위치해야 하며, 덜 중요한 코드는 이 심장부에 플러그인되어야 한다.
업무 규칙은 시스템에서 가장 독립적이며 가장 많이 재사용할 수 있는 코드여야 한다.
Last updated