소프트웨어 아키텍처는 단순히 기능(FR, Functional Requirements)을 구현하는 것이 아니라, 다양한 품질 속성(QA, Quality Attributes)을 만족시키고, 제약 조건을 준수하는 설계 결정을 포함함. 이 때 핵심 역할을 하는 요소가 Architectural Driver이며, 그 요구를 만족시키기 위해 Tactic을 사용하고, 여러 설계 결정이 뒤따름.
1. Architectural Driver (AD)
소프트웨어 아키텍처 설계에 큰 영향을 주는 요구 사항으로, 다음과 같은 구성 요소로 나뉨:
1.1 Primary Functionality
- 일반적으로 FR은 구조 자체에는 큰 영향을 주지 않음
- 구조와는 독립적(independent of structure)
- 하지만, 약 전체 FR 중 약 10%에 해당하는 Primary Functionality
즉, 기술적으로 어렵거나, 중요한 비즈니스 골과 관련되어있는 요구 사항은 전체 구조에 큰 영향을 줄 수도 있음
1.2 Constraints
- 사용 가능한 기술, 표준, 정책, 시간, 예산 등의 제약 사항
- 아키텍처 설계 시 반드시 준수해야 하며, 선택의 폭을 제한함
1.3 Quality Attributes
- 아키텍처에 매우 큰 영향을 미침
- 설계 초기 단계부터 고려되어야 함
- 다양한 품질 속성 간에는 Trade-off 관계가 있음
- 구체적인 측정 지표(Response Measure)가 존재해야 함
- 종류
- General Quality Attribute Scenarios: 모든 시스템에 적용 가능한 일반적인 시나리오
- Concrete Quality Attribute Scenarios: 특정 시스템에 맞게 작성된 구체적인 시나리오
- QA Design Decisions
- 품질 속성 요구사항을 충족시키기 위해 이루어지는 설계 결정들로, 시스템의 구조와 동작을 결정짓는 핵심 요소임.
| 설계 항목 | 설명 |
|---|
| Allocation of responsibilities | 각 컴포넌트가 어떤 책임을 가질지 결정 |
| Coordination model | 컴포넌트 간 상호작용(통신/동기화 등)을 어떻게 처리할지 |
| Data model | 시스템에서 어떤 데이터를 유지할지, 어떻게 표현하고 접근할지 결정 |
| Management of resources | CPU, 메모리, 스레드 등의 자원을 누가/어떻게 관리할지 |
| Mapping among architectural elements | 논리적 요소 간의 연결 방식 및 흐름 결정 |
| Binding time decisions | 특정 결정이 시스템에 언제 적용될지를 결정 (예: 컴파일 시, 런타임 시 등) |
| Choice of technology | 사용할 기술 스택, 프레임워크, 언어 등을 선택 |
1.4 Design Goal
AD를 통해 설계에서 달성하고자 하는 목적
1.5 Architectural Concern
설계 목적 달성을 위한 고려사항
2. Tactics
품질 속성(Quality Attribute) 시나리오를 만족시키기 위한 솔루션
- 단일 QA를 만족시키기 위한 설계 기법
- 다른 QA와의 Trade-off가 존재함
2.1 Availability Tactics
시스템이 고장 없이 지속적으로 동작 가능한 상태를 유지하기 위한 기법
Fault Detection
- Ping/Echo: 한 컴포넌트가 다른 컴포넌트에 ping을 보내고, 일정 시간 안에 echo를 받아 생존 여부 확인
- Heartbeat: 컴포넌트가 주기적으로 생존 신호(heartbeat)를 보내고, 시스템 모니터가 수신 여부를 감시
- Time Stamp: 분산 시스템에서 메시지나 이벤트의 시간 순서를 확인하여 이상 감지
- Sanity Checking: 연산 결과나 동작이 사전에 정의된 정상 범위 내에 있는지 검사
- Condition Monitoring: 시스템의 상태를 실시간, 주기적, 원격 또는 예측 방식으로 모니터링하여 이상 징후 감지
- Voting: 중복된 컴포넌트들의 결과를 투표하여 비정상 출력을 제거
- Exception Detection: 시스템 실행 중 예외 상황(예: 0으로 나누기, 응답 지연 등)을 감지하여 비정상 흐름 식별
- Self-test: 컴포넌트나 서브시스템이 자체 테스트 루틴을 실행하여 스스로의 정상 작동 여부 확인
Fault Recovery - Preparation & Repair
- Active Redundancy (Hot spare): 주 구성요소와 예비 구성요소가 동시에 동작하며, 오류 발생 시 즉시 전환됨
- Passive Redundancy (Warm spare): 예비 구성요소가 주기적으로 상태를 업데이트받으며, 오류 시 빠르게 활성화됨
- Spare (Cold Spare): 예비 구성요소가 완전히 비활성 상태로 있다가, 오류 발생 후 수동으로 초기화 및 가동
- Exception Handling: 예외 상황에 대해 적절한 처리를 수행하여 시스템을 정상 상태로 회복
- Rollback: 오류 발생 시 저장된 체크포인트로 되돌아가 이전 정상 상태로 복구
- Software Upgrade: 실행 중에도 기능 추가 및 버그 수정을 무중단으로 적용 (ISSU 등 활용)
- Retry: 일시적인 오류 발생 시, 같은 동작을 제한된 횟수 내에서 다시 시도
- Ignore Faulty Behavior: 신뢰할 수 없는 입력이나 메시지를 무시하고 시스템 동작을 유지
- Degradation: 비핵심 기능을 줄이거나 비활성화하여 핵심 기능을 유지하며 시스템 가용성 확보
- Reconfiguration: 장애 발생 후 자원 및 책임을 재할당하여 시스템 기능의 최대한 유지
Fault Recovery - Reintroduction
- Shadow Operation: 복구된 컴포넌트를 백그라운드에서 일시적으로 실행하여 정상 작동 여부를 검증한 뒤 주 역할에 재배치
- State Resynchronization: 장애 복구 후 백업 구성요소의 상태를 주 구성요소와 동기화하여 서비스에 재진입 (Active Redundancy and Passive Redundancy tactics의 파트너)
- Escalating Restart: 오류 복구를 위해 점진적으로 재시작 범위를 확장 (스레드 → 메모리 → 전체 프로세스)
- Removal from Service: 고장 가능성이 있는 구성요소를 일시적으로 서비스에서 제외하여 문제 확산 방지
- Predictive Model: 상태 정보를 기반으로 향후 장애를 예측하고 사전에 조치를 취함
- Exception Prevention (Smart Pointer, Wrappers): 예외 발생 자체를 방지하는 설계 패턴 적용 (예: 자동 메모리 해제)
- Increase Competence Set: 컴포넌트를 보다 다양한 예외 상황까지 수용 가능하도록 설계하여 장애 대응 범위 확장
2.2 Interoperability Tactics
이기종 시스템 간 의미 있는 정보 교환을 가능하게 하기 위한 기법
- Syntactic interoperability: 데이터 전달 능력
- Semantic interoperability: 전달된 데이터 해석 능력
Locate
- Discover Service: 디렉토리 서비스를 통해 서비스의 위치를 동적으로 탐색
Manage Interfaces
- Orchestrate: Workflow engine이나 mediate pattern을 통해 복잡한 서비스 호출 순서를 조정
- Tailor Interface: Decorator Pattern ,Adapter Pattern을 통해 인터페이스를 변환하거나 확장하여 호환성 확보
2.3 Modifiability Tactics
변경에 대한 유연성을 확보하고, 변경의 비용과 영향 범위를 최소화하는 기법
- Coupling: 변경 시 영향 전파 여부 → 변경할수록 영향 받는 모듈이 많다 → 낮아야 좋음
- Cohesion: 모듈의 책임이 얼마나 강하게 연관되어 있는지 → 변경하면 내부만 변화가 있고 외부 모듈에 영향이 덜하다 → 높아야 좋음
Module size ↓
- Split Module(SRP): 하나의 모듈을 여러 책임 단위로 나누어 변경 범위를 축소
Cohesion ↑
- Increase Semantic Coherence: 관련 없는 책임을 분리하여 모듈 내부 응집도 향상
Coupling ↓
- Encapsulate: 모듈의 내부 구현을 숨기고 명시적 인터페이스만 노출
- Use Intermediary: 중간자(Pub-Sub, Directory service)를 통해 직접 의존 제거
- Restrict Dependencies: 접근 제한(Layered, Wrapper, Facade)으로 의존 관계 단순화
- Refactor: 중복 책임을 공통 모듈로 분리하여 변경 시 영향을 한 곳으로 집중
- Abstract Common Services: 유사 기능을 일반화된 형태로 추출하여 재사용성 확보
Defer Binidng time of modification
- Defer Binding Time: 변경을 유연하게 적용할 수 있도록 결합 시점을 늦춤
응답 시간, 처리량 등을 만족시키기 위한 성능 최적화 기법
- 주요 지표
- Latency
- Jitter
- Throughput
- Miss rate
Control Resource Demand
- Manage Sampling Rate: 불필요한 고빈도 처리를 줄이기 위해 샘플링 주기를 조정
- Limit Event Response: 이벤트 큐 과부하 방지를 위해 처리 이벤트 수를 제한
- Prioritize Events: 중요도에 따라 이벤트 처리 우선순위를 설정
- Reduce Overhead: 중간 계층 제거, 리소스 정리 등으로 처리 비용 최소화
- Bound Execution Times: 반복 횟수 제한 등으로 최대 실행 시간을 강제로 제한
- Increase Resource Efficiency: 핵심 처리 로직의 알고리즘을 개선하여 자원 효율성 향상
Manage Resources
- Increase Resources: CPU, 메모리, 네트워크 등 물리적 자원을 확충하여 병목 해소
- Introduce Concurrency: 스레드 및 프로세스를 병렬로 분리하여 처리량 향상
- Schedule Resources: 자원이 부족할 때 FIFO, 고정 우선순위, Round-Robin 등으로 효율적 할당
- Maintain Multiple Computations: 동일 계산을 여러 서버에 분산해 부하 분산 및 응답 속도 개선
- Caching: 자주 사용하는 데이터를 빠른 저장소에 보관하여 접근 시간 단축
- Data Replication: 데이터 복제본을 유지하여 병렬 접근 처리 및 부하 분산
2.5 Security Tactics
시스템의 기밀성, 무결성, 가용성을 유지하기 위한 보안 기법
Detect Attacks
- Detect Intrusion: 네트워크 패턴을 분석하여 알려진 공격 서명과 비교해 침입 여부 탐지
- Detect Service Denial: 트래픽 패턴을 분석해 DDoS 등의 서비스 거부 공격 여부 탐지
- Verify Message Integrity: 체크섬 또는 해시값을 통해 메시지 변조 여부 확인
- Detect Message Delay: 비정상적인 지연을 감지해 중간자 공격 가능성 식별
Resist Attacks
- Identify Actors: 입력의 출처를 식별하여 행위 주체를 명확히 함 (ID, IP 등)
- Authenticate Actors: 비밀번호, 인증서 등으로 사용자의 신원을 검증
- Authorize Actors: 인증된 사용자에게 필요한 권한만 부여
- Limit Access (DMZ 등): 방화벽이나 네트워크 구역 분리를 통해 접근 제한
- Limit Exposure: 민감한 자원이나 서비스를 외부에 최소한만 노출
- Separate Entities: 민감한 컴포넌트를 분리 배치하여 공격 범위 축소
- Encrypt Data: 저장 데이터 및 전송 데이터를 암호화하여 무단 노출 방지
- Change Default Settings: 공개된 기본 설정을 변경하여 보안 강화
React to Attacks
- Revoke Access: 공격 감지 시 정상 사용자도 포함해 접근을 제한
- Lock Computer: 반복 실패 시 해당 장치에 대한 접근 차단
- Inform Actors: 관리자 및 관련 사용자에게 공격 발생 사실을 즉시 통보
Recover from Attacks
- Maintain Audit Trail: 공격 분석과 사후 대응을 위한 활동 로그를 체계적으로 저장
- Use Availability Tactics: 서비스 유지를 위해 중복 시스템, 재구성 등 대응 전략 적용
2.6 Testability Tactics
시스템의 테스트 가능성을 높이고 결함을 빠르게 찾기 위한 기법
Control and Observe State
- Specialized Interfaces: 내부 상태를 조회·설정할 수 있는 테스트 전용 인터페이스 제공
- Record/Playback: 입력 및 시스템 상태를 기록하여 동일한 테스트 시나리오를 재현
- Localize State Storage: 테스트 시작 시 원하는 상태를 지정할 수 있도록 상태 저장 위치를 분리
- Abstract Data Sources: 외부 데이터 소스를 추상화해 테스트 데이터로 손쉽게 교체 가능
- Sandbox: 실제 환경에 영향을 주지 않는 격리된 가상 테스트 환경 구성
- Executable Assertions: 사전에 정의된 조건을 코드에 삽입해 자동으로 검증 수행
Limit Complexity
- Limit Structural Complexity: 순환 의존성, 깊은 상속, 과도한 동적 호출 등을 줄여 테스트 용이성 향상
- Limit Nondeterminism: 병행성, 랜덤성 등 비결정적 요소를 제거하거나 통제하여 결과의 재현성 확보
2.7 Usability Tactics
사용자가 시스템을 더 쉽게 이해하고 조작할 수 있도록 돕는 기법
Support User Initiative
- Cancel / Undo / Pause: 사용자 명령을 취소하거나 중단·복구할 수 있도록 제어 권한 제공
- Aggregate: 반복 작업을 묶어 한 번에 처리할 수 있도록 그룹화 기능 제공
Support System Initiative
- Maintain Task/User/System Model: 사용자의 작업, 성향, 시스템 상태를 모델링해 맞춤형 지원 제공
- Modifiability와 연계: UI 관련 변경이 빠르고 안전하게 이루어지도록 구조적으로 설계
3. Tactic과 Architectural Style의 관계
- 아키텍처 스타일은 여러 Tactic의 조합으로 구성됨
- 단일 스타일만으로는 QA를 완벽히 만족할 수 없고, 여러 tactic을 조합해야 함
- e.g.,
Broker 패턴 + 복제 + 로드밸런싱 + 모니터링 + 자원 증설 등
- Tactic 간 Side Effect 및 Trade-off 고려 필요
→ 마치 체스 게임 처럼 한 수 두고 분석하고, 한 수 두고 분석하는 과정이 필요함