IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  자바  >

사람을 위한 자동화: Continuous Inspection (한글)

소프트웨어 인스펙터(inspector)를 사용하여 수동 방식의 검사에서 탈피하기

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

샘플 코드


제안 및 의견
피드백

난이도 : 중급

Paul Duvall, CTO, Stelligent Incorporated

2007 년 5 월 15 일

새로운 프로젝트를 시작할 때, 제품을 실제로 릴리스 하기 전에 코드를 리뷰 할 계획도 세웁니다. 하지만, 납품(delivery) 스케줄이 다른 요소들 보다 우선할 때, 리뷰 단계가 가장 먼저 무시됩니다. 이러한 리뷰를 자동으로 수행할 수 있다면 어떨까요? 사람을 위한 자동화 시리즈, 첫 번째 글에서는 개발 자동화 전문가 Paul Duvall이 CheckStyle, JavaNCSS, CPD 같은 자동화 인스펙터들이 개발 프로세스를 어떻게 향상시키는지, 그리고 이것을 사용할 시기에 대해 설명합니다.

코드 검사는 다양한 형태를 취한다. 어떤 조직은 일반적인 피어 리뷰(peer review)를 사용하는데, 개발자 피어들은 코드를 분석하고 향상될 부분에 대한 그들의 생각을 제시한다. 어떤 조직들은 페어링(pairing)을 수행하는데, 한 사람이 유형을 정하고 다른 사람이 고급 디자인 결정을 구상하고 코드 향상을 제안하게 된다. 어떤 팀에서는 버전 관리 저장소로 코드를 전달하기 전에, "데스크 체크(desk check)"의 형태로 또 다른 개발자가 코드를 리뷰하게 된다.

한 조직이 코드 검사를 어떻게 수행하는지에 상관 없이 한 가지 확실한 것은 이들 모두가 수동 프로세스라는 점이다. 필자도 지난 몇 년 동안 알아낸 사실이지만, 수동 프로세스는 에러를 만들어 내기 쉽고 상황이 힘들어지면 간과되기도 한다. 하지만 소프트웨어 검사가 늘 수동 방식일 필요는 없다. 사실, 모든 오픈 소스 및 상용 소프트웨어 인스펙터들은 정적으로 코드를 분석하는데 사용될 수 있다. (따라서 정적 분석 툴로도 알려져 있다.)

소프트웨어 인스펙터를 사용하면 코드 검사는 Ant 또는 Maven 같은 빌드 툴을 통해 자동화 된다. 또한, 이러한 자동화를 통해 코딩 표준, 복잡성, 중복 같은 저급의 소스 코드 상세들은 머신이 담당한다. 이러한 책임 분야의 전환을 통해서 디자인과 장기적인 관리 문제 같은 보다 고급의 개발 측면에 집중하게 함으로써 수동적인 검사를 향상시킬 수 있다.

시리즈 소개
개발자로서, 사용자를 위해 프로세스를 자동화 하고 있습니다. 하지만, 정작 우리들 자신의 개발 프로세스를 자동화 할 수 있는 기회를 간과하고 있습니다. 따라서, 사람을 위한 자동화 시리즈에서는 소프트웨어 개발 프로세스를 자동화 하는 방법을 연구하고, 자동화를 적용할 시기방법을 설명합니다.

우리의 구원자 소프트웨어 인스펙터

고급 상용 툴부터 단순한 오픈 소스 툴에 이르기까지 소프트웨어 인스펙터는 다양하다. 개인적으로는 CheckStyle, CPD, JavaNCSS 등이 유용하다고 생각한다. (참고자료):

  • CheckStyle은 프로젝트의 사전 정의된 코딩 표준을 벗어나는 것을 보고한다.
  • CPD는 코드 중복을 보고한다.
  • JavaNCSS를 사용하여 팀은 복잡한 고급 코드 영역에 집중할 수 있다.
이러한 모든 툴들은 무료로 사용할 수 있고 Ant나 Maven 같은 빌드 플랫폼에 쉽게 결합될 수 있다. 결국 Continuous Integration (CI) 시스템으로 쉽게 통합될 수 있다.

Continuous Integration이란 무엇인가?

Continuous Integration (CI)은 팀이 피드백을 받고, 개발 사이클에서 오류를 탐지하여 픽스할 때를 기다리지 않고 지속적으로(continual basis) 향상 시키는 방식이라고 할 수 있다. (CruiseControl 같은) 툴은 백그라운드에서 실행되어 버전 관리 저장소로 폴링(poll)하여 변경 사항을 찾는다. 변경 사항이 발생하면, 이 툴은 Ant를 통해서 사전 정의된 빌드 스크립트를 실행한다. Continuous Inspection은 Continuous Integration 방식에서 활용되고 있다.

