소프트웨어 공학에서 어떤 결과를 생산하기 위한

상호명 : (주)세진에듀 SEJIN Edu|대표이사 : 이재헌|개인정보책임자 : 박명식 ()
사업자등록번호 : 304-81-27235 [사업자 정보확인] |통신판매업신고 : 2021-서울성동-01578|출판사 신고 : 도서출판 에듀온 (제2008-1호)
소재지 : 서울특별시 성동구 광나루로8길31(성수동2가) SK V1 2동 1206호 대표전화 1599-9477|FAX : 02-2179-9477
기업부설연구소 : 강원도 원주시 지정면 신지정로 212, 퍼스트프라자 702호 | 사이트명: 에듀온

소프트웨어 개발이란 무엇일까? 개발 툴을 실행시켜 ‘코딩’하는 것만이 소프트웨어 개발일까? 소프트웨어를 테스트하고 품질을 검사하는 단계는 소프트웨어 개발이라고 이야기할 수 있을까? 그럼 ‘성공적인 소프트웨어 개발’은 어떤 단계를 의미할까?

성공적인 소프트웨어 개발?
필자는 ‘성공적인 소프트웨어 개발’을 다음과 같이 표현하고 싶다.

소프트웨어 개발자 + 고객 = 성공적인 소프트웨어 개발

소프트웨어 개발자와 고객 간의 의사소통으로 요구사항이 충족되고 적절한 정보서비스의 개발이 원활하게 이뤄진다면, 이것이야말로 성공적인 소프트웨어 개발이라고 할 수 있다. 생각해 보면 고객이 직접 자신이 원하는 소프트웨어를 개발한다면 더 완벽하지 않을까? 

그러나 1인 프로그래머가 홀로 모든 것을 다하던 시대와 달리 현재는 설계자와 코더가 나뉘고, 시대의 흐름이나 서비스 중심의 구조적인 설계를 하는 아키텍트의 시대로까지 많은 변화가 발생한다. 소프트웨어 개발 조직이 정말 방대하고 복잡해졌기 때문이다. 고객의 목소리가 실제 개발조직에 전달되고, 어떤 단계를 거쳐 실제 필요한 정보서비스로 변해가는 과정은 정말 블랙박스화되어 그 누구도 통제하기 어려운 형태로 변했기 때문이다.

이러한 소프트웨어 개발과정의 통제나 개발자들 간의 커뮤니케이션에 대해 다양한 각도로 생각해 보자. 가볍게 설명한다면 이 과정 자체가 아키텍팅의 과제이고 단계다. 이 글을 통해 소프트웨어 아키텍처가 중요하게 부각된 이유를 설명하고 소프트웨어 아키텍처를 도입함으로써 어떤 목표가 달성될 것인지를 살펴본다.

소프트웨어 개발을 시대별로 구분하면 전설의 시대, 고대시대, 중세시대, 근대시대, 현대시대로 나눠 설명할 수 있겠다. 전설의 시대는 ‘소스가 곧 라이브러리’이던 시대였다. 그리고 고대시대는 ‘binary’ 기반의 라이브러리 시대라고 할 수 있고, 중세시대는 에디터가 존재하던 시대를 말한다. 그리고 근대시대는 ‘RAD 툴’을 써서 소프트웨어를 개발하던 시대를, 마지막으로 현대시대는 ‘서비스’를 중심으로 한 ‘프레임워크’의 시대라고 할 수 있겠다.

현실적으로 소프트웨어 개발이 얼마나 어려운지 몇 가지 나열해 보자. 현대의 소프트웨어는 정말 많은 기능이 부여되어 있는데다, 기능의 변경이 정말 잦다. 또한 이렇게 구현된 소프트웨어 내부구조와 동작은 정말 비가시적이다. 게다가 소프트웨어 개발의 진행상황 자체를 파악하기도 너무 어렵다. 그래서일까? 개발비용이나 개발기간의 예측은 거의 도박 수준이다. 또한 정말 다양한 분야의 전문지식과 기술, 경험이 요구되고 있으며 관련 컴퓨터 하드웨어와 소프트웨어 기술은 정말 급격하게 발전하는 상황이다. 다른 분야의 공학적인 부분이 소프트웨어공학의 이론 단계에서는 아직 미성숙 단계에 와있다고 하겠다. 그럼 좀 더 전문적으로 소프트웨어의 특성에 대해 설명해 보자.

(1) 소프트웨어는 유형적(tangibility)인 형태로 존재한다

프로그램 코드의 형태로 존재하고 산출물로 가시화할 수 있다.

(2) 소프트웨어의 상호작용(dynamic behavior)을 통한 완성

프로그램 자체는 분명 정적인 코드이지만, 소프트웨어 자체는 구동되어 동적이다. 프로그램이 하드웨어에 의해 수행되고 사용자와 상호작용할 때 비로소 프로그램이 아닌 소프트웨어가 되는 것.

(3) 소프트웨어의 상품성은 기본적인 가치다

개발된 프로그램은 제품에 불과하지만, 이 소프트웨어가 포장되고 사용자가 사용할 가치가 생기므로 상품이 된다.

(4) 소프트웨어의 견고성은 유연할 수 없는 현실

소프트웨어 개발의 행위는 정말 예측이 어렵고 수정이 용이하지 않다. 한번 구조성을 잃어버리면 유지보수는 점점 어려워지게 된다. 말 그대로 소프트하지 못하고 유연하지 못한 것이 소프트웨어이다.

