'소프트웨어 공학' 검색 결과 3건

  1. 2009.02.03 도요타 방식과 제약 이론(The Goal) (7)
  2. 2009.02.02 설계가 완벽하지 않아야 하는 이유 (10)
  3. 2009.01.02 소프트웨어는 소프트한가? (4)

설계가 완벽하지 않아야 하는 이유에서 이어지는 글입니다.

도요타 생산 시스템(Toyota Production System) 혹은 도요타 방식(Toyota Way) - 그냥 짧게 린(lean) 방식이라고 하겠습니다 - 과 더 골(The Goal)이라는 책에서 소개하고 있는 제약 이론(Theory of Constraints)의 관련성에 대한 글입니다.


1. 도요타 방식 혹은 린 방식

린 방식에서는 공정의 시작과 끝까지를 길게 잇는 Value Stream을 정의하고(queue라고 보시면 됩니다), Stream의 입구에 투입된 비용이 얼마나 빨리 가치로 변환되어 출구로 나오느냐를 중요하게 생각합니다(공학적인 용어로는 latency가 얼마나 낮으냐인거죠). 이를 흐름(flow)이라고 표현합니다. 또 한가지 중요한 것은 출구에 수요가 있는 경우에만 입구에 비용을 투입한다는 것입니다. 이를 밀어넣기(push)의 반대라는 의미에서 당기기(pull) 방식이라고 표현합니다.

이 두 가지가 결합되면 투자에 대한 회수가 빨라지고(latency가 낮으므로), 재고가 줄게 됩니다(pull 방식에 의해 투자가 일어나니까). 회수가 빨라지고 재고가 줄어들면 변화에 기민하게(agile) 대처할 수 있게 됩니다. 소프트웨어를 조금 더 소프트하게 만들 수 있는 방법입니다.

그럼, latency를 어떻게 줄일 수 있을까요? 여러가지 요인이 있습니다만 이 글에서는 Stream 사이를 흐르는 가치의 단위가 작을 수록 좋다는 점을 강조하고 싶습니다. 즉, packet의 크기가 작을수록 latency가 낮아진다는 뻔한 얘기입니다.

그럼, packet의 크기란 무엇일까요? 소프트웨어 개발로 치자면 각 단계(phase) 혹은 반복주기(iteration)의 크기입니다. 전통적인 프로세스 관점에서 말하자면 산출물(artifacts)의 크기입니다. 거대한 산출물을 만들어서 다음 단계로 넘기려고 하면 흐름이 끊기고 latency가 늘어납니다. 거대한 산출물의 대표적인 예로는 BUFD(Big Up-Front Design - 거대한 선행 설계) 같은 것이 있습니다.

소프트웨어 공정을 activity 사이에 artifact가 입/출력으로 오가는 과정으로 보는 관점(대표적으로 USDP)의 문제에 대해서는 추후에 별도의 글을 써보려고 합니다.

이것이 설계가 완벽하지 않아야 하는 이유 중 하나입니다.


2. 제약 이론

제약 이론에도 Value Stream 같은 것이 있습니다. 그런데 린 방식에서와는 집중하는 부분이 좀 다릅니다. 제약 이론에서는 이 Stream 내부의 가장 느린 지점 - 이를 제약(constraints)이라고 부릅니다 - 을 발견하고 개선하는 것에 집중합니다. 왜냐하면 Stream의 전체 성능은 가장 느린 지점에 의해 결정되기 때문입니다. 이를 병목(bottleneck)이라고 부르죠.

여기에서 성능이란 (latency와 마찬가지로 공학적인 용어로 표현하자면) 바로 throughput 을 말합니다. 제약이론은 끊임없이 병목을 제거하여 throughput 을 높이는 방법에 대한 것입니다.

병목을 제거(사실 병목은 제거되는 것이 아니라 다른 곳으로 옮겨질 뿐이죠)하는 방법 중 하나는 병목 지점에 추가적인 리소스를 투입하는 것입니다. 소프트웨어 개발로 치자면 병목이 되는 단계에 추가 인력을 배치하는 것으로 볼 수 있겠죠. 전문화의 폐해는 여기에 있습니다. 각 역할별 전문화가 잘 되어 있는 조직일수록 가능한 인력 운용의 폭이 좁아지게 됩니다.

테스트 단계가 병목이라고 칩시다. 테스트 단계에 추가 인력을 배치해야 합니다. 그런데 개발자, 설계자, 분석가는 다른 프로젝트에 "투입"되어 있습니다. 혹은 일이 없어서 놀고 있다고 하더라도 테스트 전문가가 아니기 때문에 테스트 공정에 배치될 수 없습니다. 아니, 배치되어서는 안된다고 합니다.

