일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 영속 자료구조
- 다리를 지나는 트럭
- kubenetes
- 크론 표현식
- 가장 큰 수
- 쿠버네티스
- H-index
- 기능개발
- 커링
- @Setter
- @EnableScheduling
- 해시
- 전화번호 목록
- 코딩 테스트
- @configuration
- 스택/큐
- Java
- 루씬 인 액션
- 프로그래머스
- @Getter
- 정렬
- 완주하지 못한 선수
- 모던 자바 인 액션
- 롬복 어노테이션
- K번째수
- 검색 기능 확장
- 스프링 스케쥴러
- 알고리즘
- 고차원 함수
- @Data
- Today
- Total
Today I Learned
05 아키텍처 (7) 본문
26장. 메인(Main) 컴포넌트
모든 시스템에는 최소 하나의 컴포넌트가 존재한다.
이 컴포넌트가 메인컴포넌트가 되어 나머지 컴포넌트를 생성, 조정 관리한다.
궁극적인 세부사항
메인컴포넌트는 궁극적인 세부사항으로 가장 낮은 수준의 정책이다.
시스템의 초기 진입점이며, 운영체제를 제외한 어떤 것도 메인에 의존하지 않는다.
메인컴포넌트에서 의존성 주입 프레임워크를 이용해 의존성을 주입한다.
메인은 클린 아키텍처에서 가장 바깥 원에 위치하는 저수준의 모듈이다.
고수준의 시스템을 위한 모든 것을 로드한 후, 제어권을 고수준의 시스템에게 넘긴다.
27장. '크고 작은 모든' 서비스들
서비스 아키텍처?
시스템의 아키텍처는 의존성 규칙을 준수하며 고수준의 정책을 저수준의 세부사항으로부터 분리하는 경계에 의해 정의된다.
서비스 그 자체로는 아키텍처를 정의하지 않으며, 프로세스나 플랫폼 경계를 가로지르는 함수 호출에 지나지 않는다.
서비스의 이점?
결합 분리의 오류
시스템을 서비스들로 분리함으로써 서비스 사이의 결합이 확실히 분리된다는 이점이 있다.
그러나 개별 변수 수준에서는 각각 결합이 분리되지만, 프로세스 또는 네트워크 상의 공유자원 때문에 결합될 가능성이 여전히 존재한다.
서비스 사이를 오가는 데이터 레코드에 새로운 필드가 추가된다면 이 필드를 사용하는 모든 서비스가 반드시 변경되어야 한다. 또한 이 필드에 담긴 데이터를 해석하는 방식을 사전에 완벽하게 조율해야 한다.
따라서 서비스들은 이 데이터 레코드에 강하게 결합되고, 서비스들 사이는 서로 간접적으로 결합되어 있다.
개발 및 배포 독립성의 오류
서비스를 사용함에 따라 전담팀이 서비스를 소유하고 운영한다는 이점이 있다.
시스템의 개발, 유지보수, 운영을 비슷한 수의 독립된 팀 단위로 분할할 수 있다고 생각한다.
이러한 개발 및 배포 독립성을 확장해서 대규모 엔터프라이즈 시스템을 독립적으로 개발하고 배포할 수 있다고 여긴다.
하지만 이러한 확장 가능한 시스템에 서비스가 유일한 선택지는 아니며, 모노리틱 시스템이나 컴포넌트 기반 시스템으로도 구축이 가능하다.
또한 '결합 분리의 오류'에 따르면 서비스라고 항상 독립적으로 개발,배포,운영할 수 있는 것은 아니다.
야옹이 문제
택시 통합 시스템을 구축해 소규모 단위의 개발팀이 팀 규모에 맞게 적당한 서비스를 개발, 유지보수하고 운영하고 있었다.
이제 이 시스템에 야옹이를 배달하는 서비스를 추가해야한다. 이 기능을 구현하려면 어디를 변경해야할까? 전부다.
이 서비스들은 모두 결합되어 있어서 독립적으로 개발, 배포, 유지할 수 없다.
횡단 관심사(cross-cutting concern)가 지닌 문제다. 모든 시스템은 서비스 지향이든 아니든 이 문제에 직면하게된다.
객체가 구출하다
컴포넌트 기반 아키텍처는 다형적으로 확장할 수 있는 클래스 집합을 생성해 새로운 기능을 처리하도록 한다.
배차에 특화된 로직 부분은 Rides 컴포넌트로 추출되고, 야옹이에 대한 신규 기능은 Kittens 컴포넌트에 들어갔다.
이 두 컴포넌트는 기존 컴포넌트들에 있는 추상 기반 클래스를 템플릿 메서드나 전략 패턴 등을 이용해서 오버라이드한다.
TaxiUI는 변경해야겠지만 그 외의 것들은 변경할 필요가 없다. 야옹이 기능은 결합이 분리되며, 독립적으로 개발, 배포할 수 있다.
컴포넌트 기반 서비스
서비스에도 이렇게 할 수 있을까?
서비스가 반드시 소규모 단일체여야 할 이유는 없다. 서비스는 SOLID 원칙대로 설계할 수 있으며 컴포넌트 구조를 갖출 수도 있다. 이를 통해 서비스 내의 기존 컴포넌트들을 변경하지 않고도 새로운 컴포넌트를 추가할 수 있다.
서비스들의 존재는 달라진게 없지만, 각 서비스의 내부는 자신만의 컴포넌트 설계로 되어 있어서 파생 클래스를 만드는 방식으로 신규 기능을 추가할 수 있다. 파생 클래스들은 각자의 컴포넌트 내부에 놓인다.
횡단 관심사
아키텍처 경계는 서비스 사이에 있지 않다. 오히려 서비스를 관통하며, 서비스를 컴포넌트 단위로 분할한다.
횡단 관심사를 처리하려면 서비스 내부는 의존성 규칙도 준수하는 컴포넌트 아키텍처로 설계해야 한다.
시스템의 아키텍처를 정의하는 것은 서비스가 아닌, 서비스 내의 위치한 컴포넌트이다.
28장. 테스트 경계
시스템 컴포넌트의 테스트
TDD로 생성한 작은 테스트이든, 대규모 테스트이든 아키텍처 관점에서는 모든 테스트가 동일하다.
테스트는 의존성 규칙을 따르며, 의존성은 항상 테스트 대상이 되는 코드를 향한다.
또한 테스트는 독립적으로 배포 가능하다.
테스트는 시스템 컴포넌트 중에서 가장 고립되어 있지만, 엄연히 시스템 컴포넌트이다.
테스트를 고려한 설계
테스트가 지닌 극단적인 고립성과 테스트가 대체로 배포되지 않는다는 사실이 어울어져, 테스트는 종종 시스템의 설계 범위 밖에 있다고 여겨진다.
하지만 테스트가 시스템의 설계와 잘 통합되지 않으면, 테스트는 깨지기 쉬워지고 시스템은 뻣뻣해져 변경하기 어려워진다.
문제는 결합이다. 시스템 컴포넌트에 생긴 사소한 변경도, 이와 결합된 수많은 테스트를 망가뜨릴 수 있다.
따라서 설계 시에 테스트를 고려해야 한다. 변동성이 큰 GUI로 시스템을 조작하는 테스트 스위트는 깨지기 쉽다.
업무 규칙을 테스트 할 때에는 변동성이 큰 GUI에 의존하지 않아야 한다.
테스트 API
테스트 API는 테스트를 애플리케이션으로부터 분리할 목적으로 사용한다. 단순히 테스트를 UI에서 분리하는 것만이 아닌, 테스트 구조를 애플리케이션 구조로부터 분리하는 것이 목표다.
이러한 API는 보안 제약사항을 무시할 수 있으며, 데이터베이스와 같은 값비싼 자원은 건너뛰고, 시스템을 테스트 가능한 특정 상태로 강제하는 강력한 힘을 지녀야만 한다.
구조적 결합
테스트 API의 역할은 애플리케이션의 구조를 테스트로부터 숨기는 데 있다. 이렇게하면 사용 코드와 테스트를 각각 리팩터링할 수 있다. 시간이 지날수록 테스트는 점점 구체적이고 특화된 형태로 변하며, 상용코드는 점점 추성적이고 범용적인 형태로 변할 것이다.
하지만 구조적 결합이 강하면 이러한 진화과정을 방해할 뿐만 아니라, 상용 코드의 범용성과 유연성이 좋아지지 못하게 막는다.
'클린 아키텍처' 카테고리의 다른 글
05 세부사항 (2) (0) | 2021.09.23 |
---|---|
05 세부사항 (1) (0) | 2021.09.16 |
05 아키텍처 (6) (0) | 2021.09.03 |
05 아키텍처 (5) (0) | 2021.08.27 |
05 아키텍처 (4) (0) | 2021.08.20 |