인스펙터 스타일 표준

필자는 여러 기업들의 위원회 같은 데에 참여하여 코딩 표준을 정의하느라 많은 시간을 보냈다. 어떤 경우에, 25 페이지에 달하는 코딩 표준 문서를 만들었지만 어떤 누구도 이를 지키는 사람이 없었다. 결국, 개발자가 two-spaces 규칙(four-spaces 규칙과 반대 개념)을 사용하는지, 그리고 매개변수가 final로 선언되어야 하는지의 여부를 놓고 논쟁하느라 코드 리뷰는 고통스러운 시간이 되어버렸다. 하찮은 검사는 소프트웨어 인스펙터에게 넘김으로써 귀중한 시간을 아낄 수 있었다.

CheckStyle 같은 자동화 소스 코드 검사 툴은 프로젝트의 코딩 표준에 기반한 규칙 세트를 실행할 수 있는 쉬운 방식을 제공한다. 더욱이, Eclipse 같은 IDE에서 CheckStyle 플러그인을 통해서 CheckStyle을 실행할 수 있고, CheckStyle은 Ant 태스크나 Maven 플러그인을 통해서 빌드 스크립트로 간단히 통합될 수 있다. CheckStyle이 발견한 규칙 위반은 리포트 폼에 디스플레이 되고, 이것을 통해 어떤 파일이 위반했는지를 알 수 있다. 또한, Ant와 Maven에서 규칙을 위반하면 구현이 실패하도록 CheckStyle을 설정할 수 있다.

예를 들어, Listing 1은 HTML 리포트를 생성하는 CheckStyle을 실행하는 Ant 빌드 스크립트 조각이다. failOnViolation 프로퍼티가 false로 설정되었다. 이 애트리뷰트가 true로 설정되면, 어떤 소스 코드 위반이라도 발견되면 빌드는 실패한다.


Listing 1. Ant에서 CheckStyle 사용하기
<taskdef resource="checkstyletask.properties" classpath="${checkstyle.jar}"/>
<checkstyle config="${basedir}/cs-rules.xml" failOnViolation="false">
  <formatter toFile="${checkstyle.data.file}" type="xml" />
  <fileset casesensitive="yes" dir="${src.dir}" includes="**/*.java" />
</checkstyle>
<xslt taskname="checkstyle"
  in="${checkstyle.data.file}"
  out="${checkstyle.report.file}"
  style="${checkstyle.xsl.file}" />

Listing 1에서 cs-rules.xml로 설정된 config 애트리뷰트는 해당 소스 디렉토리에 대해 반복적으로 실행할 규칙 파일들을 구분해 낸다. (fileset dir 애트리뷰트) xslt 태스크는 formatter toFile 애트리뷰트에서 생성된 파일을 수락한다. 이 태스크는 Listing 1에서 생성된 XML을 checkstyle.xsl XSL 파일을 사용하여 가독성 있는 HTML 파일로 변형한다. 이것은 CheckStyle 설치에 포함되어 있다.

Listing 2는 CheckStyle 규칙 파일의 일부이다. CheckStyle은 하나의 코드 베이스에서 120개 이상의 규칙들을 실행할 수 있다.


Listing 2. cs-rules.xml 파일에 정의된 CheckStyle Rules
<module name="Checker">
  <module name="TreeWalker">
    <property name="cacheFile" value="target/checkstyle.cache"/>
    <property name="tabWidth" value="4"/>
    <module name="ImportOrder">
      <property name="ordered" value="true"/>
      <property name="separated" value="true"/>
	</module>
    <module name="LineLength">
      <property name="max" value="120"/>
    </module>
    <module name="FileLength">
      <property name="max" value="400"/>
    </module>
	<module name="UnusedImports"/>
  </module>
</module>

각각의 CheckStyle 규칙은 모듈의 일부이다. 예를 들어, LineLength 모듈은 모든 라인이 120 문자 이하가 되어야 하고 그렇지 않을 경우 CheckStyle은 에러를 만들어 낸다는 것을 규정하고 있다.

여러분은 CheckStyle을 커스텀 규칙으로 확대할 수 있고 코딩 표준도 쉽게 적용할 수 있다. 더욱이 이 모든 것은 자동화 된다.