작은 조직에서 적극적으로 전문화를 시도하면 문제가 더욱 커집니다. 특정한 한 사람이 병가를 내거나 사고가 생기거나 하면 전체 프로젝트가 지연되거나 아예 멈춰버리는 수가 있습니다. 소위 말하는 트럭넘버가 낮아지는 것이죠.

저작자 표시
신고

설계가 완벽할 수 없는 이유를 읽고 씁니다.

저는 윗 글에 동의합니다. 설계는 완벽할 수 없습니다(사실 명제). 그리고 저는 설계를 완벽하게 하는 것이 가능하다고 하더라도 그렇게 해서는 안된다고 생각합니다(가치 명제).


1. 설계가 완벽할 수 없는 이유

소프트웨어는 소프트한가?에서도 인용한 적이 있고, 윗 글에도 나와있지만 짧게 요약하자면 세상이 바뀌거나, 내가 더 똑똑해지기 때문에 완벽한 설계란 좀처럼 얻어내기가 힘듭니다.

하지만 가정을 해봅시다. 세상(and/or 요구사항)이 바뀔 일도 없고, 나는 이미 천재이고 모든 도메인 지식을 다 가지고 있기 때문에 더이상 똑똑해질 일도 없다고 칩시다. 그렇다면 설계가 완벽해질 수 있을 것입니다. 그런데, 설계를 완벽하게 하고나서 코딩을 시작하는 것이 과연 좋을까요?


2. 설계가 완벽하지 않아야 하는 이유

2.1. 완벽한 설계의 가치

완벽한 설계(design)라는 가정 이면에는 완벽한 분석(analysis)이 전제되어 있습니다. 하지만 설계는 설계일 뿐 작동하지 않습니다(Executable UML 같은 시도도 있지만 뻘짓으로 간주하겠습니다). 그리고 작동하지 않는 소프트웨어는 고객에게 아무런 가치를 전달하지 못합니다.

즉, 완벽한 분석에 이어 완벽한 설계를 하느라 프로젝트 기간의 (이를테면) 절반 정도가 지나도 프로젝트는 아무런 가치를 창출하지 못합니다. 그 이후에 구현 조금, 테스트 조금, 배포 조금 하는 방식을 따른다면 이 때부터 가치가 창출되기 시작하겠지만 선행 분석/설계를 하는 프로젝트의 대부분은 끝까지 그 스타일을 유지하죠. 완벽한 설계 이후에는 완벽한 구현과 완벽한 테스트 단계가 오고, 그제야 완벽한 배포를 하는 소위 완벽한 폭포수(waterfall) 프로세스가 완성됩니다. 결국 프로젝트가 완전히 끝나야 가치가 전달되기 시작합니다.

2.2. Self-funding point와 BEP

애자일 방법론에서는 사용자에게 가치를 주는 작은 기능들을 단위로 하여 약간의 분석/설계/개발/테스트/배포를 짧은 주기로 반복합니다. 따라서 프로젝트 초창기부터 작동하는 소프트웨어를 고객에게 전달할 수 있게 됩니다. 다음은 폭포수 방식과 애자일 방식의 차이를 극명하게 보여주는 그래프입니다:


출처: The Origin of Value

참고로, Self-funding point란 프로젝트에서 발생하는 수익이 프로젝트를 지속하기 위한 비용과 일치하는 지점을 말합니다. 이 지점을 지나면 프로젝트는 소위 "밥벌이"를 한다고 볼 수 있습니다. 한편, 프로젝트에 현재 투입되고 있는 비용을 지속적으로 자체 충당(self-funding)하면서, 그 이전에 투입된 비용까지 다 갚아버리는 지점을 BEP - 손익분기점 - 라고 합니다.

빨간 선은 프로젝트에 투입되는 비용입니다. 위 그래프에서는 애자일이나 폭포수나 투입되는 비용이 동일한 것으로 간주하고 있습니다. 애자일 방법론을 실천하는 사람들은 애자일 방법론이 더 저비용일 것이라고 주장할 것이고, 폭포수 방법론을 실천하는 사람들은 폭포수 방법론이 더 저비용일 것이라고 주장할 것인데, 이 부분에서는 일단 중립을 지켜보도록 하죠.