(5) 소프트웨어의 비마모성 때문에 품질은 점차 저하된다

소프트웨어는 하드웨어와 다르게 마모되지 않으므로, 시대가 변하면서 그 품질 자체는 점차 저하되는 현상을 일반적으로 거치게 된다. 더군다나 구조성을 잃어버려 유지보수 과정을 거치면서 점점 더 품질이 저하되는 특성이 있다.

그렇다면 소프트웨어 개발 과정에서는 어떤 특징이 있을까?

(1) 소프트웨어 개발은 비제조적이다

소프트웨어 개발은 말 그대로 ‘개발’이다. 제조, 생산되는 것이 아니다. 말 그대로 ‘개발 과정’ 자체가 결국 그 소프트웨어의 ‘품질’이 된다. 이러한 기본적인 원리를 무시한 채 ‘공정’과 ‘생산계획’에만 치중한 소프트웨어 개발은 그 품질을 기대할 수 없다. 성공적인 소프트웨어를 원하는 개발조직이나 고객이라면 그 ‘개발과정’ 자체를 관리해야 한다.

(2) 소프트웨어 개발은 비조립적이다

말 그대로 소프트웨어 컴포넌트만 조립해서 소프트웨어가 개발된면 제조업의 형태를 가지겠지만 아직까지 소프트웨어 개발은 ‘조립’이 불가능한 상황이다. ‘단순 조립’이 가능한 시대가 올 수 있지만 적어도 지금까지는 그런 시대가 오지 않았다.

(3) 소프트웨어 개발 과정은 정말 비과학적이다

수학과 과학으로 모든 것이 설명될 수 있다면 얼마나 좋을까? 하지만 소프트웨어 개발은 조직, 인력, 시간, 비용, 절차와 같은 관리 기술적인 요소를 통해 만들어지는 정말 비과학적인 분야다.

소프트웨어 개발에 대한 잘못된 인식

그렇다면 이러한 소프트웨어 개발을 바라보는 관리자나 고객의 시야는 어떤지 살펴보자. 여기에는 소프트웨어 개발을 바라보는 3대 착각과 망상이 있다.

● 관리자들의 착각

소프트웨어 개발방법이 문서나 소스 코드에 상세하게 기록되어 있으니 개발자들이 어려움을 느끼지 않을 것이란 착각, 하드웨어와 다양한 도구들의 개발환경만 좋아지면 개발자들은 불편하지 않을 것이란 착각, 스케줄이 지연되면 인력을 추가로 투입시키면 된다는 착각, 교육만 잘 시키면 우수한 소프트웨어 개발인력은 손쉽게 확보 가능하다는 착각.

● 사용자들의 착각

시스템의 정의와 개발목표가 정해지면 언제든지 프로그래밍은 착수 가능하다는 착각, 요구사항과 상세내역은 발생할 때마다 언제든지 프로그램에 추가할 수 있다는 착각, 사용자의 요구는 지속적으로 변할 수밖에 없으니 개발 도중에 변경되는 요구사항을 쉽게 수용할 수 있을 것이라는 착각.

● 개발자들의 착각

프로그램을 코딩하기 시작하고 테스트를 마치면 개발자의 작업은 완결된다는 착각, 프로젝트가 완료되었을 때의 결과는 작동되는 프로그램이다라는 착각, 개발 단계에서의 결과물에 대한 검토회(review)는 정말 번거로운 일이라는 착각, 소프트웨어의 유지보수란 결함을 찾아서 수정하는 작업으로 간단한 일이라고 여기는 착각.

<그림 1>은 소프트웨어공학을 쉽게 설명하기 위한 것으로, 필자가 생각하는 소프트웨어공학적인 형태를 표현했다.

소프트웨어 공학에서 어떤 결과를 생산하기 위한

<그림 1> 소프트웨어 공학

소프트웨어공학을 한마디로 표현하면 ‘최소의 경비로 고 품질의 소프트웨어 상품을 개발하고 유지보수 및 관리하기 위한 모든 기법, 도구, 방법론의 총칭’이다. 소프트웨어공학에서는 기법(technique), 방법(method), 방법론(methodology)의 기본으로서 중요한 관리기법, 개발기법, 그리고 사람에 대한 커뮤니케이션까지 포괄한 것이 ‘방법론’에서 이야기하는 중요한 요소일 것이다.

소프트웨어 생명주기 모델과 개발 모델들의 발전단계를 살펴보면, 폭포수 모델 쭻 프로토타이핑 모델 쭻 나선형 모델 쭻 반복 또는 점증적 방법 쭻 컴포넌트 기법과 모델까지 중요한 관점의 변화는 개발자들 간의 의사소통과 관리에 대한 중요성을 점차 늘려왔다는 것이다.

소프트웨어 아키텍처는 이러한 방법론을 기반으로 한다. 작업절차, 작업방법, 산출물, 기법, 관리, 도구를 기반으로 소프트웨어를 구조적으로 바라보는 관점을 변화시킨다. 필자가 소프트웨어 아키텍처를 강의하면서 가장 자주 말하는 것 중의 하나는 ‘우리는 람보가 아니다’라는 점이다. 그래서 정말 세심한 부분까지 고민하고 실천해야 한다. 람보처럼 전쟁터에서 총알만 집어던져도 전투에서 승리하는 수퍼프로그래머와 같은 프로그래머들만이 우리의 개발세계에 존재하는 건 아니라는 점이다. 물론 이런 ‘람보’ 같은 개발자들과 호흡하고 같이 일할 수 있다면 그것도 방법이기는 할 것이다(이런 사람들은 정말 불가사의한 개발능력을 발휘하곤 한다).

