블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2013. 1. 28. 09:05 Dev Environment/Build System

참조의 원문에 대해서 테스트 해하고 글을 정리해 본다. JavaScript에 대한 빌드 자동화를 ant로 하는 방법을 알아보자.


Javascript코드에 대해 Ant를 이용하여 Java의 Maven처럼 compile -> test -> build를 자동으로 수행할 수 있는 방법을 소개하고 있다. 하지만 현재는 gruntjs를 통하여 본 글에서 수행하였던 것을 보다 더 쉽게 할 수 있다. gruntjs에서 하나 단점은 shell command 호출인데 grunt-jasmine-task를 통해  극복하였다. 


1) JavaScript 대응 테스트 & 빌드자동화 도구들

  - 구문오류 체크 : JSLint / JSHint 

  - 유닛 또는 행휘 테스트 : Jasmine 또는 QUnit

  - API 문서 생성 : JSDoc

  - JS 파일압축 : YUI compressor 또는 Uglify.js 

  - 위의 내역들 빌드 통합 수행 : Ant


각 내역들에 대해서 순차적으로 수행하는 것을 Ant로 만들어 보도록 한다 


2) Ant로 구현한 Build Automation 구조

  - GitHub 소스 : git clone https://github.com/creynders/Build-JS-example.git  수행하여 로컬에 내려 받는다 

  - Ant로 하다 보니 1)에서 필요로 하는 모든 프레임워크 라이브러리를 다운로드 받아 놓아야 한다   

   

  

  - 디렉토리 구조 

    + bin : ant의 destination 디렉토리, 배포되는 최종 .js 파일이 위치함 

    + docs : API 문서 생성 디렉토리 

    + lib : 3-rd party 도구들 

    + specs : unit test 파일 존재 (test 파일이 specification 즉, 명세라는 표현이 맘에 든다)

    + src : 원본 소스 


3) 도구 설명

  - Apache Ant : 의존관계를 만들어서 타겟소스에 대하여 빌드를 수행케 하는 command-line 도구 (다운로드)

  - JSHint : JSLint 기반의 자바스크립트를 위한 code 품질 측정 도구. 에러나 문제가능성 있는 것을 찾아줌 (다운로드)

  - JSDoc Toolkit : HTML (XML, JSON, TEXT) 포멧으로 자바스크립트 애플리케이션에 대한 자동 문서 생성 도구 (다운로드)

  - YUI compressor : 압축을 통하여 네트워크 전송 성능을 높여준다. (다운로드)

  - Jasmine : 자바스크립트 코드 테스트를 위한 행위지향 개발 프레임워크(behavior-driven) (다운로드)

  - PhantomJS : 자바스크립트에 대해서 브라우져 없이(without GUI client) 없이 브라우징이 가능토록 해준다 (다운로드)

    + 즉, HTML 파일의 parse & rendering을 해준 다음 수행하고 결과값 읽고 ant에게 전달한다 (Headless WebKit)

    + OS 버전에 맞는 것을 다운로드 받은후 path를 잡아준다

    + 좀 더 쉽게 사용할 수 있도록 casperjs 도 있다. (요걸 사용하는게 좋을듯)


4) 소스 빌드 프로세스 (순서)

  - 원본 소스는 3개 존재 : buildexample.js, Baz.js, Foo.js

    + buildexample.js에서 namespace를 정의한다 

  - 모든 .js 파일에 대해 JSHint를 통해서 QA tool을 수행한다 

  - unit test를 수행한다

  - 3개의 개별 .js 파일을 1개의 .js 파일로 통합한다

  - 한개의 파일을 축소된(minified) .js 파일로 나눈다 

  - API 문서를 생성한다 

  - 통합하고 축소화한 파일명칭과 API 문서에 version number를 사용한다 


5) build.xml 작성하기 

  * properties : 상수 속성값을 설정. build.properties

  * tasks : ant 수행전 전처리 환경 내역들 

  * targets : 각 단계에 대하여 ant에 task로 구분하여 설정. build.xml


  - 버젼 (Version Number)

    + version.txt 파일을 읽는다 

    + 테스트 : ant version

