조지 페어뱅크스의 "Just Enough Software Architecture: A Risk-Driven Approach"[1]은 성공적으로 소프트웨어를 만드는 것이 "가능한 실패를 예상하고 실패할 수 있는 설계를 피하는 것을 의미"한다고 이야기 한다. 그렇기 때문에 실패 리스크를 찾고 이것에 매핑하는 소프트웨어 설계 테크닉을 적용하는 것이라고 한다.

 

책에서 말하는 리스크 주도 모델의 경우는 다음과 같은 단계를 거치면서 반복하는 과정이라고 말한다.

  1. 리스크 식별/우선 순위 지정
  2. 적용할 테크닉 선택/적용
  3. 리스크 감소의 평가

소프트웨어 개발은 설계만으로 끝나는 것이 아니고 구현을 해야 한다. 그러므로 다음과 같은 예의 논리를 바탕으로 진행하는 것을 제안한다.

 

"A, B 그리고 C를 리스크로 식별하고, B는 매우 중요하다. 이를 위한 테크닉 X와 Y를 통해 B의 리스크를 줄일 수 있다고 판단했다. 결과물인 설계를 평가했을 때, B의 리스크가 충분히 완화되어 구현을 계속 했다."

 

리스크란 무엇인가?

책에서 이야기 하는 리스크의 정의는 "인지된 실패 확률*인지된 영향"이라고 정의 한다. 즉, 인지되지 않은 실패 혹률을 리스크로 판단할 수 없고, 실패로 인한 소프트웨어 프로젝트로의 영향도 파악할 수 없다면 리스크는 확인할 수 없는 것이다.

 

리스크의 구분은 크게 엔지니어링 및 프로젝트 관리 리스크로 나눈다. 일반적으로 엔지니어링 리스크는 제품의 분석, 설계 및 구현과 관련된 사항이고, 프로젝트 관리 리스크는 일정, 작업 순서, 팀 규모 등과 관련된 것들이다. 여기서 말하는 리스크는 엔지니어링 리스크와 관련되고 이를 해결하기 위한 엔지니러링 테크닉을 적용하는 것이 일반적이다.

 

리스크의 식별의 경우는 요구 사항에서 하는 것이 일반적이다. [2]에서 설명한 것과 같이 소프트웨어의 요구 사항에서 아키텍처적으로 중요한 요구 사항(Acrhitectural Significant Requirement, ASR)을 추출과 연결 시켜 보면, 추출된 요구 사항(기능적 그리고 비기능적 요구사항/품질 속성)에서 중요한 것을 찾는 것이 기존 방법과 다르게 리스크라는 관점에 중점에 두고 선정하는 것이 차이일 수 있다. 여기서 가장 달성하기 어려운 것을 찾는 것이 방법이라고 할 수있다.

 

개발하는 소프트웨어의 도메인에 따라 주로 발생하는 원형적 리스크(Prototypical Risk)도 있다. 예로는 아래와 같은 것들이 있다.

프로젝트 도메인 원형적인 리스크
정보 기술(IT) 복잡하고 잘 이해되지 않은 문제
실제 문제를 해결하고 있는지 확실하지 않음
잘못된 상용 기성품(COTS) 소프트웨어를 선택
잘 이해되지 않은 기존 소프트웨어와 통합
사람들에게 흩어져 있는 도메인 지식
수정가능성(modifiability)
시스템 성능, 신뢰성, 크기, 보안
동시성(concurrency)
구성(composition)
보안
애플리케이션 규모확장성(scalability)
개발자 생산성/표현성(expressability)

 

적용 테크닉

리스크를 인식하고 나면 리스크를 줄일 수 있을 것으로 예상 되는 테크닉(Techique)을 적용할 수 있다. 조지 페어뱅크스는 기존에 방식에서 지혜를 얻고 있다. 소프트웨어 아키텍처 설계에서 사용되는 전술(Tactics)[3] 혹은 패턴(Pattern)을 예로 들고 있다.

 

