-
Notifications
You must be signed in to change notification settings - Fork 0
Description
CHAPTER 1 '베스트 프랙티스'가 없다면?
아키텍트는 조직이 처한 상황과 환경에 대해 큰 그림을 그리는 사람들이므로 거의 대부분 문제에 독특한 어려움이 도사리고 있습니다.
누군가 지금 바로 이 상황과 정확히 똑같은 경험을 한 사람이 자기 블로그나 스택 오버플로에 글을 쓸 확률이 얼마나 될까요?
모든 문제가 하나하나 새로운 도전을 요하기에 어떻게든 문제를 해결하려는 중대한 의사 결정의 양편에 치우친 수많은 트레이드오프를 냉정하게 판단하고 평가할 때 아키텍트의 진가가 드러납니다.
아키텍트가 만들어낼 수 있는 최고의 설계는 나쁜 것 중에서 제일 나은 트레이드오프의 조합인 경우가 많습니다.
어느 한 가지 아키텍처 특성만 우월한 게 아니라, 다른 경쟁 아키텍처 특성도 균형이 다 잘 맞아야 프로젝트를 성공으로 이끌 수 있습니다.
1.1 왜 '하드 파트' 인가?
첫째, 어려움입니다.
아키텍트는 이전에 그 누구도 경험해보지 못한 난제에 끊임없이 직면해 의사 결정을 내리는, 대인 관계 및 정치적 환경에 시달리면서도 장기적인 영향을 미칠 만한 갖가지 기술 결정을 내리는 사람들입니다.
둘째, 단단함입니다.
아키텍트는 아키텍처와 설계를 구분하는데, 아키텍처는 구조에 관한 것이라 쉽게 달라지지 않지만 설계는 비교적 쉽게 변경됩니다.
1.2 소프트웨어 아키텍처에 관한 영원불변의 조언
소프트웨어 개발 생태계는 전혀 예상치 못했던 방향으로 확장하고 진화합니다.
새로운 기능이 다른 기능으로 이어지고 없던 기능이 불쑥 튀어나오기도 합니다.
시간이 흐르면서 생태계는 한 번에 하나씩 스스로를 완전히 대체합니다.
그래서 기술이나 상세 구현에 집중하는 대신, 아키텍트가 어떻게 의사 결정을 내리는지, 새로운 상황에 처했을 때 트레이드오프를 어떻게 객관적으로 평가할 것인지에 집중합니다.
1.3 아키텍처에서 데이터의 중요성
데이터는 소중한 것입니다. 데이터는 시스템 자체보다 더 오래갈 테니까요. - 팀 버너스-리Tim Berners-Lee
아키텍트와 DBA는 모놀리스 시스템을 분해하는 것과 같은 아키텍처의 큰 변화가 일어나도 비즈니스 데이터가 온전히 살아남아 가치를 창출할 수 있도록 만들어야 합니다.
여기서는 운영 데이터와 분석 데이터를 명확하게 구분하고 각각에 미치는 영향을 자세히 다룹니다.
운영 데이터
운영 데이터는 판매, 거래성 데이터, 재고 등 비즈니스 활동에 쓰이는 데이터입니다.
운영 데이터는 일반적으로 데이터베이스에서 데이터를 삽입, 수정, 삭제하는 OLTP(Online Transactional Processing) 성격의 데이터입니다.
분석 데이터
분석 데이터는 예측, 트렌드 분석, 기타 BI 용도로 데이터 과학자와 비즈니스 분석가가 사용하는 데이터입니다.
이 데이터는 장기적인 전략 수립과 의사 결정에 중요하게 활용됩니다.
1.4 아키텍처 결정 레코드
아키텍처 결정을 가장 효과적으로 문서화하는 방법은 ADR(Architecture Decision Records)을 활용하는 것입니다.
ADR은 아키텍처 결정이 기록된 짧은 텍스트로 작성합니다.
ADR의 포맷은 다음과 같습니다.
- Context: ADR이 다루는 문제를 간략히 기술하고 문제를 해결할 수 있는 대안을 열거한다.
- Decision: 확정된 아키텍처 결정과 결정하게 된 사유를 자세히 밝힌다.
- Consequence: 이 아키텍처 결정이 적용되면 어떤 결과가 발생하는지, 어떤 트레이드오프를 고려해야 하는지 기술한다.
1.5 아키텍처 피트니스 함수
아키텍트가 컴포넌트 관계를 파악해서 설계를 구체화한 다음에 다른 사름이 그렇게 설계한 대로 구현하도록 만들려면 어떻게 해야 할까요?
아키텍트는 자신이 정의한 설계 원칙이 정말 실현되는지 어떻게 확신할 수 있을까요?
이런 질문은 소프트웨어 개발에서 하나 이상의 부분을 조직적으로 관리/감독하는 아키텍처 거버넌스에 해당합니다.
여기서는 아키텍처의 구조를 다루므로 피트니스 함수로 설계와 품질 원칙을 자동화하는 방법을 비중있게 다룹니다.
1.5.1 피트니스 함수 사용하기
2017년 < Building Evolution Architectures > 에서 아키텍처 피트니스 함수라는 개념을
'어떤 아키텍처 특성이나 그것들을 조합한 아키텍처 특성의 무결성을 객관적으로 평가하는 임의의 매커니즘'이라고 정의했습니다.
(any mechanism that performs an objective integrity assessment of some architecture characteristic or combination of architecture characteristics)
임의의 메커니즘(any mechanism)
성능이나 확장성 같은 운영 아키텍처 특성은 아키텍처 구조를 테스트하는 전용 테스트 라이브러리로 평가합니다.
신뢰성과 복원성은 카오스 엔지니어링 프레임워크를 활용합니다.
객관적인 무결성 평가(Objective integrity assessment)
테스트, 모니터, 다른 피트니스 함수로 측정 가능한 객체의 값을 제공하는 방식이어야 합니다.
그 자체로 객관적으로 측정하기 어렵지만 다른 가능한 값들을 조합해서 파악할 수 있는 복합적인 아키텍처 특성도 잘 관찰해야 합니다.
(예: 민첩성은 다른 측정 가능한 특성인 배포성, 시험성, 배포 주기를 통해 식별)
만약 아키텍처 특성을 측정할 방법이 없다면 정의 자체가 모호하다는 증거입니다.
어떤 아키텍처 특성이나 그것들을 조합한 아키텍처 특성(Some architecture characteristic or combination of architecture characteristics)
피트니스 함수의 범위는 다음 두 가지로 분류됩니다.
- 원자적atomic: 하나의 아키텍처 특성만 처리
- 전체적holistic: 여러 아키텍처 특성이 조합 => 전체적 피트니스 함수로 확인
아키텍트는 아키텍처 특성의 예기치 않은 변화에 대비하기 위해 피트니스 함수를 구현합니다.
예로 탄력성은 폭증하는 유저 수를 감당하는 애플리케이션의 능력입니다.
아키텍트는 도메인을 속속들이 다 알 필요는 없지만 탄력성은 구조의 문제이므로 피트니스 함수의 범주에 속합니다.
그림 1-1은 아키텍트라면 누구나 피하고 싶은 유해한 안티패턴입니다.
Figure 1-1. Cyclic dependencies between components
코드 리뷰는 개발 주기상 너무 늦게 시작되므로 효과가 없습니다.
이 문제는 예제 1-1과 같은 피트니스 함수를 작성해서 컴포넌트 순환 참조를 방지하면 해결할 수 있습니다.
Example 1-1. Fitness function to detect component cycles
public class CycleTest {
private JDepend jdepend;
@BeforeEach
void init() {
jdepend = new JDepend();
jdepend.addDirectory("/path/to/project/persistence/classes");
jdepend.addDirectory("/path/to/project/web/classes");
jdepend.addDirectory("/path/to/project/thirdpartyjars");
}
@Test
void testAllPackages() {
Collection packages = jdepend.analyze();
assertEquals("Cycles exist", false, jdepend.containsCycles());
}
}JDepend라는 메트릭 도구로 패키지 간 디펜던시를 확인하는 코드입니다.
JDepend는 자바 패키지의 구조를 파악해서 순환 참조가 하나라도 발견되면 테스트를 실패 처리합니다.
이런 미시적인 것 외에 거시적인 구조를 검증해야 할 경우도 있습니다.
그림 1-2와 같은 레이어드 아키텍처를 설계할 때, 아키텍트는 관심사를 분리하기 위해 레이어를 나눕니다.
Figure 1-2. Traditional layered architecture
아키텍트가 이런 아키텍처를 설계한 타당한 이유를 그것을 구현하는 사람들이 임의로 침해하도록 내버려두는 건 장기적으로 볼 때 아키텍처의 건강을 해칩니다.
ArcUnit을 이용해 예제 1-2와 같은 피트니스 함수를 작성해 문제를 해결할 수 있습니다.
Example 1-2. ArchUnit fitness function to govern layers
layeredArchitecture()
.layer("Controller").definedBy("..controller..")
.layer("Service").definedBy("..service..")
.layer("Persistence").definedBy("..persistence..")
.whereLayer("Controller").mayNotBeAccessedByAnyLayer()
.whereLayer("Service").mayOnlyBeAccessedByLayers("Controller")
.whereLayer("Persistence").mayOnlyBeAccessedByLayers("Service")아키텍트는 다이어그램과 그 밖의 정보 아티팩트 외부에서도 아키텍처 원칙을 정립하고 그것이 잘 지켜지는지 지속적으로 확인할 수 있습니다.
.NET에서도 NetArchTest라는 도구가 있습니다.
Metadata
Metadata
Assignees
Labels
Projects
Status