<target name="version">
    <loadfile property="version.old" srcFile="version.txt" />
    <input message="Current version number is ${version.old}. Please enter the new version number:"
        defaultValue="${version.old}" addproperty="version"/>
    <echo file="version.txt" message="${version}" />
</target>


  - 속성 선언(Properties Declaration)

    + build.properties 파일을 사용한다 

    + build.uer.properties에 속성 재정의 한다 

<target name="properties">
    <tstamp>
        <format property="timestamp" pattern="yyyyMMddHHmmss"/>
    </tstamp>
    <!-- allow user-specific overrides -->
    <property file="build.user.properties"/>
    <property file="build.properties"/>
</target>


  - 빌드 디렉토리 생성 

   + build 디렉토리 생성한다 : 생성 temporary 파일이 위치한다. 빌드과정이 성공하면 bin에 파일이 위치한다.

<target name="create_build" depends="properties">
    <echo>Creating build...</echo>
    <delete dir="${dir.build}" />
    <mkdir dir="${dir.build.current}" />
    <echo>Finished.</echo>
</target>


  - 파일 하나로 합치기 (Consolidation)

   + src 디렉토리의 buildexample.js를 복사해서 build 디렉토리에 buildexample-.js 로 넣는다

   + 다른 파일들을 buildexample-.js 에 포함시키고 version과 timestamp를 넣는다 

<target name="consolidate" depends="properties, create_build">
    <echo>Consolidating...</echo>
    <copy file="${dir.src}/${name.base.js}" tofile="${file.consolidated.js}"/>
    <replace file="${file.consolidated.js}" token="%VERSION%" value="${version}"/>
    <replace file="${file.consolidated.js}" token="%TIMESTAMP%" value="${timestamp}"/>
    <concat id="srcfiles" destfile="${file.consolidated.js}" append="true>
        <fileset dir="${dir.src}" includes="**/*.js" excludes="${name.base.js}"/>
    </conca>
    <pathconvert pathsep=";" property="files" refid="srcfiles"/>
    <echo>${files}</echo>
    <echo>Finished.</echo>
</target>


  - JSHint 구문 검사 (코드 품질 측정)

    + PhantomJS를 통하여 수행한다 (PhantomJS API)

    + phantom-jshint-runner.js 파일로 jshint.js를 수행토록 한다 (lib 디렉토리에 존재)

<target name="jshint" depends="properties, consolidate">
    <echo>Checking syntax...</echo>
      <exec executable="phantomjs" dir="${basedir}" failonerror="true" resultproperty="specs.results">
          <arg line="'${file.jshint-runner.js}'" />
          <arg line="'${file.jshint.js}'" />
          <arg line="'${file.consolidated.js}'" />
          <arg line="${timeout.phantom}" />
      </exec>
    <echo>Finished</echo>
</target>


  - Jasmine 테스트에서 .html 파일 수행 (specs/index.html 존재)

    + PhantomJS를 통해 html을 읽어와 파싱하고 결과값을 ant로 반환한다

    + phantom-jasmine-runner.js 파일을 작성한다 (web 애플리케이션 headless test 방법)

<target name="specs" depends="properties">
    <echo>Running specs...</echo>
    <exec executable="phantomjs" dir="${basedir}" failonerror="true" resultproperty="specs.results">
        <arg line="'${file.jasmine-runner.js}'" />
        <arg line="'${file.specs-runner.html}'" />
        <arg line="${timeout.phantom}" />
    </exec>
    <echo>Finished.</echo>
</target>


  - 압축 (Minifying)

    + YUI compressor를 사용한다 (사용법)

    + command line 사용 :  java -jar yuicompressor-x.y.z.jar [options] [input files]

