한 줄 정의
아키텍처 특성을 객관적으로 측정하는 방법과, 그 특성이 지켜지도록 자동화된 거버넌스 메커니즘(적합성 함수)을 구축하는 방법을 다룹니다.
쉽게 말하면
“성능 좋게 만들어주세요”라는 요구사항을 받았을 때, “좋은 성능”이 정확히 뭔지 숫자로 정의하고, 그 기준이 깨지면 빌드가 실패하도록 자동화하는 것입니다.
아키텍처 특성을 “감”이 아닌 “측정값”으로 관리하고, 개발자가 실수로 원칙을 위반해도 CI에서 잡아내는 안전장치를 만드는 챕터입니다.
왜 중요한가?
아키텍처 특성은 정의만 해서는 의미가 없습니다. “민첩성”이나 “배포성” 같은 용어는 사람마다 해석이 다르고, 조직마다 정의가 다릅니다. 객관적 측정 기준이 없으면 논의 자체가 공허해집니다.
게다가 아키텍트가 아무리 좋은 원칙을 세워도, 개발자들이 일상 코딩에서 무의식적으로 위반하면 아키텍처는 서서히 무너집니다. 코드 리뷰로 잡을 수도 있지만 주기가 느리고 사람이 일일이 확인하기에는 한계가 있습니다. 적합성 함수를 통해 거버넌스를 자동화하면 이 문제를 구조적으로 해결할 수 있습니다.
핵심 내용
아키텍처 특성의 측정이 어려운 이유
아키텍처 특성을 정의하는 데는 세 가지 근본적인 어려움이 있습니다.
물리학이 아니다
“민첩성(agility)“이나 “배포성(deployability)“같은 용어의 의미가 모호합니다. 같은 업계 사람들이라도 공통의 용어에 대한 관점이 천차만별이고, 서로 다른 맥락에서 비롯된 정당한 차이일 때도 있지만 그냥 우연한 차이일 때도 있습니다.
정의가 너무 다양하다
같은 조직 안에서도 “성능” 같은 특성의 정의가 부서마다 다를 수 있습니다. 개발자, 아키텍트, 운영 팀이 공통된 정의에 합의하지 않으면 논의가 제대로 되지 않습니다.
너무 복합적이다
바람직한 아키텍처 특성 중에는 더 작은 여러 특성이 모여 이루어진 것이 많습니다. 예를 들어 민첩성은 모듈성, 배포성, 테스트성 같은 특성들로 세분화됩니다.
이 세 가지 문제의 해결책은 복합 특성을 하위 특성으로 분해하여 객관적으로 측정 가능한 단위까지 내려가는 것 입니다. 또한 아키텍처에 관한 하나의 보편 언어(ubiquitous language) 를 만들어, 모든 사람이 표준적이고 구체적인 정의를 사용하면 측정이 한결 쉬워집니다.
운영 특성의 측정
성능이나 확장성처럼 직접 측정할 수 있는 항목이 많지만, 같은 항목이라도 팀의 목표에 따라 해석이 달라집니다.
평균의 함정
예를 들어 “응답 시간”을 측정한다고 할 때, “평균” 응답 시간만 보면 1%의 요청이 다른 요청보다 10배 더 오래 걸리는 극단적인 상황을 알아채기 힘듭니다. 트래픽이 충분히 많다면 이런 이상치(outlier)가 눈에 잘 띄지 않으므로, 최대 응답 시간도 함께 측정 해야 합니다.
통계 모델 기반 정의
성숙한 팀은 성능상의 목표를 어떤 구체적인 수치로 정의하지 않습니다. 대신 통계 분석을 기반으로 성능 특성을 정의 합니다. 예를 들어, 동영상 스트리밍 서비스의 확장성을 모니터링한다면 일정 시간 동안 확장성 데이터를 측정해서 하나의 통계 모델을 만들고, 실시간 지표가 예측 모델을 벗어나면 경보를 울리도록 설정합니다.
지표가 모델을 벗어나는 원인은 크게 두 가지입니다. 하나는 모델이 부정확한 것이고(팀이 알고 싶어 하는 좋은 정보), 다른 하나는 실제로 시스템 문제가 생긴 것입니다(팀이 역시 알고 싶어 하는 정보).
성능의 여러 얼굴
성능이라는 아키텍처 특성 중에는 그 정의가 여러 개인 것이 많습니다. 최근에는 최초 콘텐츠 렌더링(first contentful paint) 이나 최초 CPU 유휴 상태(first CPU idle) 같은 성능 예산(performance budget) 지표에 집중하고 있으며, 도구와 목표 등을 비롯한 여러 가지 것이 바뀜에 따라 새로운 측정 대상과 측정 방법이 계속 등장할 것입니다.
웹 페이지 성능 맥락에서는 K-가중치 예산(K-weight budget) 이라는 지표도 있습니다. 이것은 특정 페이지에 포함되는 라이브러리나 프레임워크 크기의 합이 어느 수준을 넘지 않도록 제한하는 것으로, 특히 모바일 기기의 저대역폭 환경에서 한 번에 전송할 수 있는 바이트 양에 한계가 있기 때문에 필요합니다.
구조적 특성의 측정
성능은 객관적으로 측정하기 쉬운 특성이지만, 모듈성 같은 내부 구조적 특성들은 객관적 측정이 쉽지 않습니다. 모듈성은 명시적으로 드러나지 않는 아키텍처 특성의 좋은 예이며, 아직 완벽한 지표는 존재하지 않지만 코드 구조의 몇몇 중요한 측면을 좁은 범위에서 측정할 수 있는 지표와 도구는 존재합니다.
순환 복잡도(Cyclomatic Complexity)
순환 복잡도(Cyclomatic Complexity) 는 1976년에 토마스 매케이브 Sr.가 함수/메서드, 클래스, 애플리케이션 단위에서 코드의 복잡도를 객관적으로 측정하고자 고안한 지표입니다. 흔히 CC 로 표기하며, 코드에 그래프 이론을 적용해서 계산합니다.
특히 실행 경로가 달라지게 만드는 의사결정 지점(decision point) 들이 계산에 중요하게 쓰입니다. 예를 들어 어떤 함수에 조건문이 하나도 없으면 CC = 1이고, 조건문이 하나 있으면 실행 경로가 둘로 갈라지므로 CC = 2가 됩니다.
하나의 함수나 메서드에 대해 순환 복잡도를 계산하는 공식은 다음과 같습니다.
CC = E − N + 2P
- N: 노드(코드 줄 수)
- E: 간선(edge, 가능한 분기의 수)
- P: 연결 요소(connected components)의 수
다른 함수를 호출하지 않는 함수를 위해 단순화한 공식에서는 상수 2가 등장하며, 만일 함수가 다른 함수를 호출한다면 일반적인 공식인 CC = E − N + 2P를 사용해야 합니다.
// 예제 6-1: 순환 복잡도 평가용 예제 코드
public int decision(int c1, int c2) {
if (c1 < 100)
return 0;
else if (c1 + c2 > 500)
return 1;
else
return -1;
}
// CC = 3 (의사결정 지점 3개 - 2 + 2)
순환 복잡도의 적정 기준
업계에서 CC의 일반적인 기준은 다음과 같습니다.
| CC 범위 | 의미 |
|---|---|
| 10 미만 | 흔히 통용되는 “괜찮은” 기준이지만, 사실 이 기준도 너무 높다고 생각할 수 있음 |
| 5 미만 | 코드가 응집력 있고 잘 정리되어 있다고 볼 수 있는 수준 |
| 50 이상 | 심각한 수준. 단언문이 하나도 없다면 테스트 커버리지가 높아도 실제 검사 효과 의문 |
CC가 높은 코드는 복잡성, 모듈성, 테스트성, 배포성 등 코드베이스가 갖추어야 할 거의 모든 주요 특성에 악영향을 끼칩니다. 코드베이스의 복잡성이 점점 증가하는 것을 팀이 방치하고 있으면 결국에는 코드 전체가 복잡성에 압도당하고 맙니다.
자바 생태계의 측정 도구 중 하나인 Crap4j 는 CC와 코드 커버리지(code coverage)를 결합해서 코드의 ‘엉망도(crappiness)‘를 평가합니다. 다만 CC가 50을 넘는다면, 아무리 테스트 커버리지가 높아도 그 코드는 엉망일 수밖에 없습니다.
TDD 같은 엔지니어링 관행은 동일한 문제에 대해서도 평균적으로 더 작고 덜 복잡한 메서드를 작성하는 데 도움이 됩니다. 먼저 간단한 테스트를 작성한 뒤 그 테스트를 통과하는 데 필요한 최소한의 코드를 작성하는 방식은, 작은 단위의 코딩 작업과 잘 정의된 테스트 경계에 집중하므로 자연스럽게 낮은 CC가 만들어집니다.
개발 프로세스 특성의 측정
아키텍처 특성 중에는 소프트웨어 개발 프로세스와 직접 겹치는 것들도 있습니다.
민첩성(agility) 은 자주 요구되는 특성인데, 사실 이것은 테스트성, 배포성 등 개발 프로세스와 관련된 특성들로 이루어진 복합 아키텍처 특성입니다.
테스트성(testability) 은 거의 모든 플랫폼에 존재하는 코드 커버리지도 도구로 측정할 수 있지만, 테스트에 쓰인 단언문(assertion) 자체가 부실하다면 코드의 정확성(correctness)을 확신하기 어렵습니다. 예를 들어, 어떤 코드베이스의 커버리지가 100%를 달성했다고 하더라도 테스트에 단언문이 하나도 없다면 그저 ‘건드리기만’ 할 뿐 실제로 코드가 잘 작동하는지 실제 검사하지는 않는 것입니다.
배포성(deployability) 도 객관적으로 측정할 수 있습니다. 관련한 지표로는 전체 배포 중 성공한 비율, 실제 배포에 걸린 시간, 배포 중에 발견된 문제점(이슈) 수, 버그 수 등이 있습니다. 각 팀은 자신들의 우선순위와 목표를 반영하는, 질적·양적 데이터를 잘 포착할 수 있는 측정 기준들을 확립해 나가야 합니다.
개발 프로세스가 아키텍처 구조에 미치는 영향
민첩성 및 관련 요소들이 소프트웨어 개발 프로세스와 연결되어 있음은 분명하지만, 이런 프로세스가 오히려 아키텍처 구조에 영향을 주는 경우가 많습니다.
예를 들어 배포성의 우선순위를 높게 두면 아키텍트는 아키텍처 단계에서부터 배포성과 테스트성을 중시하는 쪽으로 의사결정을 내리게 되고, 이것이 바로 아키텍처 특성이 구조적 결정으로 이어지는 사례입니다.
소프트웨어 프로젝트의 범위(scope) 내에 있는 그 어떤 요소라도 Ch04 아키텍처 특성의 정의의 세 가지 기준을 충족한다면 아키텍처 특성의 수준으로 격상되며, 아키텍트는 중요한 결정을 내릴 때 그 요소를 반드시 고려해야 합니다.
거버넌스와 적합성 함수
아키텍처 특성의 거버넌스
거버넌스(governance) 는 아키텍트 역할이 책임져야 할 중요한 요소입니다. 거버넌스라는 단어는 조종하다, 이끌다 같은 뜻을 가진 그리스어 ‘kubernan’(조종하다, 이끌다)에서 유래했으며, 개발 과정에서 아키텍트가 영향력을 행사길 원하는 모든 부분을 포함합니다.
소프트웨어 프로젝트에서는 ‘시급함’이 모든 것을 지배할 때가 많습니다. 좋은 예로 모듈성은 매우 중요한 특성이지만, 항상 긴급하게 요구되는 것은 아닙니다. 아키텍트는 아키텍처 거버넌스를 보장할 도구와 기법을 갖출 필요가 있습니다.
소프트웨어 개발 생태계의 역량이 계속 발전해 왔음을 잘 보여주는 예로, XP(eXtreme Programming)에서 비롯된 자동화 열풍은 지속적 통합(Continuous Integration, CI)을 만들어 냈고, CI는 다시 운영의 자동화(요즘은 데브옵스DevOps라고 부름)로 이어졌습니다. 이 일련의 흐름은 마침내 아키텍처 거버넌스로까지 확장되었고, 그 핵심 개념이 바로 적합성 함수 입니다.
적합성 함수(Fitness Function)
적합성 함수 라는 용어는 생물학보다는 진화적 컴퓨팅(evolutionary computing) 분야의 아이디어에서 유래했습니다. 유전 알고리즘(genetic algorithm)에서 더 나은 결과물을 만들어 내도록 유전자 알고리즘을 더 나은 방향으로 유도하는 메커니즘이 필요한데, 그 결과물의 객관적 품질 평가 수치를 제공함으로써 알고리즘을 유도하는 것이 바로 적합성 함수입니다.
진화적 아키텍처에서는 이 개념을 빌려와 아키텍처 적합성 함수 라는 개념을 만들었습니다. 주어진 아키텍처 특성 하나 또는 여러 특성의 조합의 무결성(integrity) 을 객관적으로 평가하는 수단을 제공하는 메커니즘이면 어떤 것이든 아키텍처 적합성 함수가 될 수 있습니다.
적합성 함수가 새로운 도구는 아닙니다. 오히려, 기존의 다양한 도구를 바라보는 새로운 시각을 제공 하는 것입니다. 아키텍처 특성을 검증하는 기법은 특성의 종류만큼이나 다양하며, 사용하는 방식에 따라 카오스 엔지니어링, 지표 측정, 모니터링, 단위 테스트, 라이브러리 같은 기존의 여러 검증 메커니즘과 겹칠 때가 많습니다.
graph TD FF["적합성 함수"] M["지표"] MO["모니터링"] UT["단위 테스트"] CE["카오스 엔지니어링"] ETC["..."] FF --- M FF --- MO FF --- UT FF --- CE FF --- ETC
적합성 함수의 구체적 예시
순환 의존성 검출
모듈성은 대부분의 소프트웨어 아키텍트가 신경 쓰는 암묵적 아키텍처 특성입니다. 모듈성을 제대로 관리하지 않으면 코드베이스의 구조에 해를 입습니다.
이러한 좋은 의도와 반대되는 힘이 작용하는 플랫폼이 많은데, 예를 들어 여러 Java나 .NET용 IDE에서 개발자가 아직 import되지 않은 클래스를 참조하는 코드를 작성하면 IDE가 자동으로 import 문을 추가할지 묻는 대화상자를 띄웁니다. 대부분의 개발자는 자동 import 문 추가 제안을 별생각 없이 받아들이지만, 여러 컴포넌트가 무분별하게 클래스를 임포트하면 모듈성이 심각하게 훼손됩니다.
이것이 바로 순환 의존성(Cyclic Dependency) 안티패턴입니다. 세 컴포넌트가 각자 다른 두 컴포넌트의 일부를 참조하여 의존관계가 순환 형태의 네트워크를 형성하면 모듈성이 망가집니다. 한 컴포넌트만 따로 재사용하고 싶어도 다른 컴포넌트들을 모두 가져와야 하고, 점점 더 ‘진흙잡탕(Big Ball of Mud)’ 안티패턴을 닮아갑니다.
이 문제의 해결책은 순환 의존성을 잡아내는 적합성 함수를 도입하는 것입니다.
// 예제 6-2: 컴포넌트 순환 구조 검출용 적합성 함수
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 라는 측정 도구를 이용해서 패키지 간의 의존성을 검사합니다. 자바의 패키지 구조를 알고 있으며, 만일 순환 참조가 존재하면 테스트가 실패합니다. 아키텍트가 이 테스트를 프로젝트의 지속적 빌드에 포함시키면, 개발자들이 무심코 순환 구조를 만들어 내더라도 빌드에서 자동으로 잡아냅니다.
주 시퀀스 거리(Distance from the Main Sequence) 적합성 함수
Ch03 모듈성에서 다룬 “주 시퀀스 거리”라는 지표도 적합성 함수로 검증할 수 있습니다.
// 예제 6-3: 주 시퀀스 거리 적합성 함수
@Test
void AllPackages() {
double ideal = 0.0;
double tolerance = 0.5; // 허용 가능 오차. 프로젝트마다 다름.
Collection packages = jdepend.analyze();
Iterator iter = packages.iterator();
while (iter.hasNext()) {
JavaPackage p = (JavaPackage)iter.next();
assertEquals("Distance exceeded: " + p.getName(),
ideal, p.distance(), tolerance);
}
}이 코드는 JDepend로 모든 패키지를 훑으면서 각 패키지의 주 시퀀스 거리를 이상적인 거리(0.0)와 비교합니다. 만일 거리의 차이가 허용 가능 오차(0.5)를 넘으면 테스트를 실패로 돌립니다.
ArchUnit을 활용한 계층 거버넌스
적합성 함수에 특화된 도구들의 수준이 최근 몇 년간 눈에 띄게 높아졌습니다. 그 중 하나가 ArchUnit 으로, JUnit을 활용하는 자바용 테스트 프레임워크이며 다양한 사전 정의 거버넌스 규칙들을 단위 테스트 형태로 제공합니다. 모듈성을 다루는 구체적인 테스트를 아키텍트가 직접 정의해서 사용하는 것도 가능합니다.
계층형 아키텍처(layered architecture)를 예로 들면, 아키텍트는 각 계층 사이의 바람직한 관계를 정의한 적합성 함수를 작성하여 계층 간 의존 규칙이 잘 지켜지는지 검증할 수 있습니다.
// 예제 6-4: 계층들의 거버넌스를 위한 ArchUnit 적합성 함수
layeredArchitecture()
.layer("Controller").definedBy("..controller..")
.layer("Service").definedBy("..service..")
.layer("Persistence").definedBy("..persistence..")
.whereLayer("Controller").mayNotBeAccessedByAnyLayer()
.whereLayer("Service").mayOnlyBeAccessedByLayers("Controller")
.whereLayer("Persistence").mayOnlyBeAccessedByLayers("Service")이 코드는 아키텍처 계층들 사이의 바람직한 관계를 정의합니다. 표현 계층(Controller)은 어떤 계층에서도 접근할 수 없고, 서비스 계층은 컨트롤러에서만, 영속성 계층은 서비스에서만 접근할 수 있도록 제한합니다. .NET 환경에도 이와 유사한 도구인 NetArchTest가 있습니다.
이 예제는 아키텍처 특성을 객관적으로 측정하는 한 방법을 보여줄 뿐만 아니라, 아키텍트가 개발자와 밀접하게 협업하는 것이 왜 중요한지도 잘 말해줍니다. 소위 ‘상아탑’에 올라가서는 개발자들이 이해하지도 못할 난해한 적합성 함수를 몰래 만드는 것이 아니라, 오히려 코드베이스의 품질 보장을 위한 자동화된 거버넌스 규칙을 구현하는 데 목적이 있습니다.
팁
아키텍트는 적합성 함수를 도입하기 전에, 개발자들이 그것의 취지를 충분히 이해하도록 해야 합니다.
카오스 엔지니어링(Chaos Engineering)
적합성 함수의 또 다른 예로 넷플릭스의 카오스 몽키(Chaos Monkey) 가 있습니다. 넷플릭스가 운영을 온프레미스에서 AWS 클라우드로 이전하는 과정에서 아키텍트들은 더 이상 운영 환경을 직접 통제할 수 없다는 점을 걱정하게 되었고, 만약 운영 중에 결함이 나타난다면 어떻게 해야 할까 고민하다가 카오스 엔지니어링 이라는 새로운 분야를 만들었습니다.
카오스 몽키는 프로덕션 환경에서 적합성 함수와 유사하게 동작합니다. 이 ‘혼돈의 원숭이’들은 시스템이 얼마나 잘 버티는지 보기 위해 무작위로 오류나 장애를 일으킵니다. AWS 인스턴스 일부에서 지연(latency) 문제가 크게 나타났을 때 담당 팀은 카오스 몽키를 이용해서 의도적으로 높은 지연시간을 시뮬레이션했고, 이 문제가 특히 심각해지자 ‘레이턴시 몽키’라는 별도의 도구도 만들기까지 했습니다. 또한 아마존 데이터센터 전체에 장애를 일으킨 상황을 시뮬레이션하는 ‘카오스 콩(Chaos Kong)‘도 생겼는데, 이 도구 덕분에 넷플릭스는 실제로 데이터센터 장애가 발생해도 서비스를 멈추지 않을 수 있었습니다.
시미언 아미에 속하는 서비스 중 특히 거버넌스와 관련된 것들은 다음과 같습니다.
| 멍키 | 역할 |
|---|---|
| 컨포미티 멍키(Conformity Monkey) | 아키텍트가 정의한 거버넌스 규칙들의 준수 여부를 감시. 각 서비스가 어떤 요정에도 오류 없이 응답해야 한다면 해당 테스트를 컨포미티 멍키에 넣음 |
| 시큐리티 멍키(Security Monkey) | 잘못된 보안 설정 등 잘 알려진 보안 결함을 서비스별로 점검 |
| 재니터 멍키(Janitor Monkey) | 더 이상 아무 서비스도 접근하지 않는 인스턴스를 찾아서 제거. 클라우드에서 서비스 이전 후 이전의 서비스가 ‘고아’로 남아 비용 발생하는 것을 방지 |
카오스 엔지니어링은 아키텍처 디자인에 대해 흥미로운 새로운 관점을 제시합니다. 시스템이 장애를 일으킬 것은 기정사실 이므로, 고장 났을 때 잘 대처할 수 있게 만드는 것이 중요하다는 것입니다. 장애를 예상하고 테스트를 충실하게 수행하면 시스템이 훨씬 견고해집니다.
체크리스트로서의 적합성 함수
적합성 함수도 바로 그런 체크리스트처럼 생각하는 것이 바람직합니다. 적합성 함수는 무거운 거버넌스 도구가 아니라, 아키텍트가 중요한 아키텍처 원칙을 명확히 표현하고 이를 자동으로 검증하는 장치일 뿐입니다.
보안이 취약한 코드를 배포하지 않아야 한다는 점은 개발자도 잘 안다. 하지만 개발자의 실무에서 중요한 사항은 그 밖에도 수십, 수백 가지이며, 보안은 그런 사항들과 우선순위를 두고 경쟁하게 됩니다.
시큐리티 멍키 같은 도구를 이용하면(좀 더 일반적으로는 어떤 형태이든 적합성 함수를 활용한다면) 아키텍트가 중요한 거버넌스 규칙을 아키텍처의 토대에 자연스럽게 녹여 넣을 수 있습니다.
정리
| 측정 유형 | 측정 용이성 | 대표 지표/도구 | 주의점 |
|---|---|---|---|
| 운영 특성 | 비교적 쉬움 | 응답 시간, 처리량, first contentful paint, K-weight budget | 평균의 함정(이상치 누락), 통계 모델 기반 정의 필요 |
| 구조적 특성 | 간접적으로 가능 | 순환 복잡도(CC), 주 시퀀스 거리, Crap4j | 지표만으로 모든 것을 파악할 수 없음. 보조 지표 활용 |
| 프로세스 특성 | 복합 측정 필요 | 배포 성공률, 커버리지, 배포 시간 | 커버리지가 높아도 단언문 품질이 낮으면 무의미 |
| 거버넌스 방식 | 장점 | 단점 |
|---|---|---|
| 코드 리뷰 | 맥락 이해 가능, 유연함 | 느리고, 사람에 의존, 일관성 부족 |
| 적합성 함수(자동화) | 빠르고 일관됨, CI에 통합 가능 | 모든 것을 자동화할 수는 없음, 도구 학습 비용 |
| 카오스 엔지니어링 | 실제 운영 환경에서 검증, 예상치 못한 결함 발견 | 프로덕션 리스크, 성숙한 운영 체계 필요 |
내 생각
- ArchUnit 같은 도구는 특히 팀 규모가 커질수록 위력을 발휘합니다. 신규 입사자가 계층 간 의존 규칙을 몰라도 빌드에서 바로 잡아주기 때문입니다. “문서에 써놨는데 안 읽었네요”가 아니라 “빌드가 깨지니까 자연스럽게 배우게 되는” 구조를 만드는 것이 핵심입니다.
- 순환 복잡도는 PR 리뷰에서 “이 메서드 너무 복잡하지 않나요?”라는 주관적 피드백 대신 CC 수치를 기준으로 객관적 대화를 할 수 있게 해줍니다. SonarQube 같은 도구에 CC 임계값을 설정해두면 코드 품질 게이트로 활용할 수 있습니다.
- 카오스 엔지니어링은 매력적이지만 프로덕션에 바로 적용하기엔 부담이 큽니다. 스테이징 환경에서 먼저 시작하고, 게임데이(GameDay) 형태로 팀이 함께 장애 시나리오를 실험하는 방식이 현실적인 첫 걸음입니다.
관련 개념
출처
- Richards, M. & Ford, N. (2020). Fundamentals of Software Architecture. O’Reilly. Chapter 6.