그림 1은 Listing 1에 나온 xslt 태스크를 사용한 Ant에서 생성된 CheckStyle 리포트 예제이다.


그림 1. CheckStyle HTML 리포트
CheckStyle HTML 리포트
IDE에 대해서

이러한 검사들은 IDE에서 실행될 수 있다. 이것이 사실이기도 하고 매우 권장할 만한 사항이지만, 개별 머신에서 소스 코드에 대해 (Ant 같은 툴을 사용하여) 일반 규칙 세트를 실행하도록 하는 것도 일관성 유지에 도움이 된다.

CPD를 이용한 중복 검사

객체 지향 프로그래밍의 근본적인 목표 중 하나는 다른 정황에도 적용할 수 있는 재사용 가능한 객체들을 만들어서 재사용을 활용하는 것이다. 하지만, 결국에는 카피&페이스트(copy-and-paste) 프로그래밍이 사용되고 "재사용"인 것처럼 위장된다. 개발자가 재사용 가능한 컴포넌트를 알지 못해서 이러한 일이 발생하기도 하고, 때로는 "빠른 픽스(quick fix)"를 제공한 결과이기도 하다. 결국, 여러분이 수정을 해야 한다면, 모든 카피들과 변수들에게 이 모든 사항들을 적용해야 한다. (툴이 없이는 매우 어려운 작업이 된다.) 이러한 수동적인 방식은 관리 업무만 고통스럽게 만들고, 오류를 지나치거나 심지어는 오류를 불러들일 수도 있다.

대중적인 오픈 소스 정적 분석 툴인 PMD의 일부인 CPD는 코드 베이스에서 중복 라인의 수를 보고한다. 더욱이, CPD의 토큰 임계치는 설정 가능하며, CPD가 코드의 중복 라인을 알리는 방식을 다양하게 설정할 수 있다. 예를 들어, 임계치를 100 토큰으로 설정함으로써, CPD는 최소 100 토큰이 중복된 경우에만 리포팅 하게 된다. 하지만, 명심해야 할 것은, 소스 코드에는 어느 정도의 중복이 있다는 점이다. CPD는 팀에게 상당한 코드 중복 부분을 검사하는 수단을 제공하고, 이 부분에서 리팩토링 같은 수정 작업이 취해질 수 있다.

Listing 3은 Ant에서의 CPD 실행 모습이다. CPD 태스크에서 필요한 첫 번째 옵션들 중 하나는 minimumTokenCount 애트리뷰트이고, 이것은 비교할 토큰의 수를 구분한다. (최소 값은 하나의 토큰이다.) 또한, identifier와 literal 같은 특정 코드 옵션들을 무시하도록 CPD를 설정할 수 있다. 이 예제에서 Ant fileset 유형은 어떤 파일들을 CPD가 분석해야 하고 무시해야 하는지를 나타낸다.


Listing 3. Ant에서 CPD 사용하기
                
<taskdef name="cpd" 
  classname="net.sourceforge.pmd.cpd.CPDTask" classpathref="pmd.classpath" />
  <cpd minimumTokenCount="100" 
        format="xml"
        language="java"
        ignoreIdentifiers="true"
        ignoreLiterals="true"
        outputFile="${basedir}/cpd.xml">
        <fileset dir="${src.dir}">
          <include name="**/*.java" />
          <include name="**/*.jsp" />
          <include name="**/*.xml" />
          <exclude name="**/*Test*.java" />
        </fileset>
  </cpd>

그림 2에서 보듯, cpd.xml은 Listing 3에서 outputFile 애트리뷰트를 사용한 아웃풋이다. 조만간 필자는 XSL을 CPD에 추가하여 HTML 리포트를 생성할 것이다.


그림 2. 코드 중복 오류를 나타내는 CPD XML 아웃풋
CPD XML 리포트

대부분 카피&페이스트 위반으로 생긴 코드 중복을 직접 찾아내는 것은 매우 어려운 일이다. 하지만, CPD 같은 툴을 사용하면 중복된 코드를 빠르게 발견할 수 있다.

경로(path)란 무엇인가?

소스 코드 경로는 제어 흐름 문으로도 알려져 있고, 메소드 안에서 그 흐름을 변경하는 코드를 가리킨다. if 문 같은 조건문과 whilefor 같은 루핑 구조가 해당한다.

JavaNCSS를 사용한 복잡성 검사

한 메소드 내에 경로의 수가 늘어나면 같은 메소드를 이해하고 관리하는 어려움도 커진다는 연구가 있다. 결국, 코드를 이해하고 관리하기 어려워질수록, 결함도 쉽게 생기게 된다.

