IBM Korea Skip to main content
       IBM 홈    |  제품 & 서비스  |  고객지원 & 다운로드  |  회원가입  

Diagnosing Java Code : '스팩(specification)'이라는 줄타기를 하다.
목 차:
비용 및 이익
구현 내용은 사양이 아니다.
비용 효과적인 사양
단위 테스트는 사양이 아니다.
 
최종 효과
참고 자료
필자 소개
기사에 대한 평가
관련 dW 링크:
순화된 XP
IBM WebSphere Application Server로 마이그레이션하기: 변경을 위해 소프트웨어 설계하기
IBM WebSphere Application Server로 마이그레이션하기: 마이그레이션 단계
The Go-ForIt Chronicles: Memoirs of eXtreme DragonSlayers
US 원문 읽기
잘 정의된 스팩이 소프트웨어 시스템에 중요한 이유


Eric E. Allen
박사 과정, 자바 프로그래밍 언어 팀, Rice 대학교
2002년 1월

프로그램 사양은 모든 소프트웨어 프로젝트에서 중요하지만 시간이 많이 드는 부분이다. Eric Allen은 코드에 잘 정의된 사양이 왜 필요한지를 설명하고 첨단 프로그래밍 기법 뿐 아니라 전통적인 소프트웨어 엔지니어링 방식에 대해서도 장점 및 단점을 비교하며 살펴본다.

프로그램 사양은 신뢰성 있는 소프트웨어 개발에 중요하다. 잘 정의된 사양이 없으면 소프트웨어 시스템의 잘못된 작동을 진단하기가 어렵다. 그러나 많은 소프트웨어 시스템의 프로그램 사양은 허술하게 정의되어 있다. 더 나쁜 것은 프로그램 사양이 아예 없는 시스템도 많다는 것이다.

직관적으로 말해, 프로그램 사양은 프로그램의 행동을 기술해 놓은 것이다. 사양은 여러 형태를 취할 수 있지만, 하나의 스레드는 그 형태와 상관없이 모든 인스턴스에서 수행된다: 사양은 시스템이 올바로 작동하고 있는지를 알 수 있게 해주기 때문에, 일정 형태의 시스템 사양을 가지는 것은 필수적이다.

사양은 개발 중인 시스템의 안정성과 중요성 뿐 아니라 시스템 배치 후 수정이 얼마나 쉬운지에 따라 형식에 맞추어 정의될 수도 있고 느슨하게 정의될 수도 있다.

사양이 왜 중요한지와 왜 종종 무시되는지, 그리고 어떻게 상황을 개선시킬 수 있는지를 먼저 논의해보자.

정확성에 드는 비용과 이익의 균형을 맞추다.

마이크로 프로세서 설계의 세계에서 시스템은 개인용 컴퓨터에서부터 필수적인 의료 및 군대 시스템에 이르기까지 다양한 애플리케이션에 광범위하게 배치된다. 다음은 이 세계에서 당연하며 깰 수 없는 규칙이다. 배치후에 칩 설계를 수정하려면 엄청나게 비용이 많이 든다.

따라서 마이크로프로세서 사양이 보통 형식에 맞추어 작성되는 것은 놀라운 일이 아니다. 형식화된 사양은 자동적으로 해석되고 분석될 수 있다는 점에서 엄청난 이점을 가지고 있다. 마이크로프로세스의 경우 설계의 많은 측면이 올바른지가 자동적으로 입증될 수 있다.

소프트웨어에서의 유사성: 프로그래밍 언어

소프트웨어 세계에서 배치와 중대성 측면에서 마이크로스로세스와 가장 유사한 가공물은 프로그래밍 언어이다. 인기있는 프로그래밍 언어는 사소한 것에서부터 아주 중대한 수준의 시스템까지 모든 레벨의 시스템에서 수 많은 프로그램을 작성하는데 사용될 수 있다.

