Skip to content

13. 요구사항과 설계 — 구현 전에 결정의 근거를 세운다

좋은 코드는 주어진 문제를 정확히 풀 수 있다. 그러나 주어진 문제가 잘못되었거나 성공 조건이 모호하면 정확한 구현도 실패한다. 이 챕터는 이해관계자의 문제에서 검증 가능한 요구사항을 만들고, 예상 변경과 품질 목표를 근거로 모듈·아키텍처 경계를 선택하며, 그 결정을 다시 검토할 수 있게 기록하는 방법을 다룬다.

학습 목표

  • 요구사항·소프트웨어 설계·아키텍처가 답하는 질문과 산출물을 구분한다.
  • 사업 목표에서 검증 가능한 기능 요구사항과 품질 속성 시나리오까지 근거를 추적한다.
  • 예상 변경과 품질 목표를 근거로 모듈·아키텍처 대안을 비교한다.
  • 선택한 대안의 비용과 재검토 조건을 ADR에 기록한다.

배경: 정확한 구현이 실패하는 이유

한 쇼핑몰 팀이 “주문 취소 기능”을 요청받았다고 하자. 개발자는 주문 상태가 PAID이면 CANCELED로 바꾸고 결제 취소 API를 호출하는 기능을 정확하게 구현했다. 테스트도 통과했다. 운영에 배포하자 다음 문제가 드러났다.

  • 물류팀은 출고 지시 이후 취소를 막아야 한다고 생각했다.
  • 고객지원팀은 부분 취소와 상담원 강제 취소가 필요했다.
  • 재무팀은 주문 상태와 환불 원장의 감사 추적을 보존해야 했다.
  • 고객은 버튼을 누른 뒤 2초 안에 결과를 기대했지만 결제사는 수십 초 뒤 응답하기도 했다.

이것은 단순한 코딩 오류가 아니다. “취소”라는 단어 아래 서로 다른 이해관계자의 목표, 규칙, 시간 제약과 실패 의미가 숨어 있었다. 이런 불확실성을 코드에 들어가기 전에 드러내는 일이 요구사항 공학(requirements engineering)이다.

그렇다고 완벽한 요구사항 문서를 만든 뒤 설계를 시작하는 선형 절차가 정답은 아니다. 결제사의 비동기 취소만 지원한다는 설계 제약을 발견하면 “2초 안에 환불 완료”라는 요구를 바꿔야 할 수 있다. 설계가 요구사항의 실현 가능성과 숨은 가정을 드러내고, 그 결과가 다시 요구사항을 정제한다. 세 활동은 다음 피드백 루프로 연결된다.

text
이해관계자의 목표·문제


요구사항 발견·분석 ── 갈등·가정·제약
          │                    ▲
          ▼                    │ 실현 가능성·비용
검증 가능한 명세 ────────┐     │
          │                │     │
          ▼                ▼     │
모듈 설계 ─────────▶ 아키텍처 평가
          │                │
          └──── 증거·결과 ─┘


             결정 기록과 재검토

세 층은 서로 다른 질문에 답한다

요구사항 — 어떤 결과가 필요한가

요구사항은 구현 방법이 아니라 시스템이 제공해야 할 능력, 지켜야 할 제약, 성공을 판별할 관찰 가능한 결과를 다룬다. “Kafka를 사용한다”는 대개 요구사항이 아니라 해결책이다. 반면 “결제사가 30초 동안 응답하지 않아도 접수된 취소 요청을 잃지 않고, 고객에게 2초 안에 접수 상태를 알린다”는 품질과 행위를 함께 검증할 수 있는 요구사항이다.

요구사항은 발견되는 자연 법칙이 아니다. 서로 다른 이해관계자의 목표를 시스템 경계 안에서 조정한 협상된 약속이다. 그래서 출처, 근거, 우선순위와 아직 검증하지 않은 가정을 함께 기록해야 한다.

소프트웨어 설계 — 어떤 결정을 함께 바꿀 것인가

소프트웨어 설계는 책임을 코드 단위에 배치하고 상호작용의 계약을 정한다. 핵심 질문은 “클래스를 몇 개 만들까”가 아니라 다음과 같다.

  • 어떤 지식과 결정이 함께 변하는가?
  • 한 결정의 변경이 어디까지 전파되어야 하는가?
  • 어떤 불변식을 어느 경계가 소유하는가?
  • 소비자가 내부 구현 대신 어떤 계약에 의존해야 하는가?

주문 취소 규칙, 결제사별 API와 감사 원장을 한 모듈에 넣으면 처음에는 단순해 보인다. 하지만 각 규칙이 서로 다른 이유와 속도로 변한다면 작은 변경도 전체를 다시 배포하고 검증하게 된다. 모듈은 파일을 정리하는 상자가 아니라 변경의 폭발 반경을 제한하는 장치다.

아키텍처 — 어떤 결정이 시스템 수준의 품질을 좌우하는가

아키텍처는 가장 큰 상자를 그린 그림과 동의어가 아니다. 변경 비용이 크고 여러 품질 속성에 동시에 영향을 주며 되돌리기 어려운 결정들의 집합이다. 동기 결제 취소를 비동기 메시지로 바꾸면 응답성과 장애 격리를 얻을 수 있지만 즉시 일관성, 운영 복잡성, 중복 처리 문제가 생긴다.

따라서 “마이크로서비스가 좋은가”처럼 맥락 없는 질문에는 답할 수 없다. 먼저 어떤 자극이 어떤 환경에서 들어오고 시스템이 얼마 안에 어떤 반응을 보여야 하는지를 명시해야 한다. 아키텍처는 그 시나리오를 만족시키는 전술과 구조를 선택하고, 선택 사이의 위험과 트레이드오프를 평가하는 활동이다.