JavaNCSS는 주석이 달리지 않은 소스 문(또는 코드 라인)의 수와 분석된 모든 메소드의 순환 복잡도(cyclomatic complexity) 같은 다양한 코드 측정 결과를 제공하는 무료 툴이다. Listing 4는 JavaNCSS의 사용법을 보여주고 있다. 여러분도 보다시피 그다지 어렵지 않다. JavaNCSS가 소스 코드를 포함하고 있는 디렉토리를 가리킨다.


Listing 4. Ant에서 JavaNCSS 사용하기
<path id="javancss.classpath">
  <fileset dir="${lib.dir}" />
</path>
<taskdef name="javancss" classpathref="javancss.classpath"
  classname="javancss.JavancssAntTask">
</taskdef>
<javancss srcdir="${src.dir}"
      generateReport="true"
      outputfile="${javancss.report.dir}/javancss_metrics.xml"
      format="xml"/>

대부분의 소프트웨어 인스펙터와 마찬가지로, XSLT를 통해서 HTML 리포트로 쉽게 변형될 수 있도록 XML 파일이 생성된다. (그림 3)


그림 3. JavaNCSS HTML 리포트
JavaNCSS HTML 리포트

애플리케이션의 코드 복잡성을 이해한다고 해서 모든 문제가 해결된 것은 아니다. 사실, 어떤 경우에는, 복잡성 정도가 잘못 파악될 수도 있다. 예를 들어, 어떤 툴은 switch 문에 큰 값을 준다. 하지만 JavaNCSS 같은 툴을 사용하면 더 높은 복잡성을 보이는 영역들을 줄이는데 도움이 되고, 궁극적으로 코드에 대한 이해도와 관리를 향상시킬 수 있다.




위로


모든 변경 사항들에 대한 검사를 통해 결함 파악하기

팀 멤버가 버전 관리 저장소에 대한 변경 작업을 하면 코드는 수정된다. 그런데 어떻게 바꾸었는가? 수정된 코드는 카피&페이스트 작업의 희생양인가? 복잡성이 늘어났는가? 이를 알 수 있는 유일한 방법은 모든 체크인 (check-in)에 소프트웨어 인스펙터를 실행하는 것이다. 더욱이, 위험 부담에 대한 피드백을 받는 것이 자동 체크 수행 시 코드 베이스의 건전성을 유지하는 유일한 방법이다!

CI 에서의 Cruise'n

CruiseControl은 자바™ 커뮤니티에서 가장 많이 사용되는 오픈 소스 CI 툴 중 하나이다. 이 툴은 백그라운드에서 실행되고, CVS 같은 버전 관리 저장소를 폴링(poll)하도록 설정된다. 소스 코드 변경이 탐지될 때(누군가가 코드로 체크인 할 때) CruiseControl은 소스의 체크아웃을 실행하고 사전 정의된 빌드 스크립트를 실행한다.

결과적으로, 팀은 버전 관리 저장소에 변경이 이루어질 때마다 CheckStyle, CPD, JavaNCSS 같은 소프트웨어 인스펙터를 실행할 수 있다. 이 기능은 팀이 일정 기간에 검사를 수행할 수 있도록 하고, 대부분의 CI 툴들처럼, 팀은 리포트, 이메일, 심지어 Ambient Orb (그림 5) 같은 장치를 사용하여 피드백을 만들 수 있다.

Listing 5는 CruiseControl 설정 파일(config.xml)을 사용하여 CruiseControl 대시보드에 CheckStyle 리포트 결과를 디스플레이 한다. 기타 소프트웨어 인스펙터는 비슷한 신택스를 사용하여 결과를 CruiseControl 대시보드에 나타낸다.


Listing 5. CruiseControl을 사용하여config.xml에 CheckStyle 기록하기
<listeners>
  <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
</listeners>
<modificationset quietperiod="30">
  <svn RepositoryLocation="http://www.qualitylabs.org/svn/ambientorb"
    username="[username]"
    password="[password]"
  />
</modificationset>
<schedule interval="60">
  <ant anthome="apache-ant-1.6.5" buildfile="build-${project.name}.xml"/>
</schedule>
<log>
  <merge dir="merge dir="checkout/${project.name}/_reports/checkstyle" />
</log>
            

그림 4는 CruiseControl과 CheckStyle을 사용하여 생성된 리포트 예제이다. CruiseControl을 구성하여 CPD와 JavaNCSS 같은 툴에서 나온 리포트를 공개하고 이러한 리포트를 소스 코드 변경이 있을 때마다 실행하여, 팀은 다음 사이클을 기다리는 대신 실시간으로 코드를 향상시킬 수 있다.