이와 같은 테크닉은 수 없이 많을 수 있다. 하지만, 시간과 돈을 낭비하지 않으려면 우선 순위가 지정된 리스크 목록을 가장 잘 줄이는 테크닉을 선택해야 한다. 즉, 최적화 문제로 생각하고 접근해야 한다. 이러하듯, 엔지니어링 리스크를 완전히 제거할 수 없는 이유는 주로 프로젝트 관리 리스크인 비엔지니러링 리스크와 균형르 이루어야 하기 때문이라고 책[1]에서는 이야기한다.

 

이와 같은 제약 뿐 아니라 적용할 테크닉의 선택을 위해서 문제의 종류(답을 찾는 문제/증명 문제), 모델의 종류(분석 모델 및 유추 모델)에 따라 다르다고 한다. 그리고, 설계를 바라 보는 관점이라고 할 수 있는 뷰타입(Viewtype)의 경우는 리스크와 테크닉의 쌍(Pair)에 효과를 다르게 하기 때문에 어떤 것이 적절한지 매칭(matching)을 고려해야 한다고 이야기 한다.

언제 멈추는가?

소프트웨어 아키텍처를 설계에는 중요한 두가지 질문은 "어떤 테크닉을 사용하는가?" 그리고 "얼마나 설계와 아키텍처를 수행하는가?"라고 할 수 있다. 리스크 주도 설계에서는 아주 단순히 답한다면 "충분히 리스크가 줄어 들 때까지 설계한다"가 답일 수 있다.

 

이를 위해서는 설계에 들이는 노력은 "리스크에 상응해야 한다"라고 한다. 저자는 아버지의 집앞에 우편함을 만드는 이야기를 하면서 단순하게 땅을 파고 우편함을 묻기만 하면 될 일을 위해서 측량을 한다거나와 같은 높은 건물 건축에서 사용되복잡한 설계나 리스크를 측정하는 테크닉을 적용할 필요가 없다는 것이다.

 

불완전해 보일 수 있지만, 리스크 모델에서는 리스크가 인식되는 영역만 설계한다는 부분과 리스크 평가가 주관적인 평가라는 부분 또한 언급한다. 이 부분은 단점일 수 있지만, 여전히 장점이기도 하다. 

계획된 설계와 진화적 설계

책[1]에서는 소프트웨어 개발에 사용되는 설계 접근 방식을 계획된 설계(Planned design)과 진화적 설계(Evolutionary design)으로 나눈다. 리스크 주도 설계는 이 두가지 설계 방식에 모두 적용 가능하다고 책에서는 주장한다.

 

진화적 설계의 경우, 주로 애자일 소프트웨어 개발 방식에서 사용하는 방식이다. 시스템이 구현됨에 따라 설계가 확장되기 때문에 지협적이고 파편화된 설계 결정이 여러 문제를 발생 시킨다. 이러한 단점을 해결하는 방법으로 리펙터링(Refactoring), 테스트 주도 설계(Test drivn design), 지속적인 통합(Continous integration)이 제안되어 채영되고 있다. 여전히 아키텍처적 입장에서는 좋은 지침에 제공되고 있지 않다고 지적하고 있다.

 

계획된 설계는 진화적 설계의 반대쪽 끝에 있다고 설명하며, 실재 구현 이전에 설계를 자세하게 작성하는 것이다. 하지만, 이는 지나친 선행 설계(Big Design Up Front BDUF)라고 비판을 받는다. 앞에서도 이야기 한 저자의 아버지 우편함에 대한 예가 주요 내용이라고 볼 수 있다.

 

위의 두 가지는 양쪽 극단이다. 마치 스펙트럼 같은 것일 수 있다. 이 중간에는 최소 계획된 설계(Minimal planned design) 또는 작은 선행 설계(Little Design Up Front LDUF)가 있다. 

 

이러한 접근 방법들은 서로 다른 지지자들이 있다. 또한 책에서는 만병통치약이 없듯이 다른 시스템에서는 다른 방법이 적절하다고 이야기 한다. 또한 둘은 다르고, 장점 또한 다르다. 이케텍처 설계를 한다는 것은 장기적인 관점을 가지고 시스템 전체의 속성을 보장하는 장점을 가진다. 진화적 설계는 앞에서 살펴 보았듯이 리펙터링, TDD 그리고 지속적 통합(CI)의 장점을 활용할 수 있다.

