본문 바로가기

차세대 소프트웨어공학

1부터 100까지 합을 구하라

프로그래밍을 하는 분들이 다 쉽게 맞힐 수 있는 퀴즈로 시작해봅니다.

여러분은 컴퓨터 프로그래머입니다. 동료 중에 한명이 1부터 100까지 합을 구해달라고 요청했습니다. 자 여러분은 어떤 프로그램을 만드시겠습니까?
가정1. 어떤 언어를 써도 무방합니다.
가정2. 시간에 대한 제한도 없습니다.
가정3. 어셈블러가 효율이 좋다던가 하는 관점은 잊어주세요.


이렇게 단순하고 간단한 프로그래밍 문제를 퀴즈를 냈는지 궁금하실 겁니다. 이 문제에 대해서는 대략 3가지 정도의 방식이 있습니다.

방식1. 고민하지 말고 일단 다 더하고 봅니다.

sum =  1+ 2 + 3 + ............ + 100

방식2. 프로그램이니 for, while loop를 이용합니다.

for(i=1;i=<100;i++) sum += i

방식3. 수학을 이용해서 최적화된 방법을 구한다. 수학자 가우스가 선생님의 과제를 손쉽게 풀었던 방식으로 알려져 있습니다.

sum = 100 * (100+1)/2
일반식 : sum = n(n+1)/2

1 + 100 = 101
....
50 + 51 = 101
51 + 50 = 101
...
100 + 1 = 101
==
1과 100의 합인 101이 총 100번 이므로 절반인 100/2 만큼 곱하면 됩니다.

http://user.chollian.net/~lyms85/%BC%F6%C7%D0%C0%DA/Gauss.htm


자, 이제 이 3가지 방식에 대해서 평가를 해 봅시다.

평가1. 누가 동료의 요청에 가장 적절하게 대응했을까요?
평가2. 누가 정말 좋은 프로그램을 작성했을까요?

대부분 개발자 또는 프로그래머들은 웃기는 평가라고 생각하시겠지만 방식1이 가장 적절한 개발을 했다고 생각합니다.  동료의 요청인 1부터 100까지 합을 구해달라는데 가장 충실했기 때문입니다. 그리고 시간적으로 보면 방식1이 가장 적은 시간을 사용할 가능성이 많습니다.

그렇다면 왜 방식2와 방식3은 적절한 개발이 아니라고 생각할까요?
방식2와 방식3은 단순한 계산 방법을 일반화된 방법으로 풀고 있습니다.  프로그래밍 강의나 강좌를 들으신 분들은 방식2로 사고하는 것을 배우셨을 겁니다. 방식3은 알고리즘이나 수학적 방법론을 배우신 분들은 다들 아실겁니다. 방식1이 문제 그 자체에 집중했다면 방식2와 방식3은 문제의 일반화에 집중한 것입니다.  100까지가 아니라 그 숫자가 어떤 자연수라도 더하는 프로그래밍을 요구했다면 방식2와 방식3이 적절한 개발이었을 수 있습니다.

방식2와 방식3은 프로그래밍 개념인 시간복잡도(Time complexity)에 대해서 다루고 있습니다. 시간복잡도는 알고리즘을 상대적으로 평가하는 기준으로 어떤 프로그램의 효율성을 측정하며, 개선의 방향을 잡을 수 있습니다.
우리의 퀴즈에서 방식2는 O(n)의, 방식3은 O(1) 시간복잡도를 가집니다.
여기에 중요한 패러독스가 숨어있습니다시간복잡도는 프로그램의 효율성을 측정하는데, 대상이 컴퓨터가 처리하는 명령에 관한 것이지 결코 사람과 문제에 대한 것이 아닙니다. 요청을 한 동료의 관점에서 보면 효율성은 컴퓨터가 어떻게 계산하고 처리하는지가 아니라5050 이라는 답을 줄 수 있는냐, 그 답을 주는데 걸린 시간은 얼마인가에 있습니다. 방식2나 방식3을 먼저 떠 올리셨다면 효율의 관점이 컴퓨터가 일하는 방식에 있고 사람에 있지 않다는 뜻입니다.

읽을거리
  http://ko.wikipedia.org/wiki/알고리즘_분석
  http://ko.wikipedia.org/wiki/O표기법
  http://ko.wikipedia.org/wiki/알고리즘

이제, 1부터 100까지 더하는 프로그램이라면 방식3이 가장 빠르게 코딩해서 결과까지 출력할 수 있다는 분들이 많을 것입니다. 그 점에 대해서는 동의합니다. 프로그래밍을 배우면서 수도 없이 들어봤던 문제이고 방법이기 때문에 그렇습니다. 대부분 고교 수학에 집합에 관한 것은 여러번 본 기억이 있는 것처럼, 대부분 이 문제는 프로그래밍 언어나 과목의 앞부분에 있습니다. 익숙하고 이미 알려진 문제이기 때문에 방식3을 생각하시거나 방식2를 자연스럽게 떠올리실 수 있는 것입니다.

문제를 조금 바꾸어서 "1부터 100까지 합을 더한다"는 것을 우리가 동료에게 요청받은 블랙박스라고 생각해봅시다. 이 블랙박스에 어떤 문제가 들어있을지 모릅니다.

이 블랙박스를 이렇게 정의해보면 어떨까요?
"1부터 100까지 소수(Prime Number)의 합을 구해라달라"


여러분은 방식3번으로 바로 프로그래밍 하실수 있습니까? 
천재입니다.

방식2로 바로 프로그래밍을 하실 수 있습니까?
이미 이런 비슷한 문제를 풀어보았거나 소수를 구하는 알고리즘에 대해서 많이 고민하신 분이 아니라면 정말 훌륭한 프로그래머라고 생각합니다.