소프트웨어 아키텍처를 이야기할 때 또 하나 빼먹지 않고 이야기하는 관점은 ‘IT와 건축’에 대한 이야기다. 현재의 모든 IT의 설명은 건축 메타포어를 이용한다. 심지어 갑을병정의 사업구조와 형태까지 거의 동일하며, 짜임새 없는 건축 설계 없이는 복잡한 건물을 지을 수 없는 것처럼 소프트웨어 개발에서도 아키텍처는 매우 중요하다.

소프트웨어 아키텍처
소프트웨어 아키텍처에서는 다음의 두 가지에 주목해야 한다.

(1) 중요한 부분만 다뤄야 한다.
(2) 아키텍트의 역할이 중요하다.

아키텍트는 소프트웨어를 개발할 때 중요한 재료들을 잘 다뤄야 한다. 그것은 비용, 적용기술, 조직의 역량, 기능, 목표, 시스템의 복잡도에 대한 아키텍트의 중요한 판단을 바탕으로 시스템을 구상하고 추상화하는 방법이다. 이것이 바로 소프트웨어 아키텍처의 기본이며, 소프트웨어 개발을 구상하고 추상화하는 것이 곧 소프트웨어 아키텍처의 과정이다. 그러므로 아키텍트는 ‘소프트웨어 개발과 관련해 기술적인 판단을 내리는 최고책임자’라고 손쉽게 정의할 수도 있겠다.

그렇다면 이러한 소프트웨어 아키텍처를 프로젝트의 현실에 대입해 보자. 현재 SI 환경을 비롯해 소규모 개발사이든 대형 개발사이든 개발과 관련된 많은 문제들이 존재할 수 있다. 각각의 사례들은 그 규모에 따라 그 형태를 달리하는 경우가 많은데, 이 글에서는 소규모 프로젝트보다는 대규모 프로젝트에 한정해서 생각해 보도록 하겠다.

- 프로젝트 A : EJB를 기반으로 한 EAI 제품 개발, 개발기간 3년, 투입인원 4개팀 20명
- 프로젝트 B : SyncML 관련 모바일 솔루션 개발, 개발기간 6개월, 투입인원 5명
- 프로젝트 C : 온라인게임 개발, 개발기간 2년, 투입인원 12명(디자이너 제외)
- 프로젝트 D : 공공기반 프로젝트, 개발기간 3년, 투입인원 연인원 60명, 최대 130명

프로젝트의 성공 여부는 어디에 달려 있을까? 누가 성공 여부를 결정하는가? 과연 프로젝트는 어떻게 진행되는 것이 옳은가? 과연 방법론의 사용 여부는 어디까지이며 산출물의 작성 기준은 어디까지인가? 소프트웨어 아키텍트는 이러한 것들을 커다란 개념으로 볼 수 있게 한다. 예로 든 프로젝트 A와 B는 패키지 개발이고 실제 소프트웨어의 성향이나 목표에 대한 부분을 결정하는 것은 최고 경영자층과 CTO 레벨의 몫이므로, 지금 설명할 내용에서는 약간 벗어난다고 할 수 있다. 

그리고 프로젝트 C의 경우에는 일반 고객들을 상대로 하는 프로젝트이기 때문에 해당 프로젝트도 일단 이 범위에서는 제외하며, 여기서는 프로젝트 D를 기준으로 한다. 사용자들이 정해져 있고 보통 SI라고 부르는 사업이므로 이에 대해 기술한다. 프로젝트 D의 특징을 기술하면 다음과 같다.

(1) 프레임워크나 솔루션이 투입되어 일정한 공수로 개발자들이 투입되어 개발한다.
(2) 기존에 정보시스템이 있거나 대체, 혹은 신규 개발하는 형태다.
(3) 고객이나 사용자들이 일반사용자에 가까우므로 IT 관련 정보기술에 어둡다.
(4) 고급개발자들을 극소수만 사용할 수 있으며, 초급개발자들을 주로 사용한다.
(5) 기간이나 비용 등이 영업의 힘으로 결정되는 경우가 다반사이며 생각보다 제약사항들이 많다.
(6) 고객의 요구조건을 어떻게 관리하는지와 품질의 영역이 불명확한 경우가 많다.

가장 중요한 요소인 ‘소프트웨어 품질’에 대해 아키텍트는 착각하면 안 된다. 모든 소프트웨어는 100% 고품질로 만들 수 없다는 점을 깨달아야 한다. 그리고 고민해야 한다. ‘과연 모든 모듈을 고품질화시킬 필요가 있을까?’, ‘유지보수성이 정말 필요한 부분은 어디인가?’, ‘정말 고성능이 필요한 부분은 어디인가?’, ‘기본 규칙만 지키도록 하고 대다수는 자동화해 템플릿 형태에서 구현이 가능한 부분들은 어디인가?’, ‘품질의 형태에 따라서 모두 같은 산출물과 문서화가 필요할까?’ 등이다.

