개념
이해하려고 읽는 것과 리스크를 찾으려고 읽는 것
설계 문서를 받으면 대개 "이 시스템이 어떻게 동작하는지" 파악하려고 읽는다. 그 읽기는 끝나면 이해가 남지만 테스트 항목은 남지 않는다. 리스크를 찾으려고 읽는 것은 다른 작업이고, 질문의 방향이 반대다.
이해하려고 읽기 리스크를 찾으려고 읽기
────────────────────────────────────────────────────
어떻게 동작하는가 → 어디서 깨지는가
무엇이 연결됐는가 → 그 연결이 끊기면 어떻게 되는가
어떤 기술을 쓰는가 → 그 기술을 누가 다뤄 봤는가
데이터가 어디 있는가 → 두 곳의 데이터가 어긋나면 누가 아는가이 레슨은 아래 세 가지를 순서대로 한다 — 리스크가 몰리는 지점을 찍고, 비기능 리스크를 측정 가능한 시나리오로 만들고, 도출한 리스크를 테스트 수준과 기법에 배정 한다.
경계를 먼저 그어 둔다. 리스크 관리 절차 자체 — 가능성·영향 평가, 우선순위화, 대응 결정, 추적 — 는 모듈 4 레슨 2의 영역이다. 이 레슨은 그 절차에 들어갈 기술 리스크 후보를 아키텍처에서 뽑는 부분 으로 좁힌다. 보안 위협을 체계적으로 뽑는 일은 모듈 50 레슨 1의 STRIDE·공격 트리가 맡으므로 여기서는 참조만 한다.
입력 자료 — 무엇을 받아야 하는가
| 자료 | 여기서 나오는 리스크 |
|---|---|
| 시스템 구성도(컴포넌트·연결) | 경계, 단일 장애점 |
| 시퀀스 다이어그램 | 긴 경로, 순서 의존, 타임아웃 누적 |
| 데이터 흐름·저장 위치 | 정합성, 이중 원본 |
| 배포 토폴로지(인스턴스 수·영역) | 가용성, 롤링 배포 중 거동 |
| 기술 스택과 버전 | 새 기술, 지원 종료 버전 |
| 변경 이력(커밋 집중도) | 변경이 잦은 모듈 |
| 설계 결정 기록(ADR 등) | 결정의 전제와 그 전제가 깨지는 조건 |
일곱 개가 다 있는 팀은 드물다. 없을 때 기다리지 말고 받아내는 방법이 있다 — 개발자 두세 명과 화이트보드 앞에 30분 서서 "요청 하나가 들어와서 응답이 나갈 때까지 지나가는 상자를 그려 달라"고 하는 것이다. 정식 문서보다 정확할 때가 많고, 그리는 과정에서 개발자들끼리 "그거 지금 그렇게 동작 안 해"라는 말이 나온다. 그 순간이 가장 값진 발견이다.
리스크가 몰리는 여섯 지점
구성도를 받으면 전체를 균등하게 보지 않는다. 여섯 지점에 표시를 한다.
| 지점 | 무엇을 찾는가 | 물어볼 질문 |
|---|---|---|
| ① 경계 | 외부 연동, 비동기 큐, 캐시, 서비스 간 호출 | 상대가 느리면? 두 번 오면? 순서가 바뀌면? |
| ② 상태를 가진 곳 | DB, 세션, 파일, 인메모리 캐시·카운터 | 두 곳에 같은 사실이 있는가? 누가 원본인가? |
| ③ 단일 장애점 | 공유 인증, 단일 인스턴스, 공통 라이브러리 | 이것이 죽으면 몇 개 기능이 멈추는가? |
| ④ 새로 도입된 기술 | 최근 추가된 프레임워크·인프라·외부 서비스 | 팀에서 운영해 본 사람이 있는가? |
| ⑤ 변경이 잦은 모듈 | 커밋·수정 빈도가 높은 파일·모듈 | 왜 자주 바뀌는가? 회귀가 나는 곳인가? |
| ⑥ 긴 경로 | 홉이 많은 요청 흐름 | 홉마다 타임아웃·재시도가 어떻게 누적되는가? |
⑤는 데이터로 확인할 수 있어서 특히 유용하다. 변경 빈도가 높은 모듈은 결함 밀도도 높은 경향이 있고, 회귀 시험 범위를 고를 근거가 된다. 저장소에서 바로 뽑을 수 있다.
# 최근 6개월 동안 가장 많이 바뀐 파일 상위 20개
git log --since="6 months ago" --name-only --pretty=format: \
| grep -v '^$' | sort | uniq -c | sort -rn | head -20④는 사람에게 물어야 한다. 기술 자체의 성숙도보다 팀의 경험 유무가 리스크를 만든다. "운영에서 이걸 겪어 본 사람이 있는가"에 아무도 손을 들지 않으면, 그 구성요소는 시험 설계에서 한 단계 더 깊게 본다.
① 경계 — 종류마다 실패 모드가 다르다
경계는 리스크가 가장 많이 몰리는 지점이고, 경계의 종류에 따라 실패 모드가 다르다. 뭉뚱그리면 동기 호출의 실패 모드만 보게 된다.
| 경계 종류 | 특유의 실패 모드 | 시험 조건 |
|---|---|---|
| 동기 호출(HTTP·gRPC) | 지연, 타임아웃, 부분 실패, 재시도 중복 | 응답 지연 주입, 타임아웃 경계 전후 |
| 비동기 큐·이벤트 | 순서 역전, 중복 배달, 적체, 유실, 독약 메시지 | 같은 메시지 2회, 순서 뒤바꿔 투입, 적체 상태 |
| 캐시 | 무효화 누락, 스탬피드, 원본과 불일치 | 원본 변경 후 조회, 만료 동시 다발 요청 |
| 배치·스케줄러 | 중복 실행, 누락 실행, 실행 시간 초과 | 이전 회차 미종료 상태에서 다음 회차 기동 |
| 파일·연계 배치 | 부분 파일, 인코딩, 재전송 | 잘린 파일, 같은 파일 재수신 |
비동기 경계에서 가장 자주 빠지는 시험이 중복 배달과 순서 역전 이다. 대부분의 메시지 시스템이 "적어도 한 번" 배달을 보장하므로 중복은 정상 동작 인데, 소비자 쪽 멱등성이 시험된 적 없는 경우가 흔하다. 레슨 3의 상호운용성 ③층(오류·장애)에서 다룬 목 서버 기법이 여기에 그대로 쓰인다.
비기능 리스크는 품질 속성 시나리오로 구체화한다
"성능이 걱정된다", "장애 시 복구가 안 될 것 같다" 같은 말은 리스크 목록에 올릴 수 없다. 여섯 요소로 쪼개면 시험 항목이 된다.
자극원 누가·무엇이 자극을 만드는가 (사용자 5천 명, 배치, 장애)
자극 무슨 일이 일어나는가 (동시 주문, 노드 1대 중단)
대상 시스템의 어느 부분이 받는가 (주문 API, 결제 큐)
환경 어떤 상태에서 일어나는가 (평시 / 피크 / 축소 운영 중)
응답 시스템이 무엇을 해야 하는가 (요청을 계속 처리, 대기열 전환)
응답 측정 그것을 무엇으로 확인하는가 (p95 `≤ 800ms`, 오류율 `≤ 0.1%`)이 형식은 소프트웨어 아키텍처 평가에서 품질 속성을 다루는 표준적인 방식이고, 레슨 4의 "여섯 칸" 요구 문장과 목적이 같다. 차이는 출발점이 아키텍처의 한 지점 이라는 것이다.
나쁨: "트래픽이 몰릴 때 안정적으로 동작해야 한다"
좋음: "이벤트 오픈 시각에(환경: 피크) 5분간 평시 20배의 조회 요청이(자극원·자극)
상품 조회 API 에 들어올 때(대상), 캐시 만료가 동시에 발생해도
원본 DB 로 넘어가는 요청이 초당 200건을 넘지 않아야 하고(응답),
전체 응답 p95 는 1초 이하를 유지한다(응답 측정)."좋은 예의 문장은 캐시 스탬피드라는 특정 실패 모드 를 가리키고 있다. 여섯 지점을 먼저 찍었기 때문에 이 문장이 나온다. 지점을 안 찍으면 "부하 시험을 한다"에서 멈춘다.
도출한 리스크를 테스트 수준과 기법에 배정한다
리스크 목록만으로는 아무 일도 일어나지 않는다. 각 리스크에 어느 수준에서, 어떤 기법으로, 무엇이 있어야 시험할 수 있는지 를 붙여야 계획에 들어간다.
| 리스크 | 수준 | 기법·방법 | 필요한 것 |
|---|---|---|---|
| 큐 메시지 중복 배달 시 이중 처리 | 통합 | 같은 메시지 재투입, 멱등성 검증 | 큐에 직접 투입할 수단 |
| 결제 연동 타임아웃 후 성공 응답 | 통합 | 목 서버 지연 주입 | 목 서버, 설정 전환 |
| 캐시 무효화 누락 | 통합 | 원본 변경 → 조회 왕복 | 캐시 상태 조회 수단 |
| 캐시 스탬피드 | 시스템 | 만료 동시 다발 부하 | 부하 도구, 캐시 지표 |
| 공유 인증 서비스 중단 | 시스템 | 의존 구성요소 강제 중단 | 격리 가능한 환경 |
| 신규 프레임워크의 커넥션 고갈 | 통합 | 장기 부하, 커넥션 지표 관찰 | 지표 수집 |
| 변경 잦은 정산 모듈 회귀 | 단위·통합 | 결정표 기반 회귀 세트 | 시험 데이터 생성 수단 |
| 배치 이전 회차 미종료 시 중복 실행 | 시스템 | 실행 중 재기동 | 배치 수동 기동 권한 |
배정에는 두 원칙이 있다.
① 잡을 수 있는 가장 싼 수준으로 내린다. 멱등성은 시스템 수준에서 재현하기 어렵지만 통합 수준에서는 메시지 두 번 넣으면 끝난다. 시스템 수준으로 올릴수록 재현 비용과 진단 비용이 함께 오른다.
② "필요한 것" 칸이 준비 리드타임을 드러낸다. 목 서버·격리 환경·배치 기동 권한 같은 항목은 요청해서 받는 데 시간이 걸린다. 이 칸이 비어 있는 리스크는 시험할 수 없는 리스크 이고, 그건 레슨 4의 시험성 요구로 올려야 한다. 아키텍처 리스크 분석의 부산물 중에 가장 실용적인 것이 이 목록이다.
1시간 워크숍 진행 순서
이 분석은 혼자 하기보다 개발자와 함께 하는 편이 훨씬 빠르다. 한 시간 구성이 실무에서 잘 작동한다.
0~10분 구성도를 화이트보드에 그린다 (개발자가 그리고 QA가 질문한다)
10~25분 여섯 지점에 표시한다 — 경계·상태·단일 장애점·새 기술·잦은 변경·긴 경로
25~40분 표시된 지점마다 "여기가 실패하면?" 한 바퀴. 나온 것을 전부 적는다
40~50분 비기능 항목을 품질 속성 시나리오 여섯 요소로 옮긴다
50~60분 수준·기법·필요한 것을 배정한다. 빈 칸은 그대로 남긴다빈 칸을 채우지 말고 남기는 것이 중요하다. 워크숍 자리에서 추측으로 채운 값은 나중에 아무도 신뢰하지 않는다. 빈 칸은 후속 질문 목록이 되고, 그 목록이 개발·인프라와의 다음 대화 의제가 된다.
실무에서 왜 필요한가
시니어 QA 공고에 자주 나오는 "설계 문서 리뷰를 통한 결함 조기 발견"과 "아키텍처 이해 기반 테스트 설계"가 정확히 이 작업이다. 그런데 실제로 설계 리뷰에 들어가 앉아 있기만 하는 경우가 많다. 구조를 따라가는 데는 성공하지만 질문을 만들지 못하기 때문 이고, 여섯 지점 목록이 그 질문을 만들어 준다.
효과가 가장 큰 순간은 개발 착수 전 이다. 이 시점에 나온 리스크는 설계 변경으로 제거할 수 있다. 예를 들어 "큐 소비자에 멱등성이 없다"가 구현 후에 발견되면 결함이지만, 설계 단계에서 나오면 설계 항목이다. 같은 발견의 비용이 자릿수로 다르다.
또 하나의 실질적 산출물은 시험 환경·도구 요청 목록 이다. 배정표의 "필요한 것" 칸을 모으면 목 서버, 큐 직접 투입 수단, 격리 가능한 스테이징, 배치 수동 기동 권한 같은 항목이 나온다. 이 목록을 스프린트 시작 전에 내면 요구사항이 되고, 테스트 직전에 내면 일정 지연 사유가 된다.