Skip to Content

Step 04. 품질 속성 — 고통을 재는 자

만화로 보는 요약 — 먼저 읽어보세요

만화로 보는 요약 — 먼저 읽어보세요

품질 속성은 구조를 움직이고, 측정 가능한 시나리오와 우선순위 선택을 통해 피할 수 없는 트레이드오프를 관리한다.

면접 실전 질문: ① 기능 요구사항만으로 구조를 정할 수 없는 이유는? ② 품질 속성 시나리오는 어떻게 쓰는가? ③ 모든 것을 좋게 만들 수 없는 이유는?


이 장의 질문: “좋은 아키텍처”라고 할 때 그 좋음은 무엇으로 재는가? 그리고 왜 모든 아키텍처 결정은 결국 무언가를 포기하는 결정인가?


1. 기능은 아키텍처를 결정하지 않는다

사고 실험 하나. 두 팀이 같은 요구사항 명세서 — “주문을 받고, 결제하고, 정산한다” — 를 받아 시스템을 만들었다. 한 팀은 단일 서버에 레이어드 모놀리스를, 다른 팀은 이벤트로 통신하는 여섯 개의 서비스를 만들었다. 둘 다 명세의 모든 기능을 통과한다. 적어도 명세된 정상 경로에서 두 시스템의 기능은 동일하다. 그런데 구조는 완전히 다르다. (장애가 났을 때의 동작은 다를 것이다 — 그리고 그 차이가 바로 이 장의 주제다.)

이 사실이 말해주는 것: 기능 요구사항은 아키텍처를 결정하지 않는다. 무엇을 하는가(what)가 같아도 구조는 천차만별일 수 있다. 그렇다면 구조를 실제로 결정하는 것은 무엇인가? 두 시스템의 차이는 이런 질문들에서 드러난다 — 트래픽이 10배가 되면? 정산 규칙이 바뀌면 몇 개 모듈을 고쳐야 하나? 결제 서버가 죽으면 주문도 죽나? 신입이 코드를 이해하는 데 며칠 걸리나?

이 질문들의 답을 **품질 속성(quality attributes)**이라 부른다. 성능, 가용성, 변경용이성, 테스트가능성… 영어 접미사를 따서 흔히 “-ility들”이라 부르는 것들이다. Bass·Clements·Kazman의 고전 『Software Architecture in Practice』의 핵심 주장이 바로 이것이다:

아키텍처를 결정하는 것은 기능이 아니라 품질 속성이다. 기능은 어떤 구조 위에서도 구현될 수 있다. 그러나 품질 속성은 구조 그 자체가 허락하거나 금지한다.

그리고 이 책의 프레임과의 연결. 우리는 각 아키텍처를 “이전 방식의 고통”에서 태어난 것으로 설명하기로 했다. 그 “고통”의 정체가 바로 품질 속성의 결핍이다. 레이어드의 고통은 변경용이성과 테스트가능성의 결핍이었고, 모놀리스의 고통은 배포독립성의 결핍이었다. 고통에 이름을 붙일 수 있어야 처방을 평가할 수 있다 — 이 장은 그 이름들의 사전이다.

2. 고통의 사전 — 주요 품질 속성

전부 나열하면 수십 개다(ISO 25010 표준이 하나의 공식 목록을 제공한다). 여기서는 이 책의 여정에서 주인공이 될 일곱을 뽑아, 각각 “결핍되면 어떤 고통인가”로 정의한다.

변경용이성(modifiability) — 요구사항 하나를 반영하는 데 몇 곳을 고쳐야 하는가. 결핍의 증상: 한 줄짜리 정책 변경이 서른 개 파일 수정이 된다. 앞의 두 장(무기들, 의존성)이 통째로 이 속성을 위한 것이었다. Part 2에서: 레이어드의 고통이자, 모든 스타일의 기본 심사 항목.

테스트가능성(testability) — 시스템의 한 조각을 얼마나 싸고 빠르게 검증할 수 있는가. 결핍의 증상: “주문 한도 검증 로직”을 테스트하려면 DB를 띄우고 서버를 부팅해야 한다. 정책을 세부사항에서 분리했다면(DIP) 정책만 떼어 검증할 수 있다. Part 2에서: 헥사고날 아키텍처를 낳은 직접적 동기.

