본문 바로가기

SW LAB/Algorithm

Clean Architecture : (4장) 구조적 프로그래밍

 프롬스의 SWDEVLAB 

구조적 프로그래밍

 에츠허르 비버 데이크스트라는 1930년대 로테르담에서 태어났습니다. 2차 세계대전을 견디며 1948년에 수학, 물리, 화학, 생물에서 최고 점수를 받으며 고등학교를 졸업하고 1952년 3월, 21살의 나이로 네덜란드 최초의 프로그래머로서 암스테르담의 수학 센터에 취업합니다.

 1955년, 그는 이론 물리보다 프로그래밍에 대한 지적 도전이 더 큰 의미가 있다고 생각하고 장기적인 진로로 프로그래밍을 선택합니다. 1957년 마리와 데베츠와 결혼할 때, 자신의 직업을 기입해야 했는데, 프로그래머라는 직업이 인정되지 않아 이론 물리학자로 제출하게 됩니다.

 진공관 시대였던 이 때는 컴퓨터가 거대하고, 쉽게 손상되며, 느린 데다가 결과마저 믿을 수 없는.. 그래서 극도로 제한적으로만 사용될 때 였습니다. 입력은 종이테이프나 천공카드와 같은 물리적인 형태를 띠었습니다. 수정, 컴파일, 테스트를 반복하는 일은 최소 몇 시간에서 며칠이 걸렸습니다.

 즉, 데이크스트라는 원시적인 환경에서 위대한 발견을 해냅니다.

 

증명

 데이크스트라가 초기에 인식한 문제는 프로그래밍은 어렵고, 프로그래밍을 잘하지 못한다는 사실이었습니다. 프로그램은 단순할지라도 인간의 두뇌로 감당하기에는 너무 많은 세부사항을 기억하고 있어야 했고, 간과하면 실패를 하게 되었습니다.

 데이크스트라는 증명(Proof)이라는 수학적인 원리를 적용하여 이 문제를 해결하고자 했습니다. 그의 비전은 공리, 정리, 따름정리, 보조정리로 구성되는 유클리드 계층구조를 만드는 것이었습니다. 다시말해 프로그래머는 입증된 구조를 이용하고, 이들 구조르 코드와 결합시키며, 그래서 코드가 올바르다는 사실을 스스로 증명하게 되는 방식이었습니다.

 데이크스트라는 이렇게 하려면 단순한 알고리즘에 대해 기본적인 증명을 작성할 수 있는 기법을 보여줘야 한다는 사실을 깨달았지만, 이 연구는 상당히 힘들었습니다. 이 연구를 진행하며 goto 문장이 모듈을 더 작은 단위로 재귀적으로 분하는 가정에 방해가 되는 경우가 있다는 사실을 발견했습니다. 합리적으로 증명할 때 필수적인 기법인 분할 정복 접근법을 사용할 수 없게 된 것입니다.

 반면 goto 문장을 사용하면서 모듈을 분해해도 문제가 되지 않는 '좋은' 사용 방식도 있었는데.. if/else/then, do/while과 같은 분기와 반복이라는 단순한 제어 구조에 해당한다는 사실을 발견했습니다. 그는 이러한 제어구조가 순차 실행과 결합했을 때 특별하다는 사실을 깨달았습니다. 이러한 제어구조는 뵘과 야코피니가 2년 앞서 발견했는데, 모든 프로그램을 순차, 분기, 반복이라는 세 가지 구조만으로 표현한다는 사실을 증명하였습니다.

 모듈을 증명 가능하게 하는 바로 그 제어 구조가 모든 프로그램을 만들 수 있는 제어 구조의 최소 집합과 동일하다는 사실을 발견했고.. 그리고 구조적 프로그래밍이 탄생하게 됩니다.

 

해로운 설명서

 1968년 데이크스트라는 CACN 편집자에게 "goto문의 해로움(To To Statement Considered Harmful)" 라는 제목으로 편지를 보냈습니다. 그리고 세 가지 제어 구조에 대한 자신의 의견을 피력했습니다. 그리고 이 의견을 지지하는 자들과 반대하는 자들 간 10년간의 전쟁 끝에 데이크스트라가 승리하게 됩니다. 컴퓨터 언어가 진화하며 goto 문장이 사라졌기 때문입니다.

 현재 우리는 모두 구조적 프로그래머이며, 여기에는 선택의 여기가 없습니다. 제어흐름을 제약 없이 직접 전환할 수 있는 선택권 자체를 언어에서 제공하지 않기 때문입니다.

 자바의 경우 이름을 붙인 break문이나 예외가 goto문과 유사하다는 점을 지적할 수 있지만.. 목적지 범위를 함수 안으로 한정시키는 편입니다. 과거 포트란이나 코볼 같은 언어처럼 제약이 없는 것은 아닙니다.

 