필자의 경험으로는 20%의 고성능과 80%의 단순함으로 승부하고 고객에게 ‘사용자 경험’을 어떻게 전달할지를 디자인해야 한다. 이러한 문제는 바로 비용, 인력, 솔루션에서 발생하기 때문이다. 언제나 적절한 비용, 인력, 기간, 솔루션 및 기술은 완비되지 않기 때문이다.

또한 가능한 아키텍트에게 UI와 UX에 대해 준비하라고 언제나 이야기한다. 모든 정보서비스의 완성은 사용자의 경험에서 얻어지는 비기능적인 경험에서 결론 나기 때문이다.

프로젝트의 일반적인 경향
그럼 프로젝트의 일반적인 경향은 어떤지 지금부터 살펴보자.

(1) 기술적인 결정을 내릴 때 비합리적인 결정을 내리는 경우가 많다 

대부분 기술적인 결정은 경험에 의해 이뤄지곤 한다. 그러나 경험적인 해결책이 현재 진행 중인 프로젝트에 부적절한 경우도 많다. 실제로 경험적인 결정만으로는 프로젝트에서 적용할 기술에 어떤 위험이 따르는지 판단하기 어렵다. 하지만 대체로 경험이 많은 개발자들을 중심으로 PM과 PL이 구성되고 그들을 중심으로 이러한 문제를을 해결하기 위한 미팅이나 회의가 자주 이뤄진다. 또한 기술적인 결정을 내릴 때 비용과 프로젝트 적합성을 따지지 않고 도입하는 경우가 많다. 이 경우 프로젝트 기간을 줄이고 품질을 높이기 위해 도입된 기술이 오히려 프로젝트를 지연시키고 시스템의 품질을 저하시킬 수 있다. 기술적인 의사결정이 프로젝트 중간에 흔들려서 프로젝트가 지연되는 경우도 종종 발생하는데, 이것은 선택된 기술이 프로젝트에서 최적의 선택인지 고민하지 않았기 때문이다. 사용자의 요구사항에 기초하지 않은 의사결정은 막연한 결과를 만들고 기술적인 의사결정이 올바른 것인지 프로젝트 후에도 판단하기 어렵다. 의사결정을 하기 위해 많은 시간을 소요하지만 합리적인 결정을 내리지 못할 때가 많다. 실제 영업적인 이유로 인해 이와 같은 경우가 발생하는 경우도 다반사다.

(2) 새로운 프로젝트에서 과거의 경험을 답습하는 경우가 많다 

프로젝트는 전혀 새로운 환경일 때가 많고 프로젝트의 성격에 따라 최적의 선택을 해야 한다. 기술을 어떻게 선택할 것인지에 대한 정형화된 프로세스가 없으며 기술은 계속 변한다. 따라서 과거의 프로젝트 성공에 대한 경험으로 현재의 문제를 해결할 수 없다. 그런데 이점을 간과하는 경우가 많으므로, 많은 기술을 조합해 현재 프로젝트를 위한 최적의 해결책을 찾아야 한다. 이 해결책은 사용자의 요구사항에서 논리적으로 도출된 것이어야 하며, 설명 가능한 방식이어야 한다.

(3) 과거의 프로젝트에서 배우지 못한다 

이것은 (2)의 내용과 정반대의 경우다. 과거의 프로젝트의 성공과 실패에서 원인 분석을 하지 못하면 성공한 이유도 실패한 이유도 알 수 없다. 프로젝트에서 대부분의 문제는 고객과 개발팀간의 커뮤니케이션 부재 때문에 발생한다. 또한 프로젝트의 범위 관리도 문제가 되며, 사용자의 요구사항을 어떻게 도출하고 관리할 것인가도 문제가 된다. 기술적으로는 시스템의 복잡성이 문제가 된다. 시스템의 복잡성은 개발자의 능력 한계를 뛰어넘는 것으로 시스템 복잡성을 줄이고 효율적으로 시스템을 구축하는 방안을 찾아야 한다. 기술적인 복잡성을 줄이고 합리적인 의사결정을 내리기 위해서는 기술적인 의사결정을 초기에 내리고 적합한지 계속 테스트해야 한다. 또한 초기에 어떻게 프로젝트 조직을 구성할 것인가도 프로젝트 성공에 많은 영향을 미친다. 역할 분담이 명확하지 않아서 책임 소재를 따지는 데 많은 문제가 발생한다. 조직 구성도 프로젝트의 성격과 기술 셋(Set)에 따라 달라진다. 프로젝트 팀원들이 도메인을 잘 알고 사용하는 기술에 익숙한 경우와 프로젝트 팀원들이 도메인과 기술을 모두 모를 경우에는 조직 구성이 달라져야 한다. 대부분 설계자가 요구사항을 정리하는 것 외에는 제 역할을 하지 못한다. 설계자가 어떤 일을 해야 하며 개발자에게는 무엇을 주어야 하는지도 결정해야 한다.

(4) 일정의 진실