배포독립성(deployability) — 시스템의 일부를 나머지와 무관하게 릴리스할 수 있는가. 결핍의 증상: 정산 모듈 한 줄 고치고 시스템 전체를 재배포하며, 배포 일정을 전 팀이 협의한다. 비교적 최근에야 일급 속성으로 승격된 항목 — 지속적 배포 문화가 이 속성의 몸값을 올렸다. Part 2에서: 마이크로서비스를 낳은 동기.

성능(performance) — 응답은 얼마나 빠르고(지연, latency), 단위 시간에 얼마나 처리하는가(처리량, throughput). 결핍의 증상: 피크 시간에 주문 API가 3초씩 걸린다. 지연과 처리량은 다른 축이다 — 하나를 챙기다 다른 하나를 잃는 일도 흔하다.

확장성(scalability) — 부하가 커질 때 자원을 더해 감당할 수 있는가. 결핍의 증상: 트래픽 2배에 서버를 2배로 늘렸는데 처리량은 그대로다(공유 자원 병목).

가용성(availability) — 시스템이 살아서 응답하는 시간의 비율. “나인(9)“으로 세는 그 숫자다(99.9% = 연간 약 8.8시간 중단). 결핍의 증상: 결제사 점검 시간에 우리 서비스 전체가 함께 멈춘다. Part 2에서: 분산 시스템 장의 주인공 — 일관성과의 트레이드오프(CAP)로.

보안(security) — 허가되지 않은 접근과 변조를 막는가. 결핍의 증상: 어느 날 갑자기 뉴스에 나온다. 다른 속성과 달리 아무도 명시적으로 요구하지 않아도 항상 요구되어 있는 속성이라는 점이 특징이다.

일곱 개 밖에도 이 책에서 계속 만날 이름들이 있다 — 금융 도메인이라면 무결성(정합성 깨진 돈은 장애가 아니라 사고다), 팀 관점에서는 단순성/이해가능성(신입의 온보딩 시간). 목록의 전모보다 중요한 것은 다음 두 절이다: 이 이름들을 측정 가능하게 만드는 법, 그리고 이들이 서로 싸운다는 사실.

3. 형용사는 요구사항이 아니다 — 품질 속성 시나리오

“시스템은 빨라야 한다.” — 이 문장은 요구사항이 아니다. 얼마나? 어떤 조건에서? 무엇이? 검증할 방법이 없는 형용사는 회의실에서 고개를 끄덕이게 할 뿐 설계를 움직이지 못한다.

Bass와 동료들의 처방이 **품질 속성 시나리오(quality attribute scenario)**다. 막연한 형용사를 여섯 조각의 구체적 문장으로 강제하는 틀이다: 자극원 / 자극 / 환경 / 대상 / 응답 / 응답 측정치.

“시스템은 빨라야 한다” → “피크 시간대에(환경) 사용자가(자극원) 주문 생성을 요청하면(자극) 주문 API는(대상) 주문을 접수하고(응답) 99번째 백분위 기준 500ms 안에 응답한다(측정치).”

“장애에 강해야 한다” → “평상 운영 중(환경) 결제 외부사가(자극원) 무응답이 되면(자극) 주문 서비스는(대상) 주문을 ‘결제 대기’로 접수해두고(응답) 결제사 복구 후 5분 내 자동 재처리한다. 주문 접수 자체의 성공률은 유지된다(측정치).”

두 번째 예에서 보이듯, 시나리오를 쓰는 행위 자체가 설계를 시작한다 — “결제사가 죽어도 주문은 받는다”고 쓰는 순간, 결제와 주문 사이에 비동기 경계가 필요하다는 구조적 결론이 따라 나온다. 측정 문장이 화살표 배치를 끌어낸다. 이것이 품질 속성이 “측정 언어”인 이유다: Part 2에서 각 스타일을 평가할 때, 우리는 “좋다/나쁘다”가 아니라 “이 시나리오는 통과하고 저 시나리오는 실패한다”로 말할 것이다.

이름 하나를 더 얹어두자. 시나리오가 요구를 재는 언어라면, 그 응답을 실현하는 수단에도 Bass는 이름을 붙였다 — 전술(tactics). 하트비트·이중화(가용성), 중개자 삽입·캡슐화(변경용이성)처럼, 품질 속성 하나의 응답을 담당하는 재사용 가능한 설계 수단이다. 이 책은 전술을 따로 카탈로그화하지 않는다 — Part 2에서 만날 아키텍처 스타일들이 사실상 특정 전술들의 검증된 조합이라, 스타일을 통해 자연스럽게 만나게 되기 때문이다.