칩과 마찬가지로 사람들이 언어를 사용한 후에 그 언어의 설계를 바꾸려면 엄청난 비용이 든다. 기존 프로그램이 수정되고 재컴파일되어야 하기 때문이다. 따라서 프로그래밍 언어에 대한 사양은 다른 소프트웨어 시스템과 비교했을 때 형식에 따라 작성된 경우가 많다.

이 형식성은 구문의 경우 특히 중요하다. 실제로 모든 현대 프로그래밍 언어는 형식에 맞추어 명시된 구문을 가지고 있다. 대부분의 파서들은 그 문법을 읽고 산출물로 충분히 완성된 파서들을 만들어 내는 자동 파서 생성기를 사용하여 구축된다.

불행히도 언어의 의미론은 그렇게 엄격하게 명시되지 않는 경향이다. 그러한 엄격성이 불가능하기 때문은 아니다.

ML과 같은 언어들은 형식을 갖춘 의미론을 가지고 있으며 그 결과, 그에 관한 많은 정리가 입증되어왔고 특정 측면(예를 들면 유형 시스템 완전성과 같은)에서 그들의 정확성이 확인되었다. 그러나 ML과 같은 언어는 예외이다. 왜 그런지에 대해 두 가지 이유를 들 수 있다.

우선, 프로그래밍 언어 사양의 특성을 실제로 입증하는 것이 하드웨어 설계에서보다 훨씬 어렵기 때문에 형식화된 사양에 대한 요구가 적은 것이다. 대신 많은 언어가 산문체로 명시된다. 컴파일러 작성자와 같이 실제로 이를 사용할 대부분의 사용자에게는 이 산문체의 사양이 충분하다. 실제로 컴파일러 작성자는 종종 보다 덜 형식화된 사양을 좋아한다. 프로그램을 최적화할 여지를 더 많이 주기 때문이다. 언어의 또다른 사용자는 프로그래머들인데, 이들 대부분이 쉽게 이해할 수 있는 비형식화된 사양을 훨씬 더 좋아한다.

두번째 이유는 많은 언어가 프로그래밍 언어를 전공하지 않은 개인 개발자에 의해 "취미 삼아" 개발되었다는 점이다. 불행히도 이 개발자들이 프로그래밍 언어 의미론을 명시하기 위해 개발된 형식을 항상 알고 있는 것은 아니다.

불명확함 때문에 드는 비용의 예


그럼에도 불구하고 언어 사양의 불명확함 혹은 불일치 때문에 드는 비용은 매우 높고 이식성과 신뢰성을 떨어뜨리며 심지어는 보안상의 구멍을 가져오기도 한다. 오늘날 인기리에 사용되는 언어 몇가지를 살펴보면 사양의 상대적 정확도가 그 언어들에 어떻게 영향을 미쳤는지를 볼 수 있다.

C++ 언어 사양은 심지어는 구문 레벨에서도 불명확한 점이 많다. 또한 사양의 많은 부분이 구현에 의존하고 있다. 그 결과 C++ 프로그램은 한 플랫폼 외에서는 의도한대로 행동하지 않는 경우가 종종 있다.

Python 언어 사양은 구체적인 많은 부분을 구현에 맡기거나 정의하지 않은채 두었다. 결과적으로 Jython과 CPythoen과 같은 구현은 상호간에 동일한 행동을 제공해야 하는 만만챦은 과제에 직면하였다. 이 문제는 Python 언어가 상대적으로 단순하지 않았다면 (좋은 의미의) 더 악화되었을 것이다.

자버 언어에는 어떤 형식화된 사양 (ML의 사양과 유사함)도 존재하지 않지만 정확한 비형식적 사양의 개발에 많은 관심이 주어졌다. 자바 언어는 보통 JVM용 바이트코드로 컴파일되는데, 그 자체가 잘 명시되어 있다 (몇몇 형식 분석에 의해 그 사양의 불명확한 점이 일부 발견되기는 했지만). 또한 자바 API는 모두 JVM의 일부분으로 명시되어 있다. 그 결과 자바 코드의 이식성은 유례없이 높다.