저는 일단 방식1을 이용해서 해보겠습니다.

sum = 2 + 3 + 5 + .... + 97

그리고 소수의 일반적인 성질을 이용하기 위해서 방식2로 이용하겠습니다. 숫자 100까지의 문제는 방식2로 손쉽게 해결이 가능합니다. 그러나 방식3은 시도하지 않을 듯 합니다. 왜냐면 방식3과 같은 일반적인 공식을 만들 수 있으면, 거의 노벨상감이거나 100만 달러 상금을 받을수도 있기 때문입니다.

읽을거리
  http://ko.wikipedia.org/wiki/소수_(수론))

이번에는 바뀐 문제에 대해서 처리 시간에 대해서 생각해봅시다.

방식1은 대략 1분 이내면 답을 구할수 있습니다. 약간의 오차도 있겠지요.


방식2는 대략 10분 이내라고 생각됩니다. 좀 생각할 것이 있지요. 루프를 돌아아야 하고, 덧셈도 해야 하고, 현재 숫자가 소수인지 판별하는 함수를 만들어야 하고, 실제 동작을 잘 하는지도 봐야 겠죠.


방식3은 대략 10년 이상이 소요될 것입니다. 대수학자들도 풀지 못한 문제이기 때문이죠.

지금까지 살펴본 예들은 기껏해야 들어있는 알고리즘이나 로직이라고 불리는 것이 기껏해야 2-3개 정도입니다. 문제가 가지고 있는 알고리즘이나 로직이 조금 복잡한 10개 이상이 우리가 풀어야할 블랙박스라면 어떤 방식을 사용하는 것이 좋을까요? 블랙박스 안에 들어있는 여러 개의 알고리즘이 처음 보는 문제라면 ?

여기서 중요한 개념들을 마주하게 되었습니다. 프로그래밍이라고 하는 것이 단순히 코딩만을 하는 것이 아니라는 점입니다. 기계와의 대화라는 관점에서 조금 벗어나 지식이라는 관점으로 옮겨보지요. 우리가 1부터 100까지 더하는 문제는 이미 초등학교 수준의  완성된 지식체계입니다. 무한하지 않은 자연수 N을 더하는 문제도 고등학교나 대학교 수준의 거의 완성된 지식입니다. 이 정도 수준은 대부분 상식이라고 부르기도 합니다. 그러나 우리가 일상에서 마주쳐야 하는 프로그래밍 또는 개발의 문제들은 어쩌면 처음 보고 개념도 낯선 문제들이 많습니다. 이런 문제에 접할 때 정규과목으로 프로그래밍을 배웠던 사람들은 먼저 방식2와 방식3을 고민합니다. 그리고 요구분석과 설계라고 부르는 단계로 푹 빠져 드는 거지요. 분석과 설계를 하는 여러분을 보고, 100까지 더해달라고 요청한 동료는 자리에 돌아가서 탁상용 계산기로 문제를 해결할 수도 있겠지요.


또 중요한 개념은 프로그래밍과 개발의 영역 또는 개념의 문제입니다. 프로그래밍은 대부분 컴퓨터에게 효율적으로 일을 시키는 방식을 다룬다면, 개발은 사람들이 요구하는 것을 컴퓨터에게 시키고 그 결과를 다룹니다. 일반적인 독립적인 컴퓨팅에 관한 주제들은 거의 완성단계에 이르렀다고 생각하면, 우리가 프로그래밍을 통해서 새롭게 개척할 분야는 거의 없습니다. 그러나 컴퓨터에게 시켜야 하는 일은 아직도 무한대에 가깝게 남아있습니다. 

평가2에 대해서 아직도 방식3이 가장 좋은 프로그램이라고 주장하시는 분이 남아 계실거라 생각합니다. 충분히 동감합니다. 그러나 최신의 컴파일러 이론이나 동향에 따르면 방식3보다는 방식1이 더 좋다고 합니다. 전문적인 영역이라 거기다가 영어라서 아래 읽을거리를 참고해주세요.
읽을거리
 
http://en.wikipedia.org/wiki/Loop_optimization
  http://blog.emptycrate.com/node/323

이 문제에 대해서는 동일한 이슈가 컴퓨터업계에서 판가름이 났다고 생각됩니다. 프로그래밍이 아닌 개발의 입장에서 보면, 방식1, 방식2를 사용하는 것이 전혀 이상하지도 부끄럽지도 않습니다.

관련 분야의 변화를 예상하지 못하는 혁신은 실패로 끝날 가능성이 높다. 기하급수 경제에서는 기술적 진보가 빨리 진행되기 때문에 머지않아 신기술에 의해 폐기될 프로젝트는 피해야 한다. 컴퓨터업계만 해도 PC에 들어가는 범용 칩의 성능을 뛰어넘으려 했던 수많은 특수목적용 칩이 그대로 매장당하고 말았다. 아무리 개선된 특수 칩을 내놓아도 18개월마다 100%씩 가격대비성능을 높이는 범용 칩의 엄청난 발전속도를 따라잡을 수 없었던 것이다.
- 혁신이란 무엇인가, 96쪽

이제 긴 글을 끝마칠때가 되었네요. 아주 간단한 퀴즈로 몇 가지 생각할 쟁점들을 뽑아냈습니다.

프로그래밍과 개발의 차이란 무엇인가?
어떤 프로그램이 적절한가?
어떤 프로그램이 좋은 프로그램인가?
개발이란 사람들과 대화한다
프로그램은 기계와 대화한다
개발과 프로그램은 지식의 축적이 필요하면, 결과로 지식이 더욱 축적된다.

앞으로 이어지는 다른 글들에서 이런 문제들을 가지고 계속하도록 하겠습니다.