4. 제1법칙 — 모든 것은 트레이드오프다

품질 속성들이 사이좋게 공존한다면 아키텍처는 쉬운 일이다. 현실은 반대다. 속성들은 서로 싸운다. Ford와 Richards는 『Fundamentals of Software Architecture』에서 이것을 소프트웨어 아키텍처 제1법칙으로 선언했다:

“소프트웨어 아키텍처의 모든 것은 트레이드오프다.” 따름정리: 트레이드오프가 안 보인다면, 그것은 없는 게 아니라 아직 못 본 것이다.

고전적인 전선(戰線)들:

  • 성능 vs 변경용이성. 앞 장에서 배운 간접층(인터페이스, 경계)은 공짜가 아니다 — 호출 한 단계, 매핑 한 번, 탐색 난이도 한 칸. 극단의 성능이 필요한 코드는 종종 경계를 무너뜨린 코드다.
  • 가용성 vs 일관성. 분산된 두 노드가 서로 연락이 끊겼을 때, 응답을 계속하면(가용) 데이터가 갈라지고, 멈추면(일관) 서비스가 죽는다. 분산 시스템 장에서 CAP 정리라는 이름으로 정면으로 다룬다.
  • 배포독립성 vs 정합성. 서비스를 쪼개면 각자 배포할 수 있지만, 하나의 트랜잭션이던 것이 여러 개의 “결과적으로 맞춰지는” 단계가 된다. 데이터 장의 주제다.
  • 보안 vs 사용성/성능. 인증 단계 하나, 암호화 한 겹이 모두 마찰이다.
  • 거의 모든 것 vs 단순성. 어떤 속성이든 그것을 구조적으로 보장하는 장치는 시스템을 복잡하게 만든다. 복잡성은 모든 트레이드오프의 공용 화폐다.

여기서 아키텍처 설계의 성격이 드러난다. Ford와 Richards의 표현을 빌리면, 목표는 최선(best)의 아키텍처를 찾는 것이 아니라 “가장 덜 나쁜(least worst)” 아키텍처에 도달하는 것이다. 모든 속성을 최대화하는 답은 존재하지 않으므로, 좋은 아키텍트의 질문은 “무엇을 얻을까”가 아니라 **“무엇을 포기해도 되는가”**다. Step 01의 정의(아키텍처 = 되돌리기 비싼 결정 + 근거)와 합치면 — 그 근거(rationale)의 실제 내용물이 바로 이 교환 명세서다: “우리는 X를 얻기 위해 Y를 지불했다.”

5. 다 가질 수는 없다 — 목록의 다이어트

트레이드오프의 실천적 결론: 챙길 속성의 목록은 짧아야 한다. 모든 -ility를 지원하겠다는 아키텍처는 아무것도 약속하지 않은 것과 같다 — 지원 장치들이 서로를 상쇄하고, 복잡성 청구서만 남는다. Ford와 Richards의 실무 조언은 목록을 가능한 한 적게 — 한 자릿수로 — 추리라는 것이다.

무엇을 남기는가는 도메인이 정한다. 같은 “주문 시스템”이라도:

  • 은행/정산: 무결성 > 가용성. 돈이 맞지 않는 것보다는 잠시 멈추는 게 낫다.
  • SNS 피드: 가용성 > 일관성. 피드가 3초 늦는 건 아무도 모르지만, 앱이 안 열리면 모두가 안다.
  • 초기 스타트업: 변경용이성·배포속도 > 확장성. 아직 없는 트래픽보다 매주 바뀌는 요구사항이 진짜 부하다.

한 가지 함정을 조심하라. 요구사항 문서에 없다고 해서 요구되지 않은 것이 아니다 — 암묵적 속성이다. 아무도 “보안이 필요하다”고 회의에서 말하지 않지만 유출되면 회사가 흔들리고, 아무도 “유지보수 가능해야 한다”고 티켓을 만들지 않지만 2년 뒤 그것이 개발 속도의 전부가 된다. 아키텍트 역할의 상당 부분은 명세서에 적히지 않은 이 속성들을 대변하는 일이다.


6. 흔한 오해 바로잡기

오해 1: “품질 속성 = 비기능 요구사항(NFR), 즉 부차적인 것.” “비기능(non-functional)“이라는 전통 용어 자체가 오해의 근원이다 — “기능이 아닌 것”이라 불리는 순간 우선순위에서 밀린다. 실상은 정반대로, 1절에서 봤듯 구조를 결정하는 쪽은 이들이다. Ford와 Richards가 굳이 “아키텍처 특성(architecture characteristics)“이라는 새 이름을 만든 이유가 이 낙인을 피하기 위해서다.