녹색선은 애자일 프로젝트가 만들어내는 가치입니다. 짧은 이터레이션을 돌면서 잦은 릴리즈를 하기 때문에 프로젝트 초반부터 가치를 생산하기 시작합니다. 파란선은 폭포수 프로젝트가 만들어내는 가치입니다. 앞에서 설명한 이유로 인해 프로젝트 막바지가 되어야 가치가 생산되기 시작합니다.

녹색선은 애자일 방법론에 유리한 방식으로 약간 편향되어 있는데, 좀 더 공평하게 하자면 기울기가 초기에는 낮다가 점점 높아지는 꼴을 취해야 합니다. 왜냐하면 초반에는 기능의 수가 적기 때문이죠. 그래프를 그런 식으로 수정하고 나면 애자일 프로젝트의 self-funding point가 조금 더 늦춰지겠지만 여전히 폭포수 프로젝트에 비해서는 빠르겠죠. 그리고 이 상태가 유지된다면 애자일 프로젝트가 폭포수 프로젝트에 비해 훨씬 이른 시기에 BEP(break-even point. 손익분기점)에 도달합니다.

추가: 위 그래프에서 애자일 방법론의 self-funding point라고 한 부분은 사실 BEP로 표시되어야 하는데 잘못 표시한 것이 아닐까 싶습니다. self-funding point는 녹색선의 기울기가 빨간선의 기울기와 같아지는 지점이어야겠죠. 이 그림보다 예쁜 그림이 Software by Numbers 본문에 나오죠:

이 그림에서는 기울기의 변화와 면적을 보시면 됩니다. 초기 투자 기간(Investment period)의 기울기가 서서히 변하고 있는 까닭은 초기부터 가치를 전달하고 있기 때문입니다. 하지만 아직은 비용이 더 크기 때문에 전체적인 가치(면적)는 마이너스 입니다. 하지만 특정 지점(self-funding point)에 이르르면 프로젝트에 투입되는 비용과 프로젝트가 창출하는 가치가 같아집니다(기울기가 0). 그 이후엔 투입되는 비용은 고정된 반면 창출되는 가치는 점점 늘기 때문에(지속적인 릴리즈) 기울기가 점점 높아집니다. 이 기간동안 초기에 투입된 비용을 갚아나갑니다(payback period). 이 상태가 지속되면 어느 순간 손익분기점(break-even time)에 도달하고 그 이후부터는 수익이 발생하기 시작합니다.


2.3. 프로젝트 중단

프로젝트가 잘 굴러가고 있다가도 갑자기 중단되는 경우가 있습니다. 일선 관리자들이나 개발자 같은 실무자들은 대체 왜 그런 결정이 내려졌는지 자세히 알지 못하는 경우가 많지만 어쨌건 빈번하게 발생하는 일입니다. 위 그래프에서 x축으로 10 정도 되는 지점에서 프로젝트가 중단되었다고 칩시다.

그래프 상으로 애자일 프로젝트는 이미 BEP를 지나 수익을 발생시키고 있지만 폭포수 프로젝트는 아직 투자 단계입니다. 사실 재무/회계 관점에서 소프트웨어 프로젝트가 거대한 블랙박스로 인식되지 않고 릴리즈 단위로 인식될 수 있다면 애자일 프로젝트는 self-funding point 이후엔 어지간해서는 중단될 이유가 없어집니다(재무/회계 관점에서 당장 그렇게 인식되지 않는다 하더라도 적어도 방어 논리를 약간은 만들어낼 수 있을겁니다).

여기서 강조하고 싶은 이야기는, 재무/회계 관점에서 소프트웨어 프로젝트가 좀 더 정밀하게 분석되면 될수록 폭포수 방식의 문제가 더 크게 부각될 것이라는 점입니다.

2.4. 재고와 도요타 생산 방식

과잉 재고는 나쁜 것입니다. 1) 재고를 최소화하고, 2) 공정 상의 흐름이 끊기지 않게 하고, 3) Push 방식이 아닌 Pull 방식을 채택하면 일단 표면적인 도요타 생산 방식이 만들어집니다. 이 중에서 이 논의와 특히 관련이 깊은 것은 앞의 두 가지 입니다. 소프트웨어에서의 재고란 노력이 투입되었으나 아직 최종 사용자의 가치와 연결되지 않은 모든 것을 말합니다. 완벽한 설계는 전형적인 재고입니다. 둘째, 공정 상의 흐름이 끊어지지 않으려면 각 단계에서 작은 단위로 끊임없이 가치가 흘러야 합니다. 앞 단계에서 거대한 작업이 끝날 동안 뒷 단계에서 손 놓고 대기하고 있으면 흐름이 끊어지는 것입니다. 완벽한 설계는 흐름을 끊기게 하는 주요 원인입니다. 완벽한 분석, 완벽한 구현,완벽한 테스트도 마찬가지 입니다.