프로세스에 적용하기

리스크 주도 소프트웨어 설계를 여러 프로세스에 적용하기 위해서 몇가지 프로세스의 특징을 우선 아래와 같이 정리하고 있다.

 

프로세스 선행 설계 설계 본질 작업 우선순위 반복 길이
폭포수 분석 및 설계 단계 계획된 설계, 재설계 없음 개방적 개방적
반복적 선택적 계획 또는 진화, 재설계 허용 개방적이고 종종 기능 중심 개방, 보통 1-8
나선 없음 계획 또는 진화 가장 위험한 작업부터 개방적
UP/RUP 선택적, 사전 설계 전반부 배치 계획 또는 진화 가장 위험한 작업 후, 가장 높은 가치 보통 2~6
XP 없음, 일부 반복 제로(Iteration zero) 진화적 설계 가장 높은 고객 가치 우선 보통 2~6

우선 애자일 개발 프로세서인 eXtream Programming(XP)에서는 일반적으로 설계 작업이 없지만 반복 제로(Iteration zero)를 두고 설계 작업을 할 수 있다. 이렇게 반복적인 작업에서 리스크 주도 기반 접근법은 각 단계에서 필요한 만큼 설계 작업을 진행할 수 있다.

 

반복적 프로세스에서 단계별 설계의 양이 다른 예

대표적인 애자일 프로세스인 스크럼은 기능 중심적 접근 방법으로 백로그에 구현할 기능을 관리한다. 여기에도 리스크 주도 접근법을 적용할 수 있다. 일반적인 기능 백로그는 제품 책임자(Product Owner)가 담당한다. 재품 책임자는 엔지니러링 리스크를 파악하기 어렵다. 대신 소프트웨어 팀이 리스크를 파악하고 이를 시스템의 테스트 가능한 기능으로 만들어 백로그에 넣을 수 있다. 이는 각 반복이 끝날 때 회고(Reflection/Retrospective)의 결과로 도출될 수 있다. 제품 책임자는 백로그 중에서 우선 순위에 따라 각 단계에 수행할 내용을 결정할 수 있다.

기능 및 리스크 백로그 활용방안

 

정리해보면...

리스크 주도 설계 접근 방식의 주요 내용은 설계에 많은 비용이 들기 때문에 리스크를 찾아 내고 이에 적절한 테크닉을 필요한 만큼 반복적으로 적용한다는 것이다. 이는 현재 소프트웨어 개발에서 적용되고 있는 양극단의 소프트웨어 개발 방법에서 모두 적용할 수 있다고 책에서는 주장하고 있다.

 

특히, 애자일 혹은 반복적 개발에서 알 수 있는 주요한 내용 중 하나가 설계가 항상 개발 프로세스의 앞부분에서만 진행되어야 하는 것은 아니라는 점이다. 후반부에 설계를 하게 되면설계를 변경하기 어려운 부분도 있을 수 있으나 구현하려고 하는 소프트웨어를 초기에는 잘 알지 못하는 문제점도 있다는 것을 책에서는 지적하고 있다. 소프트웨어 개발이 지식을 얻어 가는 과정이라면, 이를 이를 소프트웨어 설계 및 아키텍처링에 적용하는 방법으로서 리스크 주도 접근 방식의 장점과 적용하는 방법에 대해서도 흥미로운 재안을 하고있다.

참고 도서

[1] George Fairbanks, "Just Enough Software Architecture: A Risk-Driven Approach," 2010

[2] "Software Architecture: 어떻게 설계 할 것인가?," https://technical-leader.tistory.com/35

[3] 렌 베스 , 폴 클레멘츠 , 릭 캐즈먼, "소프트웨어 아키텍처 이론과 실제, 개정판 3판" 2015년, 에이콘출판

[4] Design Pattern 배우기, https://technical-leader.tistory.com/7?category=1015396 

 

 

+ Recent posts