소프트웨어 개발을 계획하고 관리하는 방법과 시스템은 많다. 정말 많다. 특정 결과를 얻으려는 기법들을 모은 집합들, 이 기법들은 모두 조직 문제와 프로젝트 관리 문제를 해결하려 애쓴다. 각 기법들에 각각의 장단점이 모두 다르다. 다만 아키텍트는 어떤 방법론을 사용하든지 간에 프로젝트에 성공하려면 기본적으로 익혀야 할 개념과 전술이 있다. 그것은 어느 상황이든, 프로젝트와 팀에 맞게 방법론을 고치고 조율해야 한다는 점이다. 방법론에 치중하기보다는 더 근본적인 지식에 근접해야 하는 것이다. 소프트웨어 개발에 있어서 프로세스와 방법론이 매우 중요하기는 하지만, 프로세스와 방법론 자체가 만병통치약이거나 성공적인 결과를 보장하지는 않는다. 필자가 자주 쓰는 말이 있다. ‘개발에 있어 형식에 얽매이는 행위야말로 삽질이다- 꿈꾸는 자.’ 이는 필자의 트위터 프로필에 있는 말로, 필자가 운영하는 아키텍트 카페에서 이야기하는 첫 번째 교훈이기도 하다. 이론은 이론일 뿐, 사람과 커뮤니케이션의 중요성을 잊어버리고 절차에만 매달리는 행위에 대한 경고이기도 하다.

(5) 테일러주의를 벗어나지 못한다

많이 알려진 최초의 산업공학자인 프레드릭 테일러는 공장의 효율성을 연구해 ‘산업공학’이라는 분야를 만들었다. 그의 주장의 핵심은 ‘과학적 관리’를 중요시한 것이다. 테일러주의식 사회공학의 첫 번째 단계는 ‘계획’과 ‘실행’을 분리하는 것이다. 일하는 방법과 일하는 데 걸리는 시간을 결정하는 것은 교육받은 공학자들을 통해서 한다. 그들은 작업자들에게 주어진 과업을 할당된 시간 동안 충실히 따르게 하면 모든 일은 잘 된다고 믿는다. 작업자들 자체를 기계 부품으로 보는 방법이다. 두 번째 단계에서는 ‘품질부서’를 두게 한다. 테일러는 작업자들은 할 수만 있다면 ‘꾀’를 부린다고 생각해 품질부서를 통해 적절한 속도, 정해진 방식으로 일하는지 확실하게 체크하는 방법을 사용하게 한다. 이런 방식으로 ‘기획/실행’을 분리하고 ‘품질부서’를 두게 하는 방법은 현재의 소프트웨어 개발에서도 흔하게 쓰는 방식이다. 이 방식 자체는 ‘개발과정’이 단순하다면 의미가 있다. 하지만 고성능이나 기술지향적인 곳에서는 이런 방식 자체는 문제가 있다. 소프트웨어 개발을 그런 제조업의 공장 라인처럼 생각하는 것 자체가 문제이기 때문이다.

그렇다면. ‘성공적인 프로젝트’는 방법론을 잘 지켰는가에 대한 질문에 대해 어떻게 답해야 할까? ‘그렇다’라고 이야기하는 게 정답이겠다. 그것은 ‘방법론’의 ‘기본’에 충실했기 때문이라고 이야기하는 것이 맞다.

국내 프로젝트의 경향그럼 국내 프로젝트의 경향은 어떠할까? 몇 가지로 정리해 보자.

(1) 신기술을 도입해 무조건 쓰는 경우가 많다. J2EE가 프로젝트의 성격에 맞는지, CBD가 프로젝트의 성격에 맞는지 고민해 프로젝트를 위한 최적의 선택을 한 경우가 많지 않으며 신기술에 대한 막연한 기대를 가지고 프로젝트를 시작한다.

(2) 프로젝트의 복잡성이 증가되고 관리되지 않으면 어느 순간 통제할 수 없는 상황에 빠진다. 이 경우 개발자들이 자체적으로 커뮤니케이션을 통해 해결하는 경우가 많다.

(3) 프로젝트 초기에 드러나지 않았던 문제들이 프로젝트 마무리 시점에 드러나는 경우가 많다. 많은 오류가 프로젝트 마무리 시점에 발생한다.

(4) 설계자가 제 역할을 못하는 경우가 많다. 단순히 사용자의 요구사항을 정리해 개발자에게 전달하는 역할만을 한다.

(5) CASE 툴의 사용이 개발 생산성 향상에 큰 도움이 되지 않는다. 개발자의 시스템 구축을 위해 미리 준비되어야 할 많은 사항들을 개발자 스스로 만들어가는 경우가 많다. 시스템 환경 세팅, 테스트, 각종 툴 사용 기법, utility 공통 코드, 코딩 표준 등을 개발자 스스로 결정한다.

(6) 몇몇 능력 있는 개발자들의 도움을 받아 프로젝트가 진행된다(결과적으로 프로젝트에서 누군가는 아키텍트의 역할을 함). 그러나 능력 있는 개발자가 자신의 능력을 발휘하는 시점이 프로젝트의 문제가 발생하는 무렵이라 개발자의 능력만으로 해결할 수 없을 정도로 이미 문제가 심각해진 경우가 많다(왜 프로젝트 초기 의사결정에 이런 사람들을 참여시키지 않는가). 프로젝트 팀원들이 프로젝트 관리자에게 의사결정을 요구하지만 기술적인 문제는 프로젝트 관리자가 의사결정을 내릴 수 없으며 몇몇 사람들의 의견을 구하거나 의사결정이 이뤄지지 않은 채 프로젝트가 진행되는 경우도 있다.