기능적 분해

 구조적 프로그래밍을 통해 모듈을 증명 가능한 더 작은 단위로 재귀적으로 분해할 수 있게 되었고, 이는 결국 모듈을 기능적으로 분해할 수 있음을 뜻했습니다. 거대한 문제 기술서를 받더라도 고수준의 기능으로 분해하고, 다시 저수준의 함수로 분해하는 과정을 반복합니다. 그리고 구조적 프로그래밍의 제한된 제어 구조를 이용하여 표현할 수 있습니다.

 이들 토대로 1970년대 후반에서 1980년대에 걸쳐 구조적 분석(Structured Analysis)이나 구조적 설계(Strutured Design)이 인기를 끌었습니다. 이 기간에 많은 기법이 소개되었고, 대규모 시스템을 모듈과 컴포넌트로 나눌 수 있었습니다. 그리고 모듈과 컴포넌트를 입증할 수 있는 아주 작은 기능들로 세분화할 수 있었습니다.

 

엄밀한 증명은 없었다

 하지만 프로그램 관점에서 정리에 대한 유클리드 계층구조는 만들어지지 않았습니다. 그리고 대부분 프로그래머들은 하나하나 엄밀히 증명하는 고된 작업에서 이득을 얻으리라 보지 않았습니다. 결국 데이크스트라의 꿈은 빛이 바랬고, 사라졌습니다. 오늘날에도 이를 믿는 프로그래머는 거의 없습니다.

 하지만 유클리드 방식처럼 수학적인 증명만은 있는 것은 아닙니다. 상당히 성공한 또 다른 전략으로 과학적 방법(Scientific Method)가 있습니다.

 

과학이 구출하다

 과학은 근본적으로 수학과 다른데, 과학 이론과 법칙은 그 올바름을 절대 증명할 수 없기 때문입니다. 뉴턴의 운동 제 2법칙인 'F=ma' 또는 만유인력 법칙을 시연하고 소수점 이하 많은 자리로 측정할 수는 있지만 수학적으로 증명할 수는 없습니다. 언제든지 이 법칙이 잘못되었음이 밝혀질 가능성은 항상 열려 있습니다.

 이 점이 과학적 이론과 법칙이 지닌 본성입니다. 즉, 과학적 방법은 반증은 가능하지만 증명은 불가능합니다. 그럼에도 우리는 매일매일 이들 법칙에 모든 것을 다 겁니다. 자동차나 건물에 우르의 생사를 걸고 있는 것이지요.

 과학은 서술된 내용이 사실임을 증명하는 방식이 아니라 틀렸음을 증명하는 방식으로 동작합니다. 각고의 노력으로 반례를 들 수 없다면 목표에 부합할 만큼 참이라고 봅니다.

 결론은 수학은 증명 가능한 서술이 참임을 입증하는 원리라고 볼 수 있고, 과학은 증명 가능한 서술이 거짓임을 입증하는 원리라고 볼 수 있습니다.

 

테스트

테스트는 버그가 있음을 보여줄 뿐, 버그가 없음은 보여줄 수는 없다

- 데이크스트라 - 

 

 이 같은 사실은 수학적인 구조를 다루는 듯 보이더라도, 소프트웨어 개발은 수하걱인 시도가 아니라는 사실입니다. 오히려 소프트웨어는 과학과 같습니다..

 구조적 프로그래밍은 증명 가능한 세부 기능 집함으로 재귀적으로 분해할 것을 강요합니다. 그리고 나서 테스트를 통해 증명 가능한 세부 기능들이 거짓인지를 증명하려고 시도합니다. 이처럼 거짓임을 증명하려는 테스트가 실패한다면, 이 기능들은 목표에 부합할 만큼은 충분히 참이라고 여기게 됩니다.

 

결론

 구조적 프로그래밍이 오늘날까지 가치 있는 이유는 프로그래밍에서 반증 가능한 단위를 만들어 낼 수 있는 바로 이 능력 때문입니다. 또한 흔히 현대적 언어가 아무런 제약 없는 goto 문장은 지원하지 않는 이유이기도 합니다. 뿐만 아니라 아키텍처 관점에서 기능적 분해를 최고의 실천법 중 하나로 여기는 이유이기도 합니다.

 가장 작은 기능에서부터 가장 큰 컴포넌트에 이르기까지 모든 수준에서 소프트웨어는 과학과 같고, 따라서 반증 가능성에 의해 주도됩니다.

 아키텍트는 구조적 프로그래밍과 유사한 제한적인 규칙드을 받아들이고 활용해야 합니다.

 

관련글

내용이 도움이 되셨으면 공감 버튼 꼬옥 눌러주세요
본문을 퍼가실 경우 댓글을 달아주세요