(얼마 전에 프로젝트 시작부터 개발자가 바글바글이라는 글을 읽었는데, 프로젝트 시작부터 개발자가 바글바글한 것이 문제인 이유는 공정 상의 흐름이 끊기기 때문입니다. 즉, 앞의 공정(완벽한 분석과 설계)이 끝나지 않으면 개발자가 놀아야 하는 것이 문제인거죠. 이에 대한 해법은 두 가지입니다. 하나는, 처음엔 개발자 없이 시작해서 프로젝트 중간에 개발자를 투입하는 것, 또 하나는 공정이 끊기지 않게 해서 초반부터 개발자가 일을 할 수 있게 하는 것.

하지만, 전자의 방식대로 하려면 조직 구조가 인력 풀 방식 혹은 직군별 팀 방식으로 운영되어야 하고 각 프로젝트의 특정 단계에 소위 "투입"되거나 "파견" 나갔다가 해당 단계가 끝나면 "철수"하는 식으로 일을 해야 합니다.

이러한 조직 구성이 효과적인 면도 분명 있겠지만 저는 별로 인간적인(humane) 방식이 아니라고 생각하고, 인간은 인간적인 방식으로 일해야 즐겁고 효과적으로 일할 수 있을 것이라고 믿습니다. 이 문제는 다음 기회에 더 쓰도록 하겠습니다. Ray님 블로그의 글은 잘 읽고 있습니다만 워낙 서로의 경험이 다르기 때문인지 의견 차이가 큰 것 같습니다. 그래서 더 열심히 읽고 이해하려고 노력하고 있습니다.)

이 밖에 "The Goal"의 제약이론도 관점이 약간 다르지만 이와 유사한 내용을 담고 있죠. 이에 대해서는 도요타 방식과 제약이론이라는 글을 참고해주세요.


3. 결론

이러한 이유로 저는 완벽한 설계가 가능하다고 하더라도 완벽한 설계를 하지 않는 것이 더 좋다고 생각합니다.


저작자 표시
신고

"소프트웨어는 소프트하지 않다"를 읽고 씁니다.


1. 소프트웨어 변경 비용 모델들

소프트웨어의 기능을 변경하고자 할 때 비용이 적게 들면 이를 두고 "소프트"하다고 표현합니다. 전통적으로는 프로젝트가 시작되고 시간이 흐를수록 변경 비용이 기하급수적으로 증가한다고 말합니다. 즉, 프로젝트 초창기에는 소프트하지만 시간이 지날수록 점점 소프트하지 않게 된다는 얘기입니다. 그림으로는 보통 이렇게 그립니다:

[그림1. 전통적 모델]

Y축이 비용(Cost), X축이 시간(Time) 입니다. Barry Boehm이 대략 30년 전에 그린 그림인데 여전히 많이 인용되고 있죠. 프로젝트 초기 단계에는 구현된 결과물이 없을 테니 변경이라는 것은 고작 머리 속 생각을 바꾸는 정도일 것이고 변경 비용은 거의 0에 가깝습니다. 한편, 프로젝트가 완료되고 현장에 배치(deploy)되거나 포장되어 매장에 출시된 후에 기능을 수정하고자 한다면? 엄청난 비용이 들 수 있습니다. 일견 맞는 말 같습니다.

하지만 10년쯤 전 Kent Beck은 소프트웨어 변경 비용을 아래와 같이 낮출 수 있다고 말합니다:

[그림2. Kent Beck의 그래프]

애자일 방법론의 여러 실천법(agile practices)을 통해 그렇게 할 수 있다고 주장합니다. 간결한 설계, 지속적 통합, 잦은 릴리즈, 테스트 주도 개발, 리팩토링, 짝 프로그래밍, 전체 팀 등 다양한 요소들이 이러한 변경 비용을 가능하게 해준다고 말합니다.

이 두 가지 극단적인 주장들(그림으로만 보자면)의 중간쯤 되는 모델들도 있죠. 이를테면 Poppendieck 부부의 Lean Software Development에서는 그래프 두 개를 합쳐놓아야 한다고 주장합니다:

[그림3. 짬뽕1]

크리스탈 방법론으로 유명한 Alistair Cockburn이나 IBM의 Scott Ambler 등도 이와 비슷한 모델을 제시했었죠. David  Anderson은 Agile Management for Software Engineering이라는 책에서 이를  S-Curve 모델이라고 부릅니다:

[그림4. 짬뽕2]