(7) 요구사항에 대한 관리가 이뤄지지 않는다. 요구사항이 시스템에 어느 정도의 영향을 미칠 것인지, 아키텍처에는 어느 정도의 영향을 미칠 것인지를 판단하지 못한다.

그렇다면 위와 같은 프로젝트의 경우에는 어떻게 할 것인가? 프로젝트를 포기하는 것도 하나의 방법일 수 있다. 혹은 제약사항을 머릿속에 두고 그와 같은 아키텍처를 그려낼 수 있는 방법을 도출할 수도 있다. 어떤 프로젝트이든 최고의 방법은 없다. 최선의 방법만 존재할 뿐이다. 실제 프로젝트에서는 최고의 비용, 최고의 기간, 최고의 프로그래머와 일하는 것이 아니기 때문이다. 이러한 것들을 해결하기 위해 무수히 많은 것들이 존재하지만, 이곳에서는 이러한 문제들의 구조를 파악하고 소프트웨어를 제작하기 위한 소프트웨어 아키텍처에 대해 서술해 보자. 그리고 흔히 간과하고 넘어가는 경우가 많은데. 다음의 예를 하나 살펴보자. 사용자들이 요구하는 아주 비기능적인 요소들이 있다.

“동일 조회업무 화면을 여러 개 보이게 해 주세요.”

이러한 요구조건을 어떻게 해결해야 할까? 생각보다 복잡하고 미묘한 문제들이 걸려 있다. 어떤 부분인지 살펴보자. 일단 어떤 사람이 개발한 업무화면이 N개 동작한다는 것은 그 업무 화면에서 여러 개 동작시키는 메커니즘을 활용하는 방법도 있을 것이고, 해당 프레임워크를 제공하거나 아니면 웹과 마찬가지로 세션을 유지하지 않는 방법을 고려할 수도 있다. 사용자의 기능 하나에 의해 구조적인 모습이 전혀 엉뚱한 모습으로 변할 수 있다. 

이러한 요구 조건들이 품질 요구사항으로 변하고 실제 소프트웨어의 아키텍처와 프레임워크, 솔루션의 도입, 개발자들의 가이드라인, 컴포넌트의 구성방식, 유지보수 방법 등에 많은 영향을 준다. 이 부분을 간과하고 넘어간 경우를 살펴보자. 업무 분석을 하고 설계, 개발, 단위테스트, 통합테스트, 배포까지 무난하게 넘어갔다고 하자. 그런데 실제 사용자가 요구한 것은 ‘전체 업무의 형태를 위와 같이 N개 동작하게 해달라’는 요구사항이었다고 나중에 밝혀졌다고 해보자.

설계자는 요구조건에 맞는 프레임워크가 아니었다고 이야기할 것이고, 개발자는 세션을 유지하는 C/S 프로그램으로 만들어 놨고, 공통 함수로 처리되는 방식으로 빠르게 개발할 것만 고려하고 구현되었다고 해보자.

소프트웨어 공학에서 어떤 결과를 생산하기 위한

<표 1> 설계와 SA 관점의 차이

과연 누구의 잘못인가? 이것이야말로 아키텍트가 초기에 소프트웨어 아키텍처를 잘못 설계한 케이스다. 처음부터 이러한 상황을 고려해 동작 가능한 구조로 만들어 주었다면, 문제가 발생하지 않았을 것이다. 개발자가 컴포넌트 개발도 할 줄 모르는 공통함수 개념과 화면별 단위 프로그램밖에 만들 줄 모르는 개발자였다면, 해당 개발자들이 해당 요구조건을 모르고 코딩해도 실제 수행에 아무런 문제가 없도록 시스템 메커니즘을 구현했어야 했다. 이 문제의 해결에는 아주 많은 방법들이 있다. 그렇다면 설계와 SA의 차이점은 과연 무엇일까?

물론 ‘요구사항을 만족시키기 위한 해법을 제시한다’는 측면에서는 공통점이 있다. 차이점으로는 ‘아키텍트의 관점은 좀 더 큰 그림을 보고, 설계는 미시적인 관점이다’라고 쉽게 설명할 수 있겠다. 아키텍트는 좀 더 기능적인 요구사항이나 품질요소 등에 대해 구분하고 있게 된다. 이러한 관점의 차이는 설계나 방법론, 산출물에도 영향을 준다. 바로 품질속성(Quality Attribute)을 결정하고 그 품질속성을 관리하는 것이 SA가 가지는 가장 큰 차이점이라고 하겠다. 그럼 PM과 SA에 대한 차이점도 몇 가지 언급해 보자.

소프트웨어 공학에서 어떤 결과를 생산하기 위한

<표 2> PM과 SA의 차이점

소프트웨어 아키텍처를 도입하면서 달성되는 목표
소프트웨어 아키텍처의 도입은 다음과 같은 목표를 달성할 수 있게 한다. 그 목표는 크게 다음의 세 가지를 들 수 있다.

(1) 견고하고 안정적이며 고품질의 시스템을 구축할 수 있다.
(2) 시스템 구축 시 발생하는 문제들을 초기 단계에서 해결할 수 있다.
(3) 아키텍트의 역할을 명확히 정의해 20%의 고급 인력으로 80%의 프로젝트 인원을 리딩할 수 있다.

아키텍트는 비용과 목표에 대해 가장 많은 고민을 해야 한다. 최고의 개발자들로만 구성해도 프로젝트는 실패할 수 있다. 튼튼하고 품질 좋고 나중에 문제가 발생하지 않고, 비용이 적게 든다면 최선이지 않을까?