그림 4. CruiseControl에서의 CheckStyle 리포트
CruiseControl에서의 CheckStyle

끊임없이 움직이는 피드백

CI 툴에서 지속적으로 실행되는 소프트웨어 인스펙터의 가장 큰 장점은 팀이 마음대로 사용할 수 있는 공지 방식이 있다는 점이다. 가끔 빌드가 실패한 것은 아니지만, 무엇인가 변경되어, 조만간 정정 액션이 수행되어야 할 경우가 있다. 예를 들어, Ambient Orb 같은 장치를 설정하여 코드 복잡성이 증가하거나 특정 코딩 표준을 위반할 경우 색깔이 변하도록 할 수 있다.

Listing 6은 Ambient Orb Ant 태스크와 Ruby 스크립트를 사용하여 20개 이상의 클래스들이 300 Source Lines Of Code (SLOC)를 초과할 경우 색깔을 바꾸도록 할 수 있다. 이 경우, 클래스가 이 조건에 해당하면 ORB의 색깔을 magenta로 바꾸고 애니메이션을 crescendo로 바꾸도록 했다.


Listing 6. CruiseControl과 Ambient Orb에 대한 Ant 빌드 파일
  <target name="checkSloc" >
    <exec dir="${basedir}" executable="cmd.exe">
      <arg line="/c ${config.dir}/javancss/SlocThreshold.rb 
          ${reports.javancss.dir}/javancss_metrics.xml 20 ${javancss.file}"/>
    </exec>
    <available file="${basedir}/${javancss.file}" property="sloc.exceeded"/>
    <antcall target="notifyOrb" />
  </target>

  <target name="notifyOrb" if="sloc.exceeded">
    <taskdef classname="org.qualitylabs.ambientorb.ant.OrbTask"
     name="orb" classpathref="orb.class.path"/>
    <orb query="http://myambient.com:8080/java/my_devices/submitdata.jsp"
      deviceId="AAA-9A9-AA9"
      colorPass="green"
      colorFail="magenta"
      animationPass="none"
      animationFail="crescendo"
      commentFail="SLOC+Exceeded" />    
  </target>

그림 5는 코드 베이스에 너무 많은 클래스들이 있을 때 ORB의 모습이다.


그림 5. Ambient Orb
Orb Code Duplication

이러한 Ambient Orb 공지로 인해 필자는 무수한 이메일을 받지 않아도 된다. 그저 SLOC Threshold Orb를 보고 얼마나 큰 클래스들이 있는지를 빠르게 파악할 수 있고, 리팩토링을 결정한다. 물론, 소프트웨어 인스펙터와 Ambient orb를 결합하면 무한한 가능성이 있음은 두말하면 잔소리이다.




위로


가능하면 자동화 하라!

매우 많은 소프트웨어 인스펙터들이 존재한다. 이 글에서 소개한 세 가지는 개인적으로 좋아하는 것들이고, JDepend, PMD, FindBugs 같은 툴들도 매우 유용하다. (뒤에 두 개의 인스펙터에 대해서는 developerWorks에서 이미 다루었다.) Continuous Inspection 프로세스가 자리가 잡히면, 새로운 인스펙터를 사용하는 것은 간단하다.

Continuous Inspection은 수동 방식의 소프트웨어 검사를 줄여주지도 않고, 줄여서도 안된다. 하지만, 버전 관리 저장소에 생긴 모든 변경 사항에 대해서 자동화 된 검사 유틸리티를 실행함으로써, 수동 방식의 검사가 매우 생산적이고 효율적으로 변할 수 있다. 더욱이 Continuous Inspection은 프로젝트의 맨 끝까지 기다리지 않고 모든 단계에서 위험 부담을 줄여나간다.

다음에는, CruiseControl, Luntbuild, Continuum 같은 보다 흥미진진한 Continuous Integration 툴을 소개하도록 하겠다.

기사의 원문보기





위로


다운로드 하십시오

설명이름크기다운로드 방식
Software Inspection examples in Antj-ap08016.zip2MBHTTP
다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기

토론


필자소개

Paul Duvall은 Stelligent Incorporated의 CTO이다.UML™ 2 Toolkit Toolkit을 공동 집필했으며 곧 출간될 Addison-Wesley Signature Series, Continuous Integration: Improving Software Quality and Reducing Risk의 공동 저자이다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의