오해 2: “일단 기능부터 만들고, 품질은 나중에 붙인다.” 속성마다 사후 이식의 난이도가 다르다는 게 정확한 답이다. 성능은 상당 부분 나중에 튜닝된다. 변경용이성과 테스트가능성은 구조 그 자체라서, 사후 이식의 실제 이름은 “재작성”이다. 가용성과 보안은 그 중간이다 — 무상태 설계라면 다중 인스턴스와 로드밸런서로, 인증·암호화는 계층으로 어느 정도 덧댈 수 있지만, 그 덧대기가 싸게 먹히려면 무상태·신뢰 경계라는 구조적 선행 조건이 이미 갖춰져 있어야 한다. 결국 어느 속성이 구조적인지(늦출 수 없는지) 판별하는 것 자체가 첫 장의 “무엇을 먼저 결정해야 하는가” 질문이다.

오해 3: “좋은 아키텍처는 모든 속성이 우수하다.” 제1법칙 위반. 모든 속성이 우수하다는 주장은 트레이드오프를 아직 발견하지 못했다는 자백이다. 좋은 아키텍처는 모든 것이 우수한 것이 아니라 포기한 것이 명시된 것이다.

오해 4: “측정할 수 없는 속성도 목표로 삼을 수 있다.” 측정 불가능한 목표는 설계를 움직이지 못하고, 달성했는지 알 수도 없다. “확장 가능해야 한다”는 소망이고, “블랙프라이데이 10배 트래픽에서 p99 1초 유지”는 요구사항이다. 시나리오로 쓸 수 없다면 아직 요구사항이 아니다.


7. 요약 — 그리고 Part 1을 닫으며

  • 기능은 아키텍처를 결정하지 않는다. 구조를 결정하는 것은 품질 속성이고, 각 아키텍처가 태어난 “고통”의 정체는 품질 속성의 결핍이다.
  • 핵심 속성들: 변경용이성, 테스트가능성, 배포독립성, 성능, 확장성, 가용성, 보안 — 그리고 도메인이 정하는 우선순위(금융이라면 무결성).
  • 형용사는 요구사항이 아니다. 품질 속성 시나리오(자극원·자극·환경·대상·응답·측정치)로 써야 설계를 움직인다.
  • 제1법칙: 모든 것은 트레이드오프다. 목표는 최선이 아니라 “가장 덜 나쁜” 아키텍처이고, 좋은 설계의 근거란 “X를 얻으려 Y를 지불했다”는 교환 명세서다.
  • 목록은 짧게(한 자릿수), 암묵적 속성(보안, 유지보수성)은 아키텍트가 대변한다.

이로써 Part 1의 도구 상자가 완성됐다. 정의(아키텍처 = 되돌리기 비싼 결정과 그 근거), 전략(변경의 파급을 가두라), 기하학(화살표의 방향을 통제하라 — 경계, DIP), 그리고 이제 측정 언어(품질 속성 시나리오와 트레이드오프). 네 개의 렌즈를 전부 손에 쥐었다. 예고 하나 — 이 측정 언어의 종착지는 이 책 후반의 진화적 아키텍처 장이다: 품질 속성 시나리오를 자동 실행되는 검사로 만든 것이 거기서 만날 **적합도 함수(fitness function)**다. 측정 언어는 결국 자동화된 방어선이 된다.

다음 장 예고: 이제 역사가 시작된다. Part 2의 첫 장은 아키텍처가 없는 곳 — 구조가 부재할 때 소프트웨어가 자연히 도달하는 상태, Big Ball of Mud — 에서 출발한다. 미리 도발 하나: 그 논문의 요지는 “진흙공은 나쁘다”가 아니다. **“진흙공은 계속 이긴다, 왜인가?”**다.


원전

연도문헌이 장에서의 역할
1998/2021Bass, Clements & Kazman, Software Architecture in Practice (초판/4판)품질 속성 중심 설계론, 품질 속성 시나리오 6요소
2011ISO/IEC 25010품질 특성의 표준 분류 체계
2020Ford & Richards, Fundamentals of Software Architecture제1법칙(모든 것은 트레이드오프), “아키텍처 특성” 용어, least-worst, 목록 다이어트
Last updated on