15장 아키텍처란?
소프트웨어 아키텍트는 최고의 프로그래머이며, 코드와 동떨어져서는 안된다. 동시에,나머지 팀원들이 생산성을 극대화 할 수 있는 설계를 하도록 이끈다.
- 아키텍처의 주된 목적은 시스템의 생명주기를 지원하는 것이다.
- 좋은 아키텍처는 시스템을 쉽게 이해하고, 쉽게 개발하며, 쉽게 유지보수하고, 쉽게 배포하게 해준다.
- 아키텍처의 궁극적인 목표는 시스템의 수명과 관련된 비용은 최소화하고, 프로그래머의 생산성은 최대화하는데 있다.
개발
개발하기 힘든 시스템이라면 수명이 길지도 않고 건강하지도 않을 것이다.
- 시스템 아키텍처는 개발팀이 시스템을 쉽게 개발할 수 있도록 만들어야 한다.배포소프트웨어 시스템이 사용될 수 있으려면 반드시 배포할 수 있어야 한다. 배포 비용이 높을수록 시스템의 유용성은 떨어진다.
- 소프트웨어 아키텍처는 시스템을 단 한 번에 쉽게 배포할 수 있도록 만드는 데 목표를 두어야 한다.
운영
아키텍처가 시스템 운영에 미치는 영향은 개발, 배포, 유지보수에 미치는 영향보다 적다.
- 좋은 소프트웨어 아키텍처는 시스템을 운영하는데 필요한 요구도 알려준다.
- 시스템 아키텍처는 유스케이스, 기능, 시스템의 필수 행위를 일급(first-class) 엔티티로 격상시키고, 이들 요소가 개발자에게 주요 목표로 인식되도록 해야 한다.
- 이를 통해 시스템을 이해하기 쉬워지며, 따라서 개발과 유지보수에 큰 도움이 된다.
유지보수
유지보수는 모든 측면에서 봤을 때 소프트웨어 시스템에서 비용이 가장 많이 든다.
- 가장 큰 비용은 탐사(spelunking)와 이로 인한 위험부담에 있다.
- 탐사: 기존 소프트웨어에 새로운 기능을 추가하거나 결함을 수정할 때, 소프트웨어를 파헤쳐서 어디를 고치는게 최선인지, 그리고 어떤 전략을 쓰는게 최적일지를 결정할 때 드는 비용이다.
- 아키텍처를 신중하게 만들면 이 비용을 크게 줄일 수 있다.
- 컴포넌트 분리 및 안정된 인터페이스를 두어 서로 격리하기
선택사항 열어 두기
소프트웨어를 부드럽게 만들기 위해서는 구조적 가치를 중요하게 여겨야 한다.
- 소프트웨어를 부드럽게 유지하는 방법은 선택사항을 가능한 한 많이, 그리고 가능한 한 오랫동안 열어 두는 것
- 선택사항: 중요하지 않은 세부사항(detail)
- 모든 소프트웨어 시스템은 주요한 두 가지 구성요소로 분해할 수 있다. 정책(policy)과 세부사항이다.
- 정책 요소는 모든 업무 규칙과 업무 절차를 구체화 한다. 정책이란 시스템의 진정한 가치가 살아 있는 곳이다.
- 세부사항은 사람, 외부 시스템, 프로그래머가 정책과 소통할 때 필요한 요소지만, 정책이 가진 행위에는 조금도 영향을 끼치지 않는다. ex) 입출력 장치, 데이터베이스, 웹 시스템, 서버, 프레임워크, 통신 프로토콜 등
- 아키텍트의 목표는 시스템에서 정책을 가장 핵심적인 요소로 식별하고, 동시에 세부사항은 정책에 무관하게 만들 수 있는 형태의 시스템을 구축하는데 있다.
- 따라서 세부사항을 결정하는 일은 미루거나 나중에 할 수 있다.
좋은 아키텍트는 결정되지 않은 사항의 수를 최대화 한다.
장치 독립성
1960년대에 프로그래머는 많은 실수를 저릴렀는데, 대표적인 실수 중 하나는 코드를 입출력 장치와 결합해버린 일이다.
프린터로 인쇄할 일이 생기면, 해당 프린터를 제어하는 입출력 명렁어를 직접 사용해서 코드를 작성했다.
- 이러한 코드는 장치 종속적(device dependent)이다.
왜 이러한 방법이 잘못된 것일까? → 장치를 바꾼다면 이 코드는 못 쓰게 되기 때문 - 오늘날의 운영체제는 입출력 장치를 소프트웨어 함수로 추상화 했고, 해당 함수는 천공카드와 같은 단위 레코드를 처리한다.
물리적 주소 할당
- 시스템에서 고수준의 정책을 물리적 구조로부터 독립시킴으로써 애플리케이션과 하드웨어를 분리할 수 있다.
결론
좋은 아키텍트는 세부사항을 정책으로부터 신중하게 가려내고, 정책이 세부사항과 결합되지 않도록 엄격하게 분리한다.
이를 통해 정책은 세부사항에 관한 어떠한 지식도 갖지 못하게 되며, 어떤 경우에도 세부사항에 의존하지 않게 된다.
좋은 아키텍트는 세부사항에 대한 결정을 가능한 한 오랫동안 미룰 수 있는 방향으로 정책을 설계한다.
16장 독립성
좋은 아키텍처는 다음을 지원해야 한다.
- 시스템의 유스케이스
- 시스템의 운영
- 시스템의 개발
- 시스템의 배포
유스케이스
시스템의 아키텍처는 시스템의 의도를 지원해야 한다는 뜻이다.
- 좋은 아키텍처가 행위를 지원하기 위해 할 수 있는 일 중에서 가장 중요한 사항은 행위를 명확히 하고 외부로 드러내며, 이를 통해 시스템이 지닌 의도를 아키텍처 수준에서 알아볼 수 있게 만드는 것이다.
운영
시스템의 운영 지원 관점에서 볼 때 아키텍처는 더 실질적이며 덜 피상적인 역할을 맡는다.
- 각 컴포넌트를 적절히 격리하여 유지하고 컴포넌트 간 통신 방식을 특정 형태로 제한하지 않는다면, 시간이 지나 운영에 필요한 요구사항이 바뀌더라도 스레드, 프로세스, 서비스로 구성된 기술 스펙트럼 사이를 전환하는 일이 훨씬 쉬어질 것이다.
개발
- 아키텍처는 개발환경을 지원하는 데 있어 핵심적인 역할을 수행한다.
- 콘웨이(Conway)의 법칙이 작용하는 지점이 바로 여기다. 콘웨이의 법칙은 다음과 같다.
시스템을 설계하는 조직이라면 어디든지 그 조직의 의사소통 구조와 동일한 구조의 설계를 만들어 낼 것이다.
- 많은 팀으로 구성된 상황에서 개발을 해야 한다면, 각 팀이 독립적으로 행동하기 편한 아키텍처를 반드시 확보해야 한다.
- 잘 격리되어 독립적으로 개발 가능한 컴포넌트 단위로 시스템 분할
배포
아키텍처는 배포 용이성을 결정하는 데 중요한 역할을 한다.
- 좋은 아키텍처는 즉각적인 배포(immediate deployment)를 목표로 한다.
- 마스터(메인) 컴포넌트는 시스템 전체를 하나로 묶고, 각 컴포넌트를 올바르게 구동하고 통합하고 관리한다.
선택사항 열어놓기
좋은 아키텍처는 선택사항을 열어 둠으로써, 향후 시스템에 변경이 필요할 때 어떤 방향으로든 쉽게 변경할 수 있도록 한다.
계층 결합 분리
아키텍트는 단일 책임 원칙과 공통 폐쇄 원칙을 적용하여, 그 의도의 맥락에 따라서 다른 이유로 변경되는 것들을 분리하고, 동일한 이유로 변경되는 것들을 묶는다.
유스케이스 결합 분리
유스케이스 또한 서로 다른 이유로 변경될 수 있다.
- 유스케이스는 시스템을 분할하는 매우 자연스러운 방법
유스케이스는 시스템의 수평적인 계층을 가로지르도록 자른, 수직으로 좁다란 조각이기도 하다. 각 유스케이스는 UI의 일부, 애플리케이션 특화 업무 규칙이 일부, 애플리케이션 독립적 업무 규칙의 일부, 그리고 데이터베이스 기능의 일부를 사용한다.
- 따라서 우리는 시스템을 수평적 계층으로 분할하면서 동시에 해당 계층을 가로지르는 얇은 수직적인 유스케이스로 시스템을 분할할 수 있다.
결합 분리 모드
유스케이스를 위해 수행하는 그 작업들(결합 분리)은 운영에도 도움이 된다.
- 운영 측면에서 이러한 장점을 살리기 위해선 결합을 분리할 때 적절한 모드를 선택해야 한다.(컴포넌트를 서비스 단계까지 나눌 수 도 있음)
- 실제로 서비스에 기반한 아키텍처를 흔히 서비스 지향 아키텍처(serice-oriented-architecture, SOA)라고 부른다.
- ex) 마이크로 서비스(micro-serice) 등
개발 독립성
컴포넌트가 완전히 분리되면 개발 팀도 분리된다. → 아키텍처는 팀 구조를 뒷받침 한다.
배포 독립성
유스케이스와 계층의 결합이 분리되면 배포 측면에서고 고도의 유연성이 생긴다.
- 실제로 결합을 제대로 분리했다면 운영 중인 시스템에서고 계층과 유스케이스를 교체(hot-swap) 할 수 있다.
- 새로운 유스케이스를 추가하는 일은 시스템의 나머지는 그대로 둔 채 새로운
jar
파일이나 서비스 몇 개를 추가하는 정도로 단순한 일이 된다.
중복
중복에는 진짜 중복과 우발적 중복 이 있다.
- 진짜 중복은 개발자라면 중복을 제거하거나 줄여야 한다.
- 우발적 중복은 진짜 중복이 아니다.(서로 다른 속도와 다른 이유로 변경된다면 중복이 아니다.)
결합 분리 모드(다시)
다시 결합 분리 모드로 돌아가보자.
계층과 유스케이스의 결합을 분리하는 방법은 다양하다. 소스 코드 수준에서 분리, 바이너리 코드(배포)수준에서, 그리고 실행 단위(서비스) 수준에서도 분리할 수 있다.
- 소스 수준 분리 모드: 소스 코드 모듈 사이의 의존성을 제어할 수 있다.
- 모든 컴포넌트가 같은 주소 공간에서 실행되고, 서로 통신할 때 간단한 함수 호출을 사용한다.
- 이러한 구조를 흔히 모노리틱 구조라고 부른다.
- 배포 수준 분리 모드: 배포 가능한 단위(라이브러리, jar 파일, DDL 등)들 사이의 의존성을 제어할 수 있다.
- 서비스 수준 분리 모드: 의존하는 수준을 데이터 구조 단위까지 낮출 수 있다.
- 순전히 네트워크 패킷을 통해서만 통신하도록 만들 수 있다.
- 완전히 독립적이다.(서비스, 마이크로 서비스)
어떤 모드가 사용하기에 가장 좋을까?
- 현 시점 가장 인기 있어보이는 모드는 서비스 수준 분리 모드이다.
좋은 아키텍처는 결합 분리 모드를 선택사항으로 남겨두어 배포 규모에 따라 가장 적합한 모드를 선택해 사용할 수 있게 만들어 준다.
- 좋은 아키텍처는 모노리틱 구조로 시작해 마이크로서비스 수준까지 성장해도 원래 형태로 돌아갈 수 있어햐 한다.
결론
시스템의 결합 분리 모드는 시간이 지나면서 바뀌기 쉬우며, 뛰어난 아키텍트라면 이러한 변경을 예측하여 큰 무리 없이 반영할 수 있도록 만들어야 한다.
'책 > CleanArchitecture' 카테고리의 다른 글
클린 아키텍처 17장, 18장, 19장 리뷰 (0) | 2023.01.15 |
---|---|
클린 아키텍처 12장, 13장, 14장 리뷰 (0) | 2022.12.30 |
클린 아키텍처 8장, 9장, 10장, 11장 리뷰 (0) | 2022.12.28 |
클린 아키텍처 6장, 7장 리뷰 (1) | 2022.12.25 |
클린 아키텍처 1장, 2장, 3장, 4장, 5장 리뷰 (0) | 2022.12.11 |