대충 두 부류로 나누자면 Boehm의 그림(1번)을 전통적 변경 비용 모델로, 나머지 그림들(2,3,4번)을 애자일 변경 비용 모델로 볼 수 있겠습니다.


2. 소프트웨어가 소프트해야 하는 이유

실제로 소프트웨어가 소프트한지 아닌지(사실 명제)를 이야기하기 전에, 소프트웨어가 소프트해야 하는지 아닌지(가치 명제)를 따져보면 좋겠습니다.

소프트웨어 프로젝트가 실패하는 원인 중 단골로 꼽히는 것이 “요구사항의 잦은 변화”입니다. 요구사항의 변화 빈도를 낮추면 성공 확률을 높일 수 있다는 해석이 가능합니다. 변화 빈도를 낮추려면 소프트웨어가 소프트하지 않다는 인식을 심어주어야 합니다.

한편, “요구사항의 잦은 변화”라는 문제에 대해 근본원인분석(root cause analysis)을 해보면 다른 해법을 찾을 수도 있습니다. 애초에 요구사항이 자주 변하면 왜 문제가 되는지를 따져보는 것이죠. 그 이유는 당연히 변경 비용이 크기 때문입니다. 그렇다면 변경 비용이 대체 왜 큰 것인지를 다시 물어보는 것이죠. 결국 변경 비용을 증가시키는 원인을 찾아서 이를 충분히 제거할 수 있다면 요구사항의 잦은 변화는 더 이상 문제가 아니게 됩니다.

이와 같이 “요구사항의 잦은 변화”라고 하는 동일한 문제에 대해 서로 다른 두 가지 해법이 존재합니다. 이 두 가지 해법 중 어느 것이 더 나은 방법일까요? 애자일 방법론에서는 당연히 후자가 나은 방법이라고 말합니다.

프로젝트 성공률을 높이기 위해 요구사항의 변화를 막는 것은 기본적으로 Win-Lose 게임입니다. 프로젝트가 성공하면 개발사는 돈을 받을 수 있어서 좋지만 개발을 의뢰한 고객은 프로젝트가 진행되는 동안 발생한 시장의 변화에 맞추어 요구 사항을 수정할 기회를 포기해야 하니까요. 게다가 시장이 변하지 않더라도 요구 사항은 수정될 수 있습니다. 왜냐하면 프로젝트가 진행되는 동안 시장에 대한 우리의 지식이 변하기 때문입니다. (코드가 바뀌어야 하는 이유 참고)

따라서 소프트웨어는 소프트해야 합니다.


3. 소프트웨어는 소프트한가?

소프트웨어가 소프트한게 좋다고 치고, 그럼 과연 소프트웨어는 실제로 소프트할까요? 이게 중요한 질문일 수 있죠. 하지만 이 질문은 사실 예/아니오 질문이 아닙니다. 정도(degree)의 문제입니다. 따라서 질문을 바꿔야죠.

“소프트웨어는 얼마나 소프트한가?”

이 질문에 대해서도 대답하기가 쉽지 않습니다. 왜냐하면 어떤 소프트웨어이냐에 따라 다르고, 우리가 프로젝트를 어떻게 수행 하느냐에 따라 다르기 때문이죠. 그래서 질문을 또 바꿔야겠습니다:

“소프트웨어는 얼마나 소프트해질 수 있는가?”

질문을 이렇게 바꾸면 답을 할 필요가 별로 없어집니다. 소프트웨어는 소프트해야 한다는 위 논의에 동의하기만 한다면, 이 질문에 대한 답이 없어도 질문을 보는 순간 우리가 뭘 어떻게 해야 하는지 감이 오기 때문이죠.

우리는 소프트웨어가 최대한 소프트해지도록 노력해야 합니다. 고객에게 소프트웨어가 소프트하지 않다는 인식을 심어주기 위해 노력할 것이 아니라, 양자가 어떻게 협업을 해야 소프트웨어가 주어진 상황 하에서 조금이라도 더 소프트해질 수 있는지 알아내기 위해 노력해야 합니다.

이상적인 얘기라고 생각하실지 모르겠습니다. 그럴지도 모르죠. 특히나 내부 고객을 상대하는 상황이 아닌 대다수의 SI 프로젝트에서는 꿈 같은 얘기일 수도 있습니다.

이게 가능하냐 안 가능하냐를 떠나서 우리가 지향할 바가 무엇이냐에 대한 얘기라고 생각해주시기 바랍니다.


4. 관련자료


저작자 표시
신고
< Newer     Older >

티스토리 툴바