<그림 2>는 소프트웨어 아키텍처 도입 시 시스템 개발 프로젝트에서 어떤 도움을 받을 수 있는지를 한눈에 보여준다.

소프트웨어 공학에서 어떤 결과를 생산하기 위한

<그림 2> 아키텍처 적용 시 얻는 이점

(1) 소프트웨어 아키텍처 도입 시 아키텍처의 품질을 평가해 비합리적인 의사결정이 합리적인 의사결정으로 변경된다.
(2) 과거의 경험을 답습하거나 과거 사례에서 배우지 못했던 문제를 해결하고 소프트웨어 아키텍처를 재사용함으로써 과거 프로젝트의 성공과 실패 사례를 배우는 것으로 변경된다.
(3) 프로젝트의 복잡성을 아키텍처를 통해 관리하는 것이 가능해진다.
(4) 프로젝트 마무리 시점에서 발생하는 문제들을 아키텍처를 도입해 프로젝트 초기에 해결할 수 있다.
(5) 설계자가 단순히 요구사항을 개발자에게 전달하는 것을 아키텍처를 통해 설계자가 요구사항 분석뿐 아니라 기술적인 문제도 모델링할 수 있게 하며 개발자는 더욱 효율적으로 시스템을 구현할 수 있다.

소프트웨어 아키텍처의 목적과 정의
그럼 소프트웨어 아키텍처의 목적은 무엇인지를 정리해 보자.

(1) 아키텍트가 프로젝트 시작 시점에 투입되어 무엇을 하는지 시나리오를 작성할 수 있게 한다.
(2) 소프트웨어 아키텍처가 개발 프로젝트에 정착될 수 있게 한다.
(3) 아키텍트의 역할에 대해 정의한다.
(4) 아키텍트와 프로젝트의 구성요소 사이의 관계에 대해 이해한다.
(5) 소프트웨어 아키텍처가 포함된 개발 프로젝트의 프로세스는 무엇인가에 대해 알아본다.
(6) 아키텍트가 프로젝트에서 결정해야 할 항목은 무엇인가에 대해 고민한다.
소프트웨어 아키텍처는 여전히 다양하게 정의되고 있지만, 여기서는 소프트웨어 아키텍처가 시스템의 핵심 구성요소와 구성요소들 사이의 연결 관계로 이뤄지므로 시스템이 가지고 있는 모듈, 모듈 사이의 연결, 시스템의 변경, 진화하기 위한 기술적인 원칙, 모듈들 사이의 상호작용, 시스템이 동작하기 위한 기술을 모두 포함하는 것으로 정의한다. 즉 소프트웨어 아키텍처는 구현할 시스템에 대한 Top-down View이며 시스템에 대한 기술적인 명세서이자 공학적인 청사진이다. 기본적인 개념은 MDA에서 취하고 있는 방향과 유사하다.

소프트웨어 아키텍처의 구성요소
소프트웨어 아키텍처의 구성요소에 대해 자세히 살펴보면 다음과 같은 구성요소로 이뤄진 것을 알 수 있다.

- 시스템의 구성요소와 구성요소들 사이의 연결 관계
- 시스템의 설계와 진화를 통제하는 원칙과 가이드라인
- 시스템 구성요소들의 collaboration(성과)
- 시스템이 어떻게 확장되고 수정될 것인가에 대한 결정
- 시스템의 구성요소들이 가지고 있는 기술

<그림 3>은 소프트웨어 아키텍처의 구성요소를 보여주는 것으로, 이를 통해 소프트웨어 아키텍처가 세 가지로 구분됨을 알 수 있다.

소프트웨어 공학에서 어떤 결과를 생산하기 위한

<그림 3> 소프트웨어 아키텍처 산출물

Meta-Architecture는 아키텍처를 설계하기 위한 일반적인 지침이다. Meta-Architecture는 소프트웨어 아키텍처가 무엇인지 결정하고 아키텍처를 설계하기 위한 일반적인 의사결정 트리와 아키텍트의 역할에 대한 정의, 아키텍처 문서에 대한 템플릿으로 구성된다.

소프트웨어 아키텍처는 네 가지 View인 Module View, Com ponent&connector View, Allocation View, Code View로 구성된다. 또한 아키텍처 설계의 결과로 컨텍스트 다이어그램, 컴포넌트 명세, 인터페이스 명세가 도출되어야 한다.

View는 사람들마다 서술하는 방법, 기술하는 방법, 다이어그램의 형태, 박스/라인/인터페이스/컴포넌트의 수준과 깊이, 의미 등이 모두 다르므로, View의 선정 기준과 기술할 때의 주의점 위주로 살펴보면 된다.