결정의 근거 사슬

이 챕터에서 좋은 산출물은 문서의 양이 아니라 다음 사슬이 끊기지 않는 상태다.

단계주문 취소 사례검증 질문
사업 목표취소 실패 문의와 수동 환불 비용을 줄인다누가 어떤 결과를 원하는가?
요구사항결제사 장애 중에도 요청을 잃지 않고 2초 안에 접수를 알린다관찰 가능한 성공 기준인가?
모듈 설계취소 정책과 결제사 연동을 별도 계약 뒤에 둔다예상 변경이 경계 안에 머무는가?
아키텍처취소 요청을 내구성 있게 기록하고 비동기 실행한다품질 시나리오를 만족하며 어떤 비용을 내는가?
결정 기록ADR에 동기 방식과 비교, 중복 처리 위험, 재검토 조건을 남긴다나중에 이유와 유효 조건을 복원할 수 있는가?

추적성(traceability)은 표의 ID를 많이 연결하는 행정 작업이 아니다. 요구가 바뀌었을 때 영향을 받는 설계와 검증을 찾고, 반대로 복잡한 구조가 어떤 요구 때문에 존재하는지 설명하는 능력이다. 어느 요구에도 연결되지 않는 복잡성은 제거 후보이고, 어떤 설계·검증에도 연결되지 않는 요구는 실현되지 않은 약속일 수 있다.

챕터 지도

  1. 요구사항 발견과 분석은 이해관계자, 경계, 목표, 제약과 갈등을 드러낸다.
  2. 요구사항 명세와 변경은 모호한 기대를 기능 요구사항과 측정 가능한 품질 속성 시나리오로 바꾸고 변경 영향을 추적한다.
  3. 모듈 소프트웨어 설계는 정보 은닉과 변경축으로 경계를 선택하고 계약과 의존 방향을 정한다.
  4. 아키텍처 결정과 평가는 품질 속성 전술과 구조 대안을 평가하고 ADR로 결정의 수명 주기를 남긴다.

테스트 전략과 SLO·에러 버짓은 챕터 14, 개발 방법론과 배포 프로세스는 챕터 15에서 심화한다. 여기서는 그 활동들이 사용할 검증 가능한 요구와 결정 근거를 만드는 데 집중한다.

실무 관점: 산출물이 목적이 될 때

요구사항 명세, 다이어그램과 ADR은 의사결정을 돕는 외부 기억장치다. 다음 상태라면 형식은 갖췄어도 목적을 잃었다.

  • 요구사항마다 ID는 있지만 어느 이해관계자의 어떤 문제인지 알 수 없다.
  • 모든 품질 요구가 “빠르게”, “안전하게”, “확장 가능하게”로 끝난다.
  • 모듈이 도메인이나 변경 이유가 아니라 기술 계층 이름으로만 나뉜다.
  • 아키텍처 다이어그램에는 상자가 많지만 각 화살표의 계약과 실패 의미가 없다.
  • ADR이 선택한 기술의 장점만 기록하고 대안·비용·재검토 조건을 생략한다.

문서가 최신인지 묻기 전에 결정을 검증하거나 바꾸는 데 실제로 사용되는지를 묻는다. 사용되지 않는 세부를 계속 기록하는 것보다, 중요한 가정과 경계와 측정 기준을 짧게 유지하는 편이 낫다.

정리

  • 요구사항은 이해관계자의 목표를 시스템이 검증할 수 있는 약속으로 바꾸는 활동이다.
  • 소프트웨어 설계는 변경 가능한 결정을 숨기고 변경 전파를 통제하는 경계를 선택한다.
  • 아키텍처는 시스템 수준의 품질 속성을 좌우하는 비싼 결정을 대안과 함께 평가한다.
  • 세 층은 선형 단계가 아니라 실현 가능성과 증거를 주고받는 피드백 루프다.
  • 좋은 산출물은 요구사항에서 설계·검증·ADR까지 근거를 추적하고 다시 질문할 수 있게 한다.

확인 문제

  1. “주문 취소는 Kafka로 처리한다”는 문장을 요구사항으로 그대로 두면 어떤 설계 문제가 생기는가?
  2. 요구사항, 모듈 설계, 아키텍처는 주문 취소의 느린 결제사 문제에 각각 어떤 질문을 던지는가?
  3. 어느 요구사항에도 연결되지 않는 복잡한 메시지 처리 계층을 발견했다. 바로 삭제하기 전에 확인할 것은 무엇인가?
정답과 해설
  1. 해결책을 문제보다 먼저 고정해 대안 비교를 막는다. 지속성, 응답시간, 장애 격리 같은 실제 요구를 먼저 명시해야 Kafka가 필요한지, 더 단순한 작업 큐나 데이터베이스 상태 전이로 충분한지 평가할 수 있다.
  2. 요구사항은 허용할 지연과 장애 중 기대 반응을 정한다. 모듈 설계는 결제사별 지연·실패 지식을 어디에 숨길지 정한다. 아키텍처는 동기·비동기 구조가 응답성, 일관성, 운영 복잡성에 주는 영향을 평가한다.
  3. 추적 링크가 사라진 것인지, 규제·보안·복구처럼 문서화되지 않은 제약을 구현하는지 확인한다. 근거가 정말 없고 예상되는 미래 요구만으로 존재한다면 제거 후보지만, 먼저 숨은 이해관계자와 운영 계약을 찾아야 한다.

참고 자료