여기서부터 우리가 얻을 수 있는 결론은 가능한한 정확한 사양을 가지는 것이 도움이 된다는 것이다. 그러나 사양에 문제가 있을 경우 가장 많은 비용이 드는 프로그래밍 언어의 세계에서조차 그러한 정확함은 드문데, 정확한 사양을 작성하는데 비용이 많이 들기 때문이다.

기업들은 시스템을 먼저 출범시키고 상세한 사양은 나중에 구체화하는 것이 (혹은 결코 구체화하지 않을 가능성이 더 높지만) 비용면에서 더 효과적이라는 점을 발견하였다. 의문의 여지 없이, 수명 주기가 짧고 배치 경로가 좁은 애플리케이션에 대해 정확한 전면적인 사양을 작성하는 것은 비용이 너무 많이 든다. 개발팀이 시스템에 대한 사양을 형식에 맞춰 작성하는 작업을 끝내기 전에 경쟁사들이 시스템을 출시할 수도 있다.

또한 고객 요구사항의 변경에 따라 대단위 사양이 업데이트되는 일은 매우 드물고, 따라서 무시된다. 전면적인 사양 작성에 비용이 너무 많이 든다면 개발팀은 소프트웨어를 명시할 때 어떤 방식을 취해야 할 것인가?

위 질문에 답하기 전에, 종종 선택되는 한가지 방식을 살펴보자. 그러나 이것은 가능한 것 중 실제로 최악의 방법이다.

구현 내용은 왜 사양이 될 수 없는가?

위의 방식들과 대조적으로, 수많은 소프트웨어가 구별할 수 있는 사양 없이 구현된다. 소프트웨어가 완성되면 이의 구현 내용이 사양으로 제시된다. I

다시 말해, 소프트웨어가 어떤 행동을 보여주든간에 그것이 명시된 행동이라고 말해지는 것이다.

이 방식은 변경되기 쉬운 일정 종류의 형식화된 안에 대해 작업하느라 개발자가 시간을 소비하지 않아도 되기 때문에 좋다고 주장하는 사람도 있을 것이다. 그러나 프로젝트 사양이 종종 변경되는 것은 사실이지만, 구현 내용은 여러 면에서 조잡한 사양이 되기 마련이다. 다음에 몇가지 이유를 들어 보겠다.

  • 구현은 임의적인 선택을 포함하고 있다.
  • 본질적으로 각 행동은 의도된 것이고 따라서 버그가 없다.

구현시 행해지는 선택중 많은 것이 임의적이다. 따라서 향후 다른 플랫폼에서 구현하려면 기존 구현 외에는 의지할 것이 없다. 개발자들은 구현이 필요로 하는 행위를 결정하기 위해 수많은 구현 상세를 힘겹게 살펴보아야 할 것이다. 보다 추상화되어 명시되어 있다면 그러한 행동을 결정하기가 훨씬 더 쉬워질 것이다.

또한 구현이 글자 그대로 자체 사양이 된다면 그 구현시 나타나는 어떤 행위도 버그로 인정하기가 불가능할 것이다. 사양을 만들지 않았기 때문에 나타나는 예측 못한 결과이기 때문에, 해롭거나 짜증나는 행위를 "정상적"이라고 하는 소프트웨어 업체를 우리는 얼마나 많이 봐 왔던가?

비용면에서 효과적인 사양

세번째로, 최초의 개발자에게 구현이 왜 사양 역할을 효과적으로 할 수 없는지의 확실한 이유는 그러한 구현이 아직 존재하지 않기 때문이다. 이 개발자들은 그들이 개발하고 있는 시스템에 대해 일부 행동 모델에 의존해야 하기 때문에 그 모델의 소스가 소프트웨어의 사양 역할을 할 수 있다.
.

이 점은 개발자들이 적절한 비용으로 어떤 종류의 사양을 사용할 수 있는지에 대해 일부 해답을 제시한다. 한 기능을 구현하는 방법을 결정하기 위해 개발자는 그 기능이 어떤 것일지 마음속으로 어느 정도의 모델을 가지고 있어야 하지만, 전체 애플리케이션에 대해 마음 속의 모델을 가질 필요는 없다.