이는 건축물을 설계할 때의 조감도 및 설계도, 세부 설계도, 투시도 등의 형태와 동일하다고 보면 된다. 필요 수준까지만 각자 알아서 그리면 되는 것이다. 일반적인 View는 Allocation View, Component & Connector View, Module View 세 가지다(필자는 Code View를 하나 더 구분해 4개의 View로 정리해야 한다고 생각하는데, 이에 대한 자세한 얘기는 다음 기회로 미룬다). 이 부분은 적어도 1개 이상에 대해 기술하고 몇 개가 적절한지는 개발자들의 역량과 도메인에 대한 이해, 이전 프로젝트의 경험 및 주요 이슈 사항 등의 요소에 의해 좌우된다. 다만 시스템의 큰 기능, 품질 속성(가용성, 변경성, 보안성, 성능)의 판단 근거가 되어야 하며, 주요 모듈의 기능이 내/외부와 어떤 연관성을 가지는지 보여야 하고, 시스템의 규모와 범위를 파악할 수 있으면 된다. 또한, 위와 같은 아키텍처 기술 정의서를 구축할 때 타당한 근거를 서술할 수 있으면 된다. 다만 이 View를 UML 1.x 영역에서는 표현하기가 어려웠다. 지나치게 기술에 종속적인 패턴의 설계나 컴포넌트의 배치 레벨에서의 작성이 주였기 때문이다. UML 2.0을 구성할 때 OMG에서 카네기 멜론 SEI의 아키텍처 정의를 상당 부분 도입한 덕분에 이 부분들에 대한 기술이 이제 수월해진 편이다.

가이드라인과 정책은 소프트웨어 아키텍처를 결정한 후 아키텍처를 기반으로 프로젝트를 진행하기 위한 가이드라인과 정책을 말한다. 아키텍트는 설계, 코딩, 배포, 통합, 테스트, 툴, 유지보수, 시스템 확장, 시스템 운영에 대한 가이드라인과 정책을 마련해야 한다. 정말 포괄적인 개발정책 부분을 모두 서술하고 결정한다는 것이다. 소프트웨어 아키텍처는 시스템 개발의 여러 구성요소와 관련을 갖는다. 프로젝트 조직, 프로젝트 스케줄, 형상 관리 계획은 소프트웨어 아키텍처에 근거해 결정된다. 소프트웨어 아키텍처의 설계 과정에는 프로토타입, 프레임워크, 유틸리티 프로그램 등이 영향을 미친다.

소프트웨어 아키텍처의 특징과 역할
소프트웨어 아키텍처의 특징은 다음과 같다.

(1) 소프트웨어 아키텍처는 시스템에 대한 추상화이다. 따라서 지엽적인 정보는 포함하지 않고 큰 그림만을 가지고 있다.

(2) 소프트웨어 아키텍처는 한 가지 다이어그램으로는 결정되지 않으며 여러 관점의 다이어그램으로 이뤄진다. 각각의 세부적인 것이 아니라 건축물의 투시도와 같으며, 옷 디자이너의 스케치와 유사한 성격을 가진다.

한편, 소프트웨어 아키텍처가 시스템 개발에서 담당하는 역할은 다음과 같다

(1) 관련 당사자들 사이의 의사소통 수단이다.

(2) 개발 프로젝트 초기 단계에서 의사결정 도구다. 아키텍처는 품질 요소를 결정하며 프로젝트 조직에 영향을 미친다.

(3) 시스템의 전체 구조를 결정한다.

(4) 개발 프로젝트의 조직을 결정하는 데 참고할 수 있다.

(5) 시스템이 가져야 할 품질 요소를 결정한다. 따라서 아키텍처를 통해 시스템이 어떤 품질을 가질 것인지 예측할 수 있다.

(6) 아키텍처를 통해 시스템 개발자들에게 어떤 교육을 시킬 것인지 결정할 수 있다.

(7) 소프트웨어의 변경사항을 어떻게 관리할 것인지를 알려준다. 상당한 역할이지 않은가? 이를 도식화하면 <그림 4>가 만들어진다.

소프트웨어 공학에서 어떤 결과를 생산하기 위한

<그림 4> 워드 프로세서의 객체 종류

<그림 4>에서 보는 것처럼 기능적, 비기능적 요구사항은 소프트웨어 아키텍처를 설계하는 데 입력 산출물로 작용한다. 소프트웨어 아키텍처가 결정되면 설계 패턴과 설계 가이드라인을 사용해 소프트웨어를 설계할 수 있다. 또한 소프트웨어 아키텍처가 결정되면 코드 작성 시 코드 표준, 코드 가이드라인을 제공할 수 있다. 또한 소프트웨어 아키텍처는 소프트웨어를 시스템에 배포 시 가이드라인을 제공한다. 이를 반복해서 구조적으로 안정적인 소프트웨어 아키텍처를 구성할 수 있다

소프트웨어 아키텍처에 포함되지 않는 것
소프트웨어 아키텍처는 하드웨어, 네트워크, 물리적인 시스템에 대한 아키텍처를 포함하지 않는다. 따라서 소프트웨어 아키텍처 설계서는 시스템 안에 포함된 소프트웨어만을 보여주며 시스템은 컨텍스트로서만 표현된다. 예를 들어 하드웨어 모델명, 하드웨어 구성, 라우터, 랜카드에 대한 정보는 소프트웨어 아키텍처에 포함되지 않는다. 이를 그린다는 것은 그것에 종속된다는 의미이므로 ‘추상화’하려면 해당 정보가 표시되면 안 되는 것이다. 세부적인 구현사항은 소프트웨어 아키텍처에 포함되지 않는다. 예를 들어 컴파일러 최적화, DLL을 shared로 할 것인지 static으로 할 것인지는 소프트웨어 아키텍처에 포함되지 않는다. 이는 별도의 의사결정 과정과 후반부에서 처리한다

*작성자:신현묵 zetlos.tistory.com