Software Architecture in Practice: 품질 속성의 공학 (QA 시나리오·전술·ATAM)
들어가며
이 글은 Architecture-Essential 시리즈의 2단계입니다. 전체 학습 경로는 Architecture Essential Curriculum에서 확인할 수 있습니다.
1단계 Domain-Driven Design: 도메인 중심 사고에서는 “무엇을 만들 것인가”를 도메인 모델과 Bounded Context로 분해했습니다. 도메인을 잘 나누면 시스템의 기능적 책임이 또렷해집니다. 그런데 현장에서 아키텍처가 무너지는 지점은 대개 기능이 아니라 비기능입니다. “이 기능은 맞는데 응답이 3초 걸린다”, “장애가 나면 복구에 한 시간 걸린다”, “권한 모델을 바꾸려니 코드 절반을 손대야 한다” 같은 문제 말입니다.
이번 단계는 바로 그 비기능 영역을 정면으로 다룹니다. 텍스트는 Len Bass, Paul Clements, Rick Kazman의 Software Architecture in Practice, 4th ed. 입니다. 이 책의 핵심 주장은 단순합니다. 아키텍처는 예술이 아니라 공학이며, 공학이 되려면 품질을 측정할 수 있어야 한다. 막연한 “확장성 좋게”, “안정적으로” 대신, 자극과 응답과 측정값으로 품질을 정량화하고, 그 품질을 달성하는 설계 결정을 카탈로그(전술)로 다루며, 설계의 트레이드오프를 평가(ATAM)하고, 이해관계자별 관점(View)으로 문서화합니다.
이렇게 정량화된 품질 사고는 3단계 Designing Data-Intensive Applications: 분산 데이터 시스템에서 실제 분산 데이터 시스템의 가용성·일관성·지연시간 문제로 곧장 이어집니다. 즉, 2단계는 “품질을 어떻게 설계하고 평가하는가”라는 일반 공학 언어를 익히는 자리입니다.
📌 이 글에서 다루는 내용
🔍 핵심 주제
- 품질 속성 (Quality Attributes): 가용성·성능·보안·수정 가능성 같은 비기능 요구사항을 1차 시민으로 다루는 사고법
- 품질 속성 시나리오 (QA Scenarios): 자극·응답·측정으로 요구사항을 정량적이고 검증 가능하게 기술하는 6요소 템플릿
- 아키텍처 전술 (Tactics): 각 품질 속성을 달성하기 위한 검증된 설계 결정 카탈로그
- 아키텍처 패턴 (Architectural Patterns): Layered·Microservices·Event-Driven 등 패턴과 전술의 관계
- 아키텍처 평가 (ATAM): 트레이드오프·민감점·위험점 분석으로 설계 위험을 조기에 식별하는 방법
- 아키텍처 문서화 (Views & Beyond): 모듈·C&C·할당 뷰로 이해관계자와 소통 가능하게 기록하기
품질 속성: 비기능 요구사항을 1차 시민으로
기능 요구사항은 “시스템이 무엇을 하는가”를 말합니다. 품질 속성(Quality Attribute, QA)은 “그 일을 얼마나 잘 하는가”를 말합니다. 가용성(Availability), 성능(Performance), 보안(Security), 수정 가능성(Modifiability), 테스트 용이성(Testability), 사용성(Usability) 등이 대표적입니다.
이 책의 출발점은 품질 속성이 아키텍처를 결정한다는 통찰입니다. 기능은 대부분 어떤 구조 위에서도 구현할 수 있습니다. 하지만 “초당 5만 건을 99.99% 가용성으로 처리하라”는 요구는 구조 자체를 강제합니다. 따라서 품질 속성은 부차적 비기능 항목이 아니라, 설계 결정을 가장 강하게 끌어당기는 1차 시민(first-class citizen)으로 다뤄야 합니다.
품질 속성을 다룰 때 흔한 실패 패턴은 두 가지입니다.
- 모호함: “시스템은 빨라야 한다” — 무엇이 얼마나 빨라야 하는지 검증 불가능합니다.
- 분류 논쟁: “이건 성능 문제인가 가용성 문제인가” — 라벨 다툼은 가치가 없습니다.
책의 처방은 라벨에 집착하지 말고 시나리오로 구체화하라는 것입니다. 시나리오는 모호함과 분류 논쟁을 동시에 해소합니다.
품질 속성 시나리오: 6요소로 정량화하기
품질 속성 시나리오는 비기능 요구사항을 검증 가능한 문장으로 바꾸는 표준 템플릿입니다. 6개 요소로 구성됩니다.
| 요소 | 영문 | 의미 |
|---|---|---|
| 자극원 | Source | 자극을 만들어내는 주체 (사용자, 외부 시스템, 내부 컴포넌트 등) |
| 자극 | Stimulus | 시스템에 도달하는 사건 (요청 폭주, 노드 다운, 변경 요구 등) |
| 환경 | Environment | 자극이 발생하는 조건 (정상 운영, 과부하, 장애 상태 등) |
| 아티팩트 | Artifact | 자극을 받는 대상 (전체 시스템, 특정 모듈, 데이터 저장소 등) |
| 응답 | Response | 시스템이 보이는 반응 (로그 기록, 페일오버, 거절 등) |
| 응답 측정 | Response Measure | 응답을 정량적으로 판정하는 기준 (시간, 비율, 비용 등) |
핵심은 응답 측정입니다. 측정값이 있어야 “달성했다/못 했다”를 객관적으로 말할 수 있습니다.
다음은 가용성(Availability) 시나리오의 구체적 예시입니다.
[가용성 QA 시나리오]
자극원(Source) : 내부 클러스터의 한 서버 노드
자극(Stimulus) : 노드가 응답 불능 상태로 전환됨 (crash)
환경(Environment) : 정상 운영 중, 평균 트래픽 부하
아티팩트(Artifact) : 결제 처리 서비스
응답(Response) : 헬스체크가 장애를 감지하고, 트래픽을
정상 노드로 자동 페일오버하며, 운영팀에 알림
응답 측정(Response Measure):
- 장애 감지까지 5초 이내
- 자동 복구(페일오버) 완료까지 30초 이내
- 해당 시간 동안 손실 요청 0건 (재시도로 보장)
- 월간 가용성 99.99% 유지
성능(Performance) 시나리오도 같은 골격으로 작성합니다.
[성능 QA 시나리오]
자극원(Source) : 외부 사용자 (모바일 클라이언트)
자극(Stimulus) : 초당 5,000건의 상품 조회 요청 도착
환경(Environment) : 피크 타임(프로모션) 부하 상태
아티팩트(Artifact) : 상품 카탈로그 조회 API
응답(Response) : 요청을 처리하고 응답을 반환
응답 측정(Response Measure):
- p95 응답 지연 200ms 이하
- p99 응답 지연 500ms 이하
- 처리량 5,000 req/s에서 에러율 0.1% 미만
이 두 예시만 봐도, “빠르게/안정적으로”가 얼마나 무력한 표현이었는지 드러납니다. 시나리오는 설계자·테스터·이해관계자 모두가 같은 합격선을 공유하게 만듭니다. 실무에서는 이 시나리오들을 아키텍처 백로그로 모아 우선순위를 매기고, 각 시나리오를 만족시키는 설계 결정을 추적합니다.
아키텍처 전술: 품질을 달성하는 설계 결정 카탈로그
시나리오가 “목표”라면, 전술(Tactic)은 그 목표를 달성하기 위한 검증된 설계 결정 단위입니다. 패턴이 여러 결정을 묶은 큰 구조라면, 전술은 그보다 작은 원자적 결정입니다. 책은 품질 속성별로 전술을 카탈로그화합니다. 대표적인 매핑은 다음과 같습니다.
| 품질 속성 | 전술 범주 | 대표 전술 |
|---|---|---|
| 가용성 (Availability) | 결함 감지 | ping/echo, heartbeat, 예외 감지, 타임아웃 |
| 가용성 (Availability) | 결함 복구 | redundancy(active/passive), 페일오버, rollback, 재시작 |
| 가용성 (Availability) | 결함 예방 | 트랜잭션, 서비스 격리(bulkhead), circuit breaker |
| 수정 가능성 (Modifiability) | 응집/결합 관리 | encapsulation, 모듈 분리, 책임 재할당 |
| 수정 가능성 (Modifiability) | 바인딩 시점 연기 | 지연 바인딩(late binding), 설정 파라미터, 플러그인 |
| 성능 (Performance) | 자원 수요 관리 | 이벤트 비율 제한, 우선순위 부여, 계산량 절감 |
| 성능 (Performance) | 자원 관리 | 병렬 처리, 자원 풀(pool), 캐시(caching), 큐잉 |
| 보안 (Security) | 공격 저항 | 인증·인가, 데이터 암호화, 접근 제한 |
| 보안 (Security) | 공격 탐지·복구 | 침입 탐지, 감사 로그, 상태 복원 |
| 테스트 용이성 (Testability) | 입출력 제어 | 의존성 주입, 기록/재생(record/playback), 인터페이스 분리 |
전술의 가치는 재사용 가능한 어휘라는 데 있습니다. “가용성을 올리자”는 추상적이지만, “결제 서비스에 active/passive redundancy와 circuit breaker를 적용하자”는 구체적이고 토론 가능합니다. 위 가용성 시나리오의 “5초 내 감지 / 30초 내 복구”는 heartbeat(감지) + 자동 페일오버(복구)라는 전술 조합으로 직접 연결됩니다.
다만 모든 전술에는 대가가 따릅니다. 캐시는 성능을 올리지만 일관성과 메모리를 희생합니다. redundancy는 가용성을 올리지만 비용과 복잡도를 늘립니다. 이 상충을 다루는 것이 바로 평가 단계의 역할입니다.
아키텍처 패턴: 전술의 묶음
패턴(Pattern)은 반복되는 설계 문제에 대한 검증된 구조적 해법으로, 여러 전술을 한데 묶은 큰 단위입니다. 패턴은 특정 품질 속성을 본질적으로 촉진하거나 억제합니다.
flowchart TD
P["아키텍처 패턴<br/>선택"]
P --> L["Layered<br/>(계층형)"]
P --> M["Microservices<br/>(마이크로서비스)"]
P --> E["Event-Driven<br/>(이벤트 기반)"]
L --> L1["촉진: 수정 가능성<br/>관심사 분리"]
L --> L2["억제: 성능<br/>계층 통과 비용"]
M --> M1["촉진: 배포 독립성<br/>확장성·격리"]
M --> M2["억제: 운영 복잡도<br/>분산 일관성"]
E --> E1["촉진: 느슨한 결합<br/>비동기 확장성"]
E --> E2["억제: 추적성<br/>흐름 디버깅 난이도"]
- Layered: 책임을 계층으로 나눠 수정 가능성과 이식성을 높입니다. 대신 계층을 가로지르는 호출이 성능 비용을 만듭니다.
- Microservices: 서비스를 독립 배포·확장 단위로 쪼개 가용성과 확장성을 높입니다. 대신 네트워크 호출, 분산 트랜잭션, 운영 복잡도가 따라옵니다.
- Event-Driven: 컴포넌트를 이벤트로 느슨하게 연결해 확장성과 진화 가능성을 높입니다. 대신 전체 흐름 추적과 디버깅이 어려워집니다.
패턴 선택은 곧 어떤 품질을 우선하고 어떤 품질을 양보할지 결정하는 일입니다. 그래서 패턴은 시나리오·전술과 분리해 고를 수 없으며, 늘 트레이드오프와 함께 평가되어야 합니다.
아키텍처 평가(ATAM): 위험을 조기에 드러내기
ATAM(Architecture Tradeoff Analysis Method)은 설계가 품질 속성 요구를 만족하는지, 그리고 그 과정에서 어떤 상충이 발생하는지를 코드 작성 전에 분석하는 평가 방법입니다. 핵심 산출물은 네 가지입니다.
| 산출물 | 영문 | 의미 |
|---|---|---|
| 민감점 | Sensitivity Point | 특정 결정이 하나의 품질 속성에 크게 영향을 주는 지점 |
| 트레이드오프점 | Tradeoff Point | 하나의 결정이 둘 이상의 품질 속성에 동시에, 상반되게 영향을 주는 지점 |
| 위험 | Risk | 품질 목표 달성을 위협하는, 정당화되지 않은 결정 |
| 비위험 | Non-Risk | 근거가 충분해 안전하다고 판단되는 결정 |
예를 들어 결제 서비스에 캐시를 도입한다고 합시다. 캐시 만료 시간(TTL)은 민감점입니다. 짧게 잡으면 일관성이 좋아지고 길게 잡으면 성능이 좋아지므로 성능 시나리오 결과가 이 값에 민감하게 반응합니다. 동시에 이 결정은 성능을 올리고 일관성을 떨어뜨리므로 트레이드오프점이기도 합니다. 만약 “TTL을 10분으로 두지만 금액 데이터에도 적용한다”면, 잘못된 잔액을 보여줄 수 있어 위험이 됩니다.
ATAM의 진짜 가치는 이런 위험을 다이어그램과 토론으로 미리 드러낸다는 데 있습니다. 이해관계자들이 모여 우선순위가 높은 시나리오를 두고 “이 결정은 어떤 품질에 어떻게 작용하는가”를 따지면, 값비싼 재작업이 발생하기 전에 설계 결함이 노출됩니다. 평가 과정은 대략 (1) 품질 속성 유틸리티 트리 작성 → (2) 시나리오 우선순위 부여 → (3) 아키텍처 접근법 분석 → (4) 민감점·트레이드오프·위험 도출 순으로 진행됩니다.
아키텍처 문서화(Views & Beyond): 관점으로 소통하기
아무리 좋은 설계도 전달되지 않으면 소용없습니다. 책은 아키텍처를 단일 그림이 아니라 여러 뷰(View)의 집합으로 기록하라고 말합니다. 뷰는 특정 이해관계자의 관심사에 맞춰 시스템을 투영한 것입니다. 크게 세 갈래로 나뉩니다.
| 뷰 범주 | 영문 | 보여주는 것 | 주요 이해관계자 |
|---|---|---|---|
| 모듈 뷰 | Module View | 코드 단위의 정적 구조, 의존 관계, 책임 | 개발자, 유지보수 담당 |
| 컴포넌트-커넥터 뷰 | C&C View | 런타임 요소와 상호작용(프로세스, 통신) | 성능·가용성 분석가 |
| 할당 뷰 | Allocation View | 소프트웨어가 인프라·팀·파일에 매핑되는 방식 | 운영, 배포, 조직 설계 |
같은 시스템이라도 모듈 뷰는 “수정 가능성”을 논할 때, C&C 뷰는 “성능·가용성”을 논할 때, 할당 뷰는 “배포·운영”을 논할 때 쓰입니다. 즉, 품질 속성마다 자연스럽게 잘 맞는 뷰가 다릅니다. 위 가용성·성능 시나리오를 검증하려면 C&C 뷰가, 수정 가능성 전술(encapsulation, 지연 바인딩)을 보이려면 모듈 뷰가 가장 효과적입니다.
“Beyond”가 가리키는 것은 뷰들을 묶는 정보입니다. 뷰 간 매핑, 설계 근거(rationale), 용어 사전, 변경 이력 같은 것들이 여기 속합니다. 특히 설계 근거는 ATAM에서 도출한 트레이드오프와 위험 판단을 기록하는 자리로, 미래의 유지보수자가 “왜 이렇게 결정했는가”를 추적할 수 있게 해 줍니다.
마무리
이번 단계의 핵심은 한 문장으로 압축됩니다. 아키텍처는 측정 가능한 품질 속성을 중심으로 설계·평가·문서화하는 공학이다. 우리는 비기능 요구를 1차 시민으로 끌어올리고(품질 속성), 그것을 6요소로 정량화하며(QA 시나리오), 검증된 설계 결정으로 달성하고(전술), 그 결정을 묶은 구조를 고르며(패턴), 트레이드오프를 미리 드러내고(ATAM), 관점별로 소통 가능하게 기록(Views & Beyond)했습니다.
이 모든 도구는 추상적인 연습이 아닙니다. 3단계 Designing Data-Intensive Applications: 분산 데이터 시스템에서는 바로 이 품질 속성 언어 — 가용성, 일관성, 지연시간, 확장성 — 를 실제 분산 데이터 시스템의 복제·파티셔닝·합의 문제에 그대로 적용하게 됩니다. 즉, 여기서 익힌 “시나리오로 정량화하고 트레이드오프로 평가한다”는 사고가, 다음 단계에서 다룰 진짜 분산 환경의 어려운 결정들을 정리하는 틀이 됩니다.
다음 학습
- Architecture Essential Curriculum — 전체 학습 경로와 진행 현황 확인
- (다시 보기) 1단계: Domain-Driven Design: 도메인 중심 사고 — 기능적 책임을 도메인으로 분해하기
- (다음 단계) 3단계: Designing Data-Intensive Applications: 분산 데이터 시스템 — 품질 속성을 실제 분산 데이터 시스템에 적용하기