즉 사양은 한 번에 한 부분씩 개발될 수 있다. 이렇게 하면 사양 개발이 더 쉬워질 뿐 아니라 고객이 변경을 요구할 때 보다 효과적으로 수정될 수 있다.

Extreme Programming (XP)에서 시스템에서 필요한 기능은 스토리 를 사용해 점진적으로 명시된다. 각 스토리는 시스템 행동의 한 측면을 간단하게 기술하고 있다. 예를 들어, Java IDE 사양에 포함될 수 있는 다음 스토리를 보자.

 

사용자가 편집기에 단어를 입력할 때, 자바라는 키워드가 나타나면 자동적으로 파란색으로 된다. 문자열과 글자의 오자는 초록색으로 , 코멘트는 빨간 색으로 나타난다.

믿건 말건간에, 자바 언어에서는 정리하기가 실제로 어려운 스토리인데 그것은 부분적으로 블록 코멘트의 몇몇 독특한 특성 때문이다. 개발팀의 속도에 따라 그 스토리를 두 개 이상의 소규모 스토리로 나누는 것이 좋을 것이다.

러나 이 스토리는 간단하고 명확한 언어로 작성된 짧은 스토리임에 주목하라. 따라서 필요할 때 분리하기 쉽고 사양의 부분들이 결합되는 것을 방지한다.

또한 스토리는 짧기 때문에 사양을 완전히 정비하지 않고도 업데이트할 수 있고 새로운 스토리를 추가할 수 있다. 따라서 스토리는 최종 제품에 대한 요구사항이 구현 과정 동안 종종 변경되는 산업 환경에서 특히 적합하다.

단위 테스트 역시 사양은 아니다.

사양이라는 주제를 마치기 전에 말하고 싶은 마지막 이슈가 있는데 단위 테스트에 관한 것이다. XP에서 단위 테스트는 한 생활 방식이다. 프로그래머들은 구현을 작성하기 전에 단위 테스트를 작성하기 시작하고, 기능의 새로운 측면 각각에 대해 더 많은 단위 테스트를 계속 작성한다.

소프트웨어 프로젝트에서 엄격한 단위 테스트를 수행하면 두가지의 큰 이점이 있다.

  • 문서화될 수 있다.
  • 갱신(refactoring) 프로세스를 촉진시킨다.

정적인 유형과 마찬가지로 단위 테스트는 실행시킬 수 있는 형식으로 된 문서라 할 수 있다. 단위 테스트는 이상적으로 구현의 모든 측면을 다루기 때문에, 그리고 기능이 제대로 작동하는지 확인하기 위해 간단한 방식으로 그 기능을 호출하기 때문에, 프로젝트에 새로 합류하거나 몇몇 코드를 새로이 유지보수하기 시작하는 프로그래머들은 다양한 기능성 컴포넌트들이 무엇을 하는지 알아 보기 위해 단위 테스트들을 살펴보는 것이 좋다.

단위 테스트가 문서화될 수 있다는 의견을 처음 들었을 때 많은 사람들은 회의적이다. " 프로그램이 작성된 것과 동일한 언어로 프로그램에 대한 문서를 어떻게 작성할 수 있습니까?"그러나 이 질문은 코드 문서화의 핵심을 놓친 것이다.

코드는 코드가 하는 일을 설명하기 위해 문서화되어서는 안된다. 코드 자체가 이미 그것을 설명하고 있다. 대신, 문서는 한 블럭의 코드가 왜 그것을 수행하는지를 설명해야 한다. 코드를 읽는 사람이면 누구나 코드가 작성된 언어에 이미 익숙할 것이다. 그렇지 않다면 어떤 언어로 쓰여진 문서라도 도움이 되지 않을 것이다.