<target name="minify" depends="properties,create_build, consolidate">
    <echo>Minifying...</echo>
    <exec executable="java" dir="${basedir}" failonerror="true">
        <arg line="-jar '${file.yui_compressor.jar}'" />
        <arg line="--type js" />
        <arg line="-o '${file.minified.js}'" />
        <arg line="'${file.consolidated.js}'" />
    </exec>
    <echo>Finished</echo>
</target>


  - JSDoc 파일 생성 

    + command line 사용 : java -jar jsrun.jar app/run.js myscript.js -t=templates/jsdoc

<target name="jsdocs" depends="properties, consolidate">
    <echo>recreating docs folder...</echo>
    <delete dir="${dir.docs}"/>
    <mkdir dir="${dir.docs}" />
    <echo>Generating...</echo>
    <exec executable="java" dir="${basedir}">
        <arg line="-jar '${file.jsdoc_toolkit.jar}' '${dir.jsdoc_toolkit}/app/run.js'" />
        <!-- -d tells JSDoc toolkit where to output the documentation -->
        <arg line="-d='${dir.docs}'" />
        <!-- use the default template -->
        <arg line="-t='${dir.jsdoc_toolkit}/templates/jsdoc'" />
        <!-- Create an arg element for each file you want to include in the documentation -->
        <arg line="'${file.consolidated.js}'" />
    </exec>
    <echo>Finished</echo>
</target>


  - Clean up

    + build 디렉토리 파일이 빌드가 성공하면 bin 디렉토리로 옮긴다 

<target name="finish" depends="properties">
    <echo>Finishing...</echo>
    <delete dir="${dir.bin}" />
    <mkdir dir="${dir.bin}" />
    <move file="${dir.build.current}" tofile="${dir.bin}"/>
    <echo>Finished.</echo>
</target>


  - 각 target을 한꺼번에 수행하기 

<target name="build" depends="version, properties, create_build, consolidate, jshint, specs, minify, jsdocs, finish">
</target>


  - 수행 : ant build

$ ant build

Buildfile: d:\git-repositories\build-automation-javascript\build.xml


version:

    [input] Current version number is 1.0.0. Please enter the new version number: [1.0.0]

1.0.1   <== 직접 입력


properties:


create_build:

     [echo] Creating build...

   [delete] Deleting directory d:\git-repositories\build-automation-javascript\build

    [mkdir] Created dir: d:\git-repositories\build-automation-javascript\build\20130128154436

     [echo] Finished.


consolidate:

     [echo] Consolidating...

     [copy] Copying 1 file to d:\git-repositories\build-automation-javascript\build\20130128154436

     [echo] concat (d:\git-repositories\build-automation-javascript\src\Baz.js;d:\git-repositories\build-automation-javascript\src\Foo.js)

     [echo] Finished.


jshint:

     [echo] Checking syntax...

     [exec] read: d:\git-repositories\build-automation-javascript/build/20130128154436/buildexample-1.0.1.js

     [echo] Finished


specs:

     [echo] Running specs...

     [exec] open: file:///D:/git-repositories/build-automation-javascript/specs/index.html

     [exec] success

     [exec] finished in 218ms.

     [exec] 2 specs, 0 failures in 0.196s

     [echo] Finished.


minify:

     [echo] Minifying...

     [echo] Finished


jsdocs:

     [echo] recreating docs folder...

   [delete] Deleting directory d:\git-repositories\build-automation-javascript\docs

    [mkdir] Created dir: d:\git-repositories\build-automation-javascript\docs

     [echo] Generating...

     [echo] Finished


finish:

     [echo] Finishing...

   [delete] Deleting directory d:\git-repositories\build-automation-javascript\bin

    [mkdir] Created dir: d:\git-repositories\build-automation-javascript\bin

     [move] Moving 2 files to d:\git-repositories\build-automation-javascript

     [echo] Finished.


build:


BUILD SUCCESSFUL

Total time: 16 seconds


* 현재는 Grunt를 많이 사용하고 있다. (참조)


<참조>

원문 : Automating JavaScript builds

posted by 윤영식