그러나 한 블록의 코드가 프로그램의 나머지 부분과 어떻게 상호작용하는지가 항상 명확한 것은 아니고, 그것이 바로 문서가 필요한 이유이다. 코드를 읽는 사람은 그것이 작성된 언어에 익숙하기 때문에 (익숙해야 하기 때문에), 코드의 의도를 코드와 동일한 언어로 설명하는 것은 아주 타당한 일이다.

또한 단위 테스트는 갱신 프로세스를 촉진시킨다. 어떤 기능이 망가졌는지 알아 보기 위해 일군의 단위 테스트를 언제든지 코드에 실행시킬 수 있다면 프로그래머는 그렇지 았은 경우보다 훨씬 더 자신있게 코드를 갱신할 수 있다. 소개된 버그의 대다수가 즉각적으로 추적될 수 있다.

따라서 단위 테스트는 강력한 소프트웨어를 작성하고자 할 때 큰 이점을 가져다 준다. 사실 단위 테스트는 문서 형태로 되어 있고 (구축 단계에 이들을 포함시킴으로써) 자동적으로 집행될 수 있기 때문에 , 테스트 자체를 시스템에 대한 사양으로 사용하도록 제안하고 싶은 유혹을 느낄 만하다.

모든 시스템 레벨의 테스트를 통과하기 위해 어떤 유효한 구현 내용을 필요로 할지 모른다는 점에서 테스트를 사양의 일부로 하는 것은 타당한 일이다. 그러나 단위 테스트로 전체 사양을 구성하는 것에는 몇가지 심각한 단점이 있다.

우선, 한 시스템에 대한 테스트 세트는 필연적으로 불완전하기 마련이다. 얼마나 많은 테스트를 명시하든간에 우리가 서술할 수 있는 것보다 많은 입력 사항과 시스템 상태가 항상 존재한다. 우리는 "가장 합리적인" 범위를 명시함으로써 테스트들을 해석할 수 있지만, 그러한 범위는 종종 불명확할 것이다.

또한 단위 테스트는 본질적으로 특정 구현의 특성을 적용한다. 시스템이 구현되는 방식은 한가지 이상이 있기 마련이다. 따라서 단위 테스트를 사양으로 사용하면 특정 구현을 사양으로 사용할 때와 동일한 단점이 있다.

따라서 테스트를 사양 전체로 보지 말고 사양을 확충하는 것으로 보는 것이 가장 바람직하다.

이익이 비용을 보충하고도 남는다.


나는 여러분이 소프트웨어 시스템 설계시 가능한한 정확한 사양을 가질 필요가 있다는 결론에 도달했고, 사양을 모듈화하여 작성하는 XP 모델이 이 정의를 만드는 데 드는 비용과 이익이 균형을 이루도록 하는 지점을 볼 수 있기 바란다.

또한 구현을 사양으로 혼동할 때의 함정 뿐 아니라 단위 테스트로 여러분의 사양을 정의한다는 멋진 개념에 완전히 의존할 경우 발생하는 문제에 대해 내가 충분하게 입증했기를 바란다.

참고자료

필자소개

Eric Allen은 Cornell 대학에서 컴퓨터 공학 및 수학 학사 학위를 받았으며 Rice 대학의 자바 프로그래밍 언어팀에서 박사 과정을 밟고 있다. 학위를 마치기 위해 Rice 대학으로 돌아가기 전에 Eric은 Cycorp 사의 선임 자바 소프트웨어 개발자였고, 또한 JavaWorld의 자바 초급자 토론 포럼의 진행자이기도 하다. 그는 자바 언어에서 소스와 바이트코드 레벨 양쪽에서의 의미론적 모델 개발과 정적인 분석 툴에 관심을 가지고 있다. Eric은 또한 일반적인 런타임 유형을 가진 자바 언어의 확장판인 NextGen 프로그래밍 언어의 컴파일러 개발을 돕기도 했다.



이 기사에 대하여 어떻게 생각하십니까?

정말 좋다 (5) 좋다 (4) 그저그렇다 (3) 수정보완이 필요하다(2) 형편없다 (1)

  회사소개  |  개인정보 보호정책  |  법률  |  문의