마이크로소프트웨어에 게재된 내용입니다. 혹시 저작권에 문제가 되는 글이라면 fromm0@gmail.com으로 메일 주시면 즉시 삭제하도록 하겠습니다.

자바의 새로운 날개, 그루비(Groovy)#

<P><A target='_blank' class='con_link' name=top>동적이고 유연한 스크립팅 언어, 그루비(Groovy)</A></P> <P> </P> <P><STRONG>그루비(Groovy)는 자바와 달리 타입에 대해 동적이고 유연한 언어이다. 그루비는 현재 JSR 241에 올라가 있고 오픈소스로 개발이 진행되고 있으며, 앞으로 J2SE 6.0에 정식으로 포함될 것이라고 한다.</STRONG> <BR><BR>J2SE 5.0보다 훨씬 고급 수준의 언어, 코딩량을 현격하게 줄여주고 개발 시간을 단축시켜주는 언어, 리스트와 맵을 위한 리터럴이 언어 자체에 녹아 있는 그루비를 배워 미래에 대비하자. <BR><BR>그루비 프로그래밍 언어라고 하면 아마도 국내에서는 생소한 독자들이 많을 것이다. 그루비는 태어난 지 이제 1년을 갓 지난 프로그래밍 언어이기 때문이다. 그루비는 지난 6월 말 미국 샌프란시스코에서 열렸던 자바원에서 소개되기도 했다. 파이썬이나 루비를 접해보고 자바에 경험이 있는 독자라면 대부분 그루비도 좋아하리라고 본다. 이 글에서는 그루비의 역사, 맛보기, 더 잘 쓰기를 주제로 하여 그루비의 특징들을 소개하고자 한다. <BR><BR><!-- 설명 테이블 --><NEWSELEMENT></P> <DIV style="BORDER-RIGHT: #666 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #666 1px solid; PADDING-LEFT: 5px; FONT-SIZE: 0.9em; BACKGROUND: #f6f6f6; FLOAT: right; PADDING-BOTTOM: 5px; MARGIN-LEFT: 10px; BORDER-LEFT: #666 1px solid; WIDTH: 180px; PADDING-TOP: 5px; BORDER-BOTTOM: #666 1px solid; POSITION: relative; TEXT-ALIGN: left"><B><FONT color=#2e3192 size=2>연재 가이드 라인 </FONT></B><BR><BR><B>운영체제</B> : 윈도우/유닉스/리눅스/맥 OS X<BR><B>개발도구</B> : J2SE 1.4.2, 그루비 1.0 베타 6<BR><B>기초지식</B> : 자바, 파이썬, 루비, 기타 스크립팅 언어<BR><B>응용분야</B> : JVM 기반 스크립트 프로그래밍<BR></DIV> <P></NEWSELEMENT><B>그루비의 역사</B> <BR>자바가 탄생한 지 이제 어언 10년이 다 되어간다. J2SE 5.0(코드명 : 타이거)까지 나왔으니 청소년기에 접었다고 할 수 있다. J2SE 5.0는 J2SE 1.4에 비하여 언어적인 면에서 많은 것이 바뀌었기 때문에 자바 프로그래머의 입장에서 보면 새로운 자바 구문을 익혀야 하는 부담이 있다. <BR><BR>그루비는 자바처럼 객체지향 언어이지만 자바에 없는 고급 개념들이 있고, 자바처럼 변수의 타입에 대해 완고하지(statical) 않으며, 동적인(dynamical) 언어이다. 또 그루비로 작성된 소스 파일을 컴파일하지 않고 바로 실행시키는 스크립팅 언어이다. <BR><BR>그루비는 미국 출신의 Bob McWhirter과 영국 출신의 James Strachan 두 사람에 의해 창시되었다. 사실 이들 두 사람은 그루비 프로젝트 이전에도 Maven 등 여러 개의 프로젝트를 이미 공동으로 진행하고 있었다. 개발 초기에 밥은 어휘 분석을, 제임스는 유닛 테스트를 담당했다. 그 결과 첫 작품은 2003년 8월 29일에 발표되었다. <BR><BR>C 언어처럼 기계어 기반의 객체지향 언어로는 C++가 있고, 또 소스코드를 바로 실행시키는 스크립팅 언어로는 셸스크립트, Perl, 파이썬, 루비, Tck/Tl 등이 있다. 한편 자바 가상기계(JVM) 기반의 스크립팅 언어로는 자이썬, 제이루비, 자끌, 빈셸, 라이노 등이 있다. <BR><BR>이 중에 그루비와 가장 맞먹을 만한 상대는 자이썬이 아닌가 한다. 특히 자이썬에 관하여는 본지를 통해 이미 소개된 적이 있는 것으로 기억한다. 제이루비 프로젝트는 현재 개발이 진행되고 있는지도 알 수 없을 정도로 프로젝트 개발이 너무 느리게 진행되고 있다. <BR><BR>그루비는 파이썬과 루비의 영향을 가장 많이 받은 언어이다. 언어의 간결함은 파이썬/자이썬의 것을 추구했고, 클로저(코드 블럭) 등의 개념은 루비의 것을 이어 받았다. <BR><BR>그루비가 발표된 지 겨우 1년여밖에 안 되었는데도 불구하고 그동안 여러 프로그래머들의 칭찬을 받아왔다. 자이썬이나 루비를 쓰다가 그루비를 접한 프로그래머도 꽤 되는 것으로 알고 있다.  <화면 1>은 2003년 12월에 조사된 JVM용 스크립트 언어의 선호도 조사표이다(출처 : <A target='_blank' class='con_link' href="http://viva.sourceforge.net/republic/2004/01/" target=zdnk><U><FONT color=#0000ff>viva.sourceforge.net/republic/2004/01/</FONT></U></A>). 또 <표 1>은 스크립트 언어의 비교표이다(출처 : <A target='_blank' class='con_link' href="http://www.tcl.tk/advocacy" target=zdnk><U><FONT color=#0000ff>www.tcl.tk/advocacy</FONT></U></A>). <BR><!-- 큰 이미지 하나 중간에 놓을때 사용하는 소스입니다. --><BR></P> <CENTER> <TABLE width=420> <TBODY> <TR> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/p1.jpg"></TD></TR> <TR> <TD class=bk align=middle><FONT face=돋움><표 1> 스크립트 언어 기능 비교표 </FONT></TD></TR></TBODY></TABLE></CENTER> <P><BR><BR><B>그루비 다운로드와 설치</B> <BR>그루비 프로젝트 홈페이지(<A target='_blank' class='con_link' href="http://groovy.codehaus.org/" target=zdnk><U><FONT color=#0000ff>groovy.codehaus.org</FONT></U></A>)나 다운로드 페이지(<A target='_blank' class='con_link' href="http://dist.codehaus.org/groovy/distributions" target=zdnk><U><FONT color=#0000ff>dist.codehaus.org/groovy/distributions</FONT></U></A>)를 방문하여 그루비 소스와 바이너리를 구할 수 있다. 현재 공식적으로 배포되는 그루비 버전은 1.0 베타 6이다. <BR><BR>    ○ groovy-1.0-beta-6-src.tar.gz    리눅스용 그루비 소스 <BR>    ○ groovy-1.0-beta-6.tar.gz        리눅스용 그루비 바이너리 <BR>    ○ groovy-1.0-beta-6-src.zip      윈도우용 그루비 소스 <BR>    ○ groovy-1.0-beta-6.zip          윈도우용 그루비 바이너리 <BR><BR>압축 해제 도구를 써서 적당한 곳에 풀어도 되고, 다음 jar 명령으로 압축 해제해도 된다. <BR><BR>C:\>jar -xvf <다운로드저장경로명>\groovy-1.0-beta-6.zip <BR><BR>그루비는 J2SE 1.4에서 가장 잘 동작한다. 최근에 배포되는 J2SE 5.0 RC에서는 아직 잘 동작하지 않는다. 그루비를 설치한 곳이 C:\groovy-1.0-beta-6인 경우 다음과 같이 환경변수 JAVA_HOME, GROOVY_HOME, PATH를 잡는다. 다음은 윈도우 환경에서 환경변수를 잡아주는 setpath.bat 파일의 내용이다. <BR><BR>   set JAVA_HOME=C:\J2SE1.4.2 <BR>   set GROOVY_HOME=C:\groovy-1.0-beta-6 <BR>   set PATH=%GROOVY_HOME%\bin;%JAVA_HOME%\bin;%PATH% <BR>   set CLASSPATH=.;%GROOVY_HOME%\groovy-1.0-beta-6.jar;%CLASSPATH% <BR>   set CLASSPATH=%GROOVY_HOME%\lib\asm-1.4.1.jar;%CLASSPATH% <BR>   set CLASSPATH=%GROOVY_HOME%\lib\commons-cli-1.0.jar;%CLASSPATH% <BR>   set CLASSPATH=%GROOVY_HOME%\lib\junit-3.8.1.jar;%CLASSPATH% <BR><BR>리눅스 환경이면 환경 변수를 다음처럼 잡아준다. <BR><BR>   export JAVA_HOME=/usr/local/java <BR>   export GROOVY_HOME=/usr/local/groovy-1.0-beta-6 <BR>   export PATH=$GROOVY_HOME/bin:$JAVA_HOME/bin:$PATH <BR>   export CLASSPATH=.:$GROOVY_HOME/groovy-1.0-beta-6.jar:$CLASSPATH <BR>   export CLASSPATH=$GROOVY_HOME/lib/asm-1.4.1.jar:$CLASSPATH <BR>   export CLASSPATH=$GROOVY_HOME/lib/commons-cli-1.0.jar:$CLASSPATH <BR>   export CLASSPATH=$GROOVY_HOME/lib/junit-3.8.1.jar:$CLASSPATH <BR>   chmod 755 $GROOVY_HOME/bin/groovy* <BR><BR>맥 OS X 환경이면 <A target='_blank' class='con_link' href="http://wiki.codehaus.org/groovy/GroovyTutorial?action=highlight&value=OS+X" tartet="zdnk"><U><FONT color=#0000ff>wiki.codehaus.org/groovy/GroovyTutorial?action=highlight&value=OS+X</FONT></U></A>를 참조한다. 그루비 실행을 위해 환경 변수를 잡는 것 외에는 모든 운영체제에서 거의 비슷하므로 앞으로의 설명은 윈도우의 경우로 한정한다. <BR><BR>설치 후 %GROOVY_HOME%\bin 디렉토리에 실행 파일인 groovy.bat, groovyc.bat, groovysh.bat, groovyConsole.bat들이 있을 것이다. 스크립트 파일을 실행할 때는 groovy.bat를, 바이트 코드로 컴파일할 때는 groovyc.bat를, 스크립트 실행 셸로는 groovysh.bat를, GUI 실행 셸로는 groovyConsole.bat를 사용한다. <BR><BR>이 중에서 가장 많이 쓰는 것은 그루비 스크립트 파일을 실행하는 groovy.bat이다. 다음은 이들 명령의 사용 예들이다. <BR><BR>groovy 명령 사용 예: <BR>    C:\test>groovy sample.groovy <BR>    C:\test>groovy -e "println Hello" <BR><BR>groovyc 명령 사용 예: <BR>    C:\test>groovyc sample.groovy <BR><BR>groovysh 명령 사용 예 : <BR>    C:\test>groovysh <BR>    Lets get Groovy! <BR>    ================ <BR>    Version:  JVM: 1.4.2_05-b04 <BR>    Type 'exit' to terminate the shell <BR>    Type 'help' for command help <BR><BR>    1> x = '친구' <BR>    2> println "${x}야 안녕◆" <BR>    3> go <BR>    친구야 안녕◆ <BR><BR><회면 2>는 groovyConsole을 실행하여 소스코드를 입력한 모습이고, <화면 3>은 소스코드를 실행한 후의 모습이다. 실행 결과는 <화면 4>처럼 명령 창에 출력된다. groovyConsole은 그 실행 환경이 별로이므로 Groovy를 연습용으로는 나중에 소개하는 RunnerPad.groovy를 사용하는 것도 좋은 방법이다. 이클립스, JEdit, IntelliJ를 쓰는 경우에는 그루비 홈페이지에서 이들을 위한 플러그인을 구할 수 있다. <BR><BR>편집 도구로 UltraEdit나 EditPlus를 선호하는 경우에는 이달의 디스켓에 이들을 위한 컬러링, 자동 완성 등의 그루비용 파일을 준비했다. <화면 5>부터 <화면 8>까지는 UltraEdit와 EditPlus로 편집하고 실행한 모습 및 그루비 실행을 위해 설정 중인 장면이다. <BR><!-- 이미지 나란히 놓을때 사용하는 소스입니다. --><BR></P> <CENTER> <TABLE width=430 border=0> <TBODY> <TR> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/01.jpg"></TD> <TD width=10> </TD> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/02.jpg"></TD></TR> <TR> <TD class=bk vAlign=top align=middle><FONT face=돋움><화면 1> 코드 입력 </FONT></TD> <TD width=10> </TD> <TD class=bk vAlign=top align=middle><FONT face=돋움> <화면 2> 실행 후</FONT></TD></TR></TBODY></TABLE></CENTER> <P><BR><!-- 큰 이미지 하나 중간에 놓을때 사용하는 소스입니다. --><BR> <TABLE width=165 align=right> <TBODY> <TR> <TD align=left><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/03.jpg"></TD></TR> <TR> <TD class=bk align=middle><FONT face=돋움>  <화면 3> 명령 창에 출력</FONT></TD></TR></TBODY></TABLE>EditPlus의 경우에는 다음의 두 파일을 EditPlus의 디렉토리에 넣어둔다. <BR></P> <DIV style="MARGIN-LEFT: 15px"><BR>◆ groovy.acp : EditPlus에서 쓰는 그루비 자동 완성 파일 <BR>◆ roovy.stx : EditPlus에서 쓰는 그루비 구문 지원 파일 <BR></DIV> <P><BR>UltraEdit의 경우에는 다음의 파일에 있는 내용을 UltraEdit의 디렉토리에 있는 wordfile.txt에 추가한다. <BR></P> <DIV style="MARGIN-LEFT: 15px"><BR>◆ wordfile_groovy.txt : UltraEdit에서 쓰이는 그루비 구문 지원 <BR></DIV> <P><BR>리눅스/유닉스 환경에서 실행 스크립트로 만들기 <BR>리눅스/유닉스 환경에서 그루비 스크립트 파일을 실행 스크립트로 만들려면 다음 한 줄을 스크립트 파일의 첫줄에 적어준다. <BR><BR>#!/usr/bin/env groovy <BR><BR></P> <CENTER> <TABLE width=430 border=0> <TBODY> <TR> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/04.jpg"></TD> <TD width=10> </TD> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/05.jpg"></TD></TR> <TR> <TD class=bk vAlign=top align=middle><FONT face=돋움><화면 4> EditPlus로 편집하고 실행한 모습</FONT></TD> <TD width=10> </TD> <TD class=bk vAlign=top align=middle><FONT face=돋움><화면5> EditPlus에서 그루비 실행을 위한 기본 설정</FONT></TD></TR></TBODY></TABLE></CENTER> <P><BR> </P> <CENTER> <TABLE width=430 border=0> <TBODY> <TR> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/06.jpg"></TD> <TD width=10> </TD> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/07.jpg"></TD></TR> <TR> <TD class=bk vAlign=top align=middle><FONT face=돋움><화면 6> UltraEdit로 편집하고 실행한 모습</FONT></TD> <TD width=10> </TD> <TD class=bk vAlign=top align=middle><FONT face=돋움><화면 7> UltraEdit에서 그루비 실행을 위한 도구 설정</FONT></TD></TR></TBODY></TABLE></CENTER> <P><BR> <TABLE cellSpacing=0 cellPadding=0 width=430 align=center border=0> <TBODY> <TR> <TD class=bk> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD width=7><IMG height=24 src="http://images.zdnet.co.kr/img/edit_table/table8_1.gif" width=7></TD> <TD class=bk vAlign=baseline width=300 background=http://images.zdnet.co.kr/img/edit_table/table8_1_bg.gif>자바 프로그래머를 위한 몇 가지 조언</TD> <TD width=34><IMG height=24 src="http://images.zdnet.co.kr/img/edit_table/table8_2.gif" width=34></TD> <TD background=http://images.zdnet.co.kr/img/edit_table/table8_3_bg.gif>  </TD> <TD width=5><IMG height=24 src="http://images.zdnet.co.kr/img/edit_table/table8_7.gif" width=5></TD></TR></TBODY></TABLE></TD></TR> <TR> <TD background=http://images.zdnet.co.kr/img/edit_table/table8_bg.gif> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD width=1 bgColor=#000000></TD> <TD> <TABLE cellSpacing=10 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD class=bk> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD class=bk>◆ 타입이 동적인 언어(dynamically typed language) : 변수의 타입이 동적이므로 변수의 타입을 미리 선언하지 않아도 된다. <BR><BR>         int x = 7;    // 자바, Groovy <BR>         x = 7         // Groovy <BR><BR>◆ 문장 끝의 세미콜론(;) 붙이기 : 그루비에서는 문장의 끝에 세미콜론(;)을 붙여도 되고 안 붙여도 된다. <BR><BR>         x = 1 + 2;   // 자바, Groovy <BR>         x = 1 + 2    // Groovy <BR><BR>◆ 메쏘드 호출이 끝나는 지점의 return 키워드 생략 가능 <BR><BR>         int square(int x) { return x*x; }    // 자바, Groovy <BR>         square(x) { x*x }                    // Groovy <BR><BR>◆ 인자를 갖는 메쏘드 호출시 소괄호 생략 가능 <BR><BR>         println("Hello");   // Groovy <BR>         println "Hello"     // Groovy <BR><BR>◆ 클래스의 속성과 메쏘드의 접근 제한자를 생략한 경우 : 접근 제한자(public, protected, private)를 생략하면 public의 의미를 갖는다. 그루비에서 protected 제한자는 자바의 package-protected 제한자와 protected 제한자의 의미를 갖는다. 즉, 같은 패키지 내에서 friend 멤버를 가질 수 있으며, 파생 클래스에서 protected 멤버를 가질 수 있다. <BR>       <BR>  class SomeClass { <BR>            protected y          // y는 protected 멤버 변수 <BR>            doubler(x) { x*2 }   // doubler는 public 멤버 메쏘드 <BR>         } <BR><BR>◆ 자동 임포트 패키지 : 자바에서는 java.lang 패키지만이 자동 임포트 패키지이지만 그루비에서는 java.lang, groovy.lang, groovy.util 패키지들이 자동 임포트 패키지이다. 즉, 이들 패키지에 속한 클래스들은 임포트 구문에 명시하지 않더라도 패키지명 없이 클래스명만으로 쓸 수 있다. <BR><BR>◆ 그루비에는 원시 타입이 없다 : 자바에서는 boolean, byte, short, char, int, long, float, double 타입이라는 여덟 가지 원시 타입(primitive type)이 있다. 이들은 객체 타입이 아니라서 자바 프로그래밍에서 까다로운 존재가 되어 왔다. 자바에서는 컬렉션에 넣거나 가져올 때 원시 타입의 자료를 각각 이들의 래퍼 타입과 상호 변환해야 하는 번거로움이 있다. <BR><BR>      # Groovy로 작성된 예 <BR>      x = 5 <BR>      list = [] <BR>      list.add(x)   # 리스트에 넣을 때 변환 없이 넣는다. <BR>      y = list[0]   # 리스트에서 가져올 때도 변환 없이 가져온다. <BR><BR>      // 자바 언어로 작성된 예 <BR>      int x = 5; <BR>      ArrayList list = new ArrayList(); <BR>      list.add(new Integer(x));   // 리스트에 넣을 때 java.lang.Integer 타입으로 변환 <BR>      int y = ((Integer) list.get(0)).intValue();   // 리스트에서 가져올 때 java.lang.Integer 타입으로 <BR>                                                    // 변환 후 int 타입으로 변환 <BR><BR><BR>그루비에서는 처음부터 원시 타입이라는 개념이 없다. 즉, 내부적으로 래퍼 타입으로 인식한다. <BR><BR>      int x = 5    // int 타입은 내부적으로 java.lang.Integer 타입으로 처리된다. <BR>      println x.class <BR><BR>앞의 실행 결과는 int가 아니라 java.lang.Integer이다. 즉, 그루비 소스코드에서 int 타입이라고 선언한 것은 JVM 내부에서는 Integer 객체로 인식됨을 알 수 있다(참고 : groovy.codehaus.org/math.html). <BR><BR>◆ for 반복문 : 자바에서 쓰던 for ( ; ; ) 반복문 대신 그루비에서는 for in 반복문을 써야 한다. <BR><BR>      for (int i = 1; i <= 10; i++) // 자바 언어의 for 반목문 <BR>      for (i in 1..10)  // Groovy 언어의 for in 반목문 <BR><BR>◆ 비교 연산자 ==와 === : 자바의 object1.equals(object2)에 해당하는 그루비의 비교 연산자는 ==이고, 자바의 객체 비교 연산자 ==에 해당하는 그루비의 비교 연산자는 ===이다. <BR><BR>         if ("abc".eqwals("abc")) { ... }  // 자바 언어의 eqluals 비교 <BR>         if ("abc" == "abc") { ... }       // Groovy 언어의 == 비교 <BR><BR>         if (obj1 == obj2) { ... }     // 자바 언어의 객체 비교 <BR>         if (obj1 === obj2) { ... }    // 그루비 언어의 객체 비교 <BR><BR>◆ 클로저 : 클로저는 LISP 때부터 있던 것으로 함수와 비슷하지만 내부적으로는 함수와는 많이 다르다. 클로저는 일종의 코드 블럭이다(변수에 저장도 할 수 있는 코드 블럭이다). 함수와 다른 점은 클로저는 지역 변수를 가지지 못한다는 점과 인자를 제외한 변수는 외부의 것을 공유한다는 점이다. <BR><BR>클로저를 잘 사용하는 것은 그루비를 잘 사용하는 것이라고 말할 수 있을 정도로, 그루비에서는 매우 많은 곳에서 클로저를 사용한다. 그루비의 클로저는 루비에서 진짜 클로저(real closure)라고 하는 것과 동등한 개념이다. 그루비의 클로저가 진짜 클로저냐 아니냐 하는 토론은 참고 자료 4(코드 블럭과 클로저, <A target='_blank' class='con_link' href="http://wiki.codehaus.org/groovy/BlocksAndClosures" target=zdnk><U><FONT color=#0000ff>http://wiki.codehaus.org/groovy/BlocksAndClosures</FONT></U></A>)와 5(루비에서 코드 블럭과 클로저, <A target='_blank' class='con_link' href="http://www.artima.com/forums/flat.jsp?forum=226&thread=26329" target=zdnk><U><FONT color=#0000ff>http://www.artima.com/forums/flat.jsp?forum=226&thread=26329</FONT></U></A>)에서 볼 수 있다. <BR><BR>◆ 익명 클래스 : 자바 언어의 익명 클래스를 그루비에서는 지원하지 않는다. 그 대신 클로저를 사용하면 자바의 익명 클래스와 비슷한 효과를 낼 수 있다. 파이썬 언어의 람다 함수의 같은 것도 그루비에서는 클로저로 할 수 있다. <BR><BR>◆ def 예약어 : 파이썬, 루비처럼 그루비에도 함수를 정의하는 def 예약어가 있다. 파이썬, 루비와는 달리 그루비에서는 def 예약어를 클래스 내부에서는 사용하지 못하고, 클래스 외부에서만 사용할 수 있다. 클래스 내부에서는 자바 언어에서 메쏘드 정의하듯이 해야 한다. <BR><BR>       class SomeClass { <BR>          void someMethod() {   // 클래스 내부에 정의된 메쏘드 <BR>             ........ <BR>          } <BR>       } <BR><BR>       def someFunc() {   // def 예약어로 클래스 외부에 정의된 함수 <BR>          ........ <BR>       } <BR><BR>◆ 클래스의 실행 시작 지점 : 자바 애플리케이션의 경우 static main 메쏘드만 실행 시작이지만 그루비에서는 Runnable 인터페이스만 구현하면 static main 메쏘드 외에 run 메쏘드도 실행 시작 지점이 될 수 있다. <BR><BR>       class GroovyApplication { <BR>          // 실행 시작 지점 <BR>          void run() { <BR>             ........ <BR>          } <BR>       } <BR><BR>◆ 그루비에서는 클래스 명을 변수로 사용하지 못한다 : 자바에서는 컴파일되기 전의 소스 파일과 컴파일된 클래스 파일이 구분되어 있으므로 원시 파일을 클래스로 인식하는 일이 없다. 그러나 그루비는 스크립트 파일을 컴파일 없이 직접 탑재(loading)하여 클래스로 인식하므로 소스 파일 자체를 클래스로 인식한다. 다음 내용을 test.groovy 이름의 파일로 저장하고 실행하여 보았다. <BR><BR># 파일명: test.groovy <BR>println test <BR>println test.class <BR><BR>C:\test>groovvy test.groovy <BR>class test <BR>class test <BR><BR>이 실행 결과에서 보듯이 test를 클래스로 인식하고 있다.   <BR><BR>test = 123 <BR><BR>만약 이런 한 줄을 추가하면 다음과 같은 에러 메시지를 받는다. 클래스 명을 변수 명으로 하지 못한다는 메시지이다. <BR><BR>org.codehaus.groovy.syntax.parser.RuntimeParserException: Cannot use a class expression on the left hand side of an assignment. <BR><BR>그루비 스크립트 소스에서 임포트한 곳이나 또는 CLASSPATH 환경 변수에 인식되어 있는 경로에 *.groovy 파일이 있으면 이 파일명을 변수명으로 쓰지 못한다. 또 이 파일에 정의되어 있는 클래스의 이름도 변수명으로 사용하지 못한다. 클래스명을 변수명으로 사용하지 못한다는 점은 자바에는 없는 것인데, 이런 종류의 에러는 그 원인을 찾기 어려운 것 중의 하나이다. <BR><BR>참고 :  <A target='_blank' class='con_link' href="http://groovy.codehaus.org/javadiff.html" target=zdnk><U><FONT color=#0000ff>groovy.codehaus.org/javadiff.html</FONT></U></A> 및 <A target='_blank' class='con_link' href="http://groovy.codehaus.org/statements.html" target=zdnk><U><FONT color=#0000ff>groovy.codehaus.org/statements.html</FONT></U></A> <DIV></DIV><BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD> <TD width=1 bgColor=#000000></TD></TR></TBODY></TABLE></TD></TR> <TR> <TD class=bk> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD background=http://images.zdnet.co.kr/img/edit_table/table8_bot_mid.gif><IMG height=7 src="http://images.zdnet.co.kr/img/edit_table/table8_bot_left.gif" width=5></TD> <TD background=http://images.zdnet.co.kr/img/edit_table/table8_bot_mid.gif></TD> <TD background=http://images.zdnet.co.kr/img/edit_table/table8_bot_mid.gif> <DIV align=right><IMG height=7 src="http://images.zdnet.co.kr/img/edit_table/table8_bot_right.gif" width=6></DIV></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><B>Groovy 맛보기</B> <BR>그루비는 영어 사전에서 찾아보면 ‘가락이 맞는, 멋있는, 도취되는’의 뜻을 지니고 있는 형용사이다. 과연 그루비가 멋있는 언어인지는 각자가 판단할 일이다. 여기서는 짧은 코드를 통해 그루비의 세세한 부분의 맛을 보기로 하자. <BR><BR>◆ 그루비의 주석문 <BR># 줄 단위 주석문 <BR>// 줄 단위 주석문 <BR>/*  블록 단위 주석문 */ <BR><BR>◆ print와 println <BR>print("안녕")     // Java 언어의 System,out.print("안녕"); 와 동일 <BR>println "안녕"    // Java 언어의 System,out.println("안녕"); 와 동일 <BR><BR>◆ 그루비의 String <BR>“.... '가' .....”   //  쌍 따옴표로 둘러싸인 스트링 <BR><BR>'..... "가" ...'   // 홑 따옴표로 둘러싸인 스트링 <BR><BR>// 여러 줄 스트링 예 1 <BR>"가나다 <BR>'라마'바" <BR><BR>// 여러 줄 스트링 예 2. 내부에서 쌍 따옴표와 홑 따옴표를 모두 쓸 수 있다. <BR>"""가나'다' <BR>"라마"바""" <BR><BR>// 여러 줄 스트링 예 3. 내부에서 쌍 따옴표와 홑 따옴표를 모두 쓸 수 있다. <BR><<<EOS <BR>가나'다' <BR>"라마"바 <BR>EOS <BR><BR>참고 : <A target='_blank' class='con_link' href="http://groovy.codehaus.org/strings.html" target=zdnk><U><FONT color=#0000ff>groovy.codehaus.org/strings.html</FONT></U></A> <BR><BR>◆ Groovy의 GString <BR>x = 5 <BR>println "${x}의 제곱은 ${x*x}이다."   // GString  "${...}" 사용 <BR><BR><BR>JSP 2.0이나 벨로시티의 EL(Expression Language)과 비슷한 것을 그루비에서도 쓸 수 있다. 그루비에서는 이를 GString이라 한다. 그 표현 방식은 스트링 리터럴 내부에 ${expression}의 형태로 적어주면 된다. 루비에서 #{expression}이라고 적는 것과 비슷하다. 그루비에서는 GString과 나중에 소개될 GPath를 쓰면 소스코드를 알아보기가 매우 쉬워진다. <BR><BR>◆ 그루비 리스트 <BR>z = [1, 3, 5] <BR>z.add(-1) <BR>z << 7 <BR>println "z = ${z}" <BR>[]    # 빈 리스트 <BR><BR>그루비에서는 리스트와 맵을 위한 리터럴을 언어 자체에서 지원한다. 리스트의 리터럴 표현은 대괄호 열기와 닫기로 둘러싸는 것이다. 대괄호 안의 콤마는 리스트 안의 자료를 구분하는 구분자이다. 그루비의 리스트는 JVM 내부에서는 java.util.ArrayList로 인식된다(참고 : <A target='_blank' class='con_link' href="http://groovy.codehaus.org/collections.html" target=zdnk><U><FONT color=#0000ff>groovy.codehaus.org/collections.html</FONT></U></A>). <BR><BR>◆ 그루비 맵 <BR>z = ["일":1, "이":2, "삼":3] <BR>println "z['일'] = ${z['일']}" <BR>[:]    # 빈 맵 <BR><BR>그루비의 맵은 JVM 내부에서 java.util.HashMap으로 인식된다. 맵의 리터럴이 리스트의 리터럴과 다른 것은 콜론(:) 구분자를 더 갖는 것이다. 콜론(:) 구분자는 키(key)와 값(value)을 구분하는 구분자이다. 대괄호 안에 적어준 콜론(:) 구분자의 유무로 맵인지 리스트인지 판단한다. 다음 두 예제는 그루비의 맵 사용법과 자바의 맵 사용법을 비교하기 위해 작성해 본 것이다. <BR><BR>0: # 파일명: mapTest.groovy <BR>1: m = [:] <BR>2: m['groovy'] = "Groovy" <BR>3: m['py'] = "Jython" <BR>4: m[0] = 'zero' <BR>5: m[1] = 'one' <BR>6: <BR>7: m.each { <BR>8:    println "키 ${it.key}의 값은 ${it.value}입니다." <BR>9: } <BR><BR>0: // 파일명: HashMapTest.java <BR>1: import java.util.*; <BR>2: public class HashMapTest { <BR>3:    public static void main(String[] args) { <BR>4:       HashMap m = new HashMap(); <BR>5:       m.put("groovy", "Groovy"); <BR>6:       m.put("py", "Jython"); <BR>7:       m.put(new Integer(0), "zero"); <BR>8:       m.put(new Integer(1), "one"); <BR>9: <BR>10:       Set keys = m.keySet(); <BR>11:       Iterator it = keys.iterator(); <BR>12:       for (;it.hasNext(); ) { <BR>13:          Object obj = it.next(); <BR>14:          System.out.println("키 " + obj + "의 값은 " + m.get(obj) + "입니다."); <BR>15:       } <BR>16:    } <BR>17: } <BR><BR><BR>◆ 수정 불가 리스트/맵 <BR>z = [1, 3, 5].asImmutable() <BR>k = ["김씨":"서울", "이씨":"부산", "박씨":"인천"].asImmutable() <BR><BR>asImmutable() 메쏘드를 쓰면 수정 불가능한 컬렉션으로 변환된다. <BR><BR>◆ 그루비 범위(range) <BR>1..9    // 오른 쪽 끝을 포함하는 range <BR>1...9   // 오른 쪽 끝을 포함하지 않는 range <BR><BR>연속된 수치 데이터의 리스트를 간단히 생성하기 위한 방법으로 그루비에서는 range(이하 범위)라는 개념을 제공한다. 범위의 리터럴은 a..b와 a,,,b가 있다. 점 2개를 사용한 범위는 우측 끝을 포함하고, 점 3개를 사용한 범위는 우측 끝을 포함하지 않는다. a..b나 a...b에서 b가 a보다 작아도 된다. 예를 들어 3..(-2)라고 표현된 범위는 [3, 2, 1, 0, -1]이라고 표현된 리스트와 같다. 인덱스가 음수인 것은 리스트의 부호를 뗀 값이 끝에서부터 헤아린 순서를 의미한다. 즉 인덱스 -1은 리스트의 마지막 자료를 의미하는 번호이다. <BR><BR>◆ 서브 스트링과 서브 리스트 <BR>z = "Hello, Groovy" <BR>z[0]                # "H" <BR>z[-1]               # "y" <BR>z[5, 7]             # ", G" <BR>z[0, 2..3, -2..-1]  # "Hllvy" <BR>z[2..-1]            # "llo, Groovy" <BR>z[-3..-2]           # "ov" <BR><BR>list = [3, 7, 2, 5, 9] <BR>list[0]         # 3 <BR>list[-1]        #  9 <BR>list[0..2]      # [3, 7, 2] <BR>list[0..1, -1]  # [3, 7, 9] <BR><BR>◆ 그루비 연산자 <BR>a == b      # 자바의 equals에 해당 <BR>a === b     # 자바의 객체 비교 ==에 해당 <BR>a <=> b     # 자바의 compareTo에 해당 <BR><BR>"문자열" * 2                     # "문자열문자열" <BR>"문자열" - "자"                  # "문열" <BR>[3, 2, 1, 0] * 2                 # [3, 2, 1, 0, 3, 2, 1, 0] <BR>[3, 2, 1, 0] - [1, 3, 5, 7, 9]   # [0, 2] <BR><BR>z = [1, 2] <BR>z << 4     // z.add(4)와 동일 <BR>z.add("삼") <BR>assert z == [1, 2, 4, "삼"] <BR><BR>그루비에서는 자바에 없는 독특한 연산자를 몇 가지 제공한다. 비교 연산자로 ==, ===, <=>가 있고, 스트링이나 리스트의 정수배 연산자 *, 뺄셈 연산자 -, 추가 연산자 << 등이 있다. <BR><BR>◆ 함수와 메쏘드의 리턴문 <BR>def square(x) { <BR>    x*x    //  return x * x; 와 동일 <BR>} <BR>z = square(7) <BR>println "z = ${z}" <BR><BR>◆ 그루비 클래스 <BR>class Car { <BR>    model; maker <BR>    Car(model, maker) { this.model = model; this.maker = maker } <BR>    String toString() { "(${model}, ${maker})" } <BR>} <BR><BR>x = new Car("소나타", "현대") <BR>println "${x}" <BR><BR>◆ 그루비 빈 <BR>class Customer { <BR>    name; phone <BR>} <BR>x = new Customer(name:"가나다", phone:"111-2222") <BR>println "${x.name}"    # GPath <BR>println "${x.phone}"   # GPath <BR><BR>이 그루비 빈 예제를 보면 자바로 작성된 것과 비교하여 그루비의 간결함을 알 수 있다. <BR><BR>◆ 클로저 <BR>x = 123 <BR>c = { println "${it + x}" }   # it는 클로저의 디폴트 인자 <BR>                            # c는 클로저의 인스턴스를 참조하는 변수 <BR>c(x)   # c.call(x) 와 동일 <BR><BR>클로저는 앞서 언급했듯이 일종의 코드 블럭이다. 코드 블럭임을 나타내기 위해 반드시 중괄호로 둘러싼다. 클로저가 메쏘드나 함수와 다른 것은 지역변수를 갖지 않으며 외부에서 선언되거나 사용된 변수를 그대로 전달시킨다는 것이다. 클로저 내부에서 인자명을 특별히 지정하지 않으면 디폴트 인자 it를 쓸 수 있다. <BR><BR>{ println "${it + x}" }   # 중괄호로 둘러싸인 코드 블럭 <BR>                          # it는 디폴트 인자, x는 외부에서 사용된 변수 <BR><BR>{ |n| println "${n + x}" }   # 중괄호로 둘러싸인 코드 블럭 <BR>                             # n은 인자, x는 외부에서 사용된 변수 <BR><BR>데이터를 변수에 저장하듯이 클로저도 변수에 저장할 수 있다. <BR><BR>c = { println "${it + x}" }   # 코드 블럭을 변수 c에 저장한다. <BR>c = { |n| println "${n + x}" }   # 코드 블럭을 변수 c에 저장한다. n은 인자로 선언되었다. <BR><BR><BR>클로저를 호출하는 구문은 closureName(parameters) 또는 closureName.call(parameters)이다. <BR><BR>x = 123 <BR>c(x)    # c.call(x) 와 동일 <BR><BR>다음은 3개의 인자를 갖는 클로저의 예이다. <BR><BR>sum = { |a, b, c|  a + b + c }   # return이 생략되었음. 이 클로저에서 a, b, c는 인자로 선언됨. <BR>println sum(1, 2, 3)   # sum.call(1, 2, 3)과 동일함 <BR><BR>다음은 타입이 지정된 3개의 인자를 갖는 클로저의 예이다. <BR><BR>sum = { |int a, int b, int c|  a + b + c }   # 세 인자 a, b, c가 모두 java.lang.Integer 타입으로 선언됨 <BR>println sum(1, 2, 3) <BR><BR>스크립트 소스에서 클로저를 호출하기 전에 반드시 클로저의 정의가 먼저 나와야 한다. 즉, 다음과 같이 코딩한 것은 에러가 난다. <BR><BR>doubler(20)   # doubler가 정의되기 전에 이를 호출하면 에러 <BR>doubler = { |z| println "${z * 2}" } <BR><BR>그루비의 클로저는 루비의 진짜 클로저의 개념과 같고 그 사용법도 거의 같다. <BR><BR>// 그루비의 클로저에서 인자를 사용하는 이전 코딩 방식과 새 코딩 방식 <BR>c1 = { z | println "${z}의 두배는 ${z*2}" }    # 이전 코딩 방식 <BR>c1 = { | z | println "${z}의 두배는 ${z*2}" }  # 새 코딩 방식은 인자 선언 좌측에 수직 문자(|)를 하나 더 <BR>                                               # 적는다. 이는 루비의 코딩 방식과 같다. <BR><BR>◆ for in 반복문 <BR>for (x in 1..9) { <BR>   println "2 X ${x} = ${2*x}" <BR>} <BR><BR>C, C++, 자바에서 많이 쓰던 for(;;) 반복문을 그루비는 아직 지원하지 않는다(그루비 1.1에서는 for(;;) 반복문을 지원할 예정이라고 한다). 그 대신 for in 반복문을 사용하면 된다. 그 구문법은 다음과 같다(참고 : groovy.codehaus.org/loops.html). <BR><BR>      for (변수명 in 컬렉션) <BR>또는 <BR>      for (변수명 in 스트링) <BR><BR>앞의 for in 사용 예제에서는 컬렉션에 1..9 즉 1에서 9까지의 정수 값을 차례로 갖는 레인지를 사용하였다. <BR><BR>◆ 클로저를 이용한 반복문 <BR>(1..9).each { | x | <BR>   println "2 X ${x} = ${2*x}" <BR>} <BR><BR>이번 것은 앞에서 for in 반복문으로 작성했던 것과 같은 것을 리스트의 each 메쏘드와 클로저를 사용하여 작성한 것이다. <BR><BR>◆ 리스트/맵/범위/스트링과 함께 사용된 클로저 <BR># 리스트의 each 메쏘드와 함께 사용된 클로저 <BR>sum = 0 <BR>last = 0 <BR>[1, 13, 4, -5].each { | x | sum + = x;  last = x } <BR>println "sum = ${sum}, last = ${last}"     # 진짜 클로저 <BR>                                           # 진짜 클로저라 함은 외부의 편수를 공유함을 의미한다. <BR>                                           # 여기서는 sum과 last가 외부 변수이다. <BR><BR># 맵의 each 메쏘드와 함께 사용된 클로저 <BR>["아침":"빵", "점심":"라면", "저녁":"매운탕"].each { <BR>   println "${it.key}에는 ${it.value}을" <BR>} <BR><BR># 리스트의 count 메쏘드를 사용한 예 <BR>z = [1, 2, 4, 1, -5, 1].count(1)   # 리스트에 들어 있는 1의 개수 <BR>println z     # 3 <BR><BR># 리스트의 find, findAll, max, min, collect, reverse, sort, join 메쏘드를 사용한 예 <BR>z = [1, 2, 4, 1, -5, 1 ].find { |x| x > 2 }     # 4 <BR>z = [1, 2, 4, 1, -5, 1 ].findAll { |x| x > 2 }  # [4] <BR>z = [1, 2, 4, 1, -5, 1 ].max()     # 4 <BR>z = [1, 2, 4, 1, -5, 1 ].min()     # -5 <BR>z = [1, 2, 4, 1, -5, 1 ].collect { |x| x * x }   # [1, 4, 16, 1, 25, 1] <BR>z = [1, 2, 4, 1, -5, 1 ].reverse()   # [1, -5, 1, 4, 2, 1] <BR>z = [1, 2, 4, 1, -5, 1 ].sort()      # [-5, 1, 1, 1, 2, 4] <BR>z = ["일", "이", "삼"].join("^")     # 일^이^삼 <BR><BR>◆ 그루비 switch문 <BR>switch (x) { <BR>    case 3:    # 상수 <BR>       ...... <BR>       break           <BR>    case 5..7:  # range <BR>       ...... <BR>       break           <BR>    case "한글":   # 객체 <BR>       ...... <BR>       break           <BR>    case [11, 111, 1111]:   # 컬렉션 <BR>       ...... <BR>       break           <BR>    case ~"
d{3}-
d{3}":   # 정규식 <BR>       ...... <BR>       break           <BR>    case java.util.Date:  .....  # 타입 <BR>       ...... <BR>       break           <BR>    default: <BR>       ...... <BR>       break           <BR>} <BR><BR>그루비의 다중 분기 switch문은 case 부분에 타입, 객체, 컬렉션, 정규식도 쓸 수 있다는 점이 자바의 switch문과는 다르다(참고 : <A target='_blank' class='con_link' href="http://groovy.codehaus.org/branches.html" target=zdnk><U><FONT color=#0000ff>groovy.codehaus.org/branches.html</FONT></U></A>). <BR><BR>◆ 연산자 오버로딩(operator overloading) <BR>import java.util.Date <BR><BR>class Friend implements Comparable { <BR>    String name; Date birth <BR>    Friend(name, birth) { this.name = name; this.birth = birth } <BR>    boolean equals(Object o) { this.name == o.name && this.birth == o.birth } <BR>    int compareTo(Object o) { this.birth <=> o.birth } <BR>} <BR><BR>a = new Friend("홍길동", new Date(1980, 8, 12)) <BR>b = new Friend("박서방", new Date(1977, 1, 20)) <BR>println a == b <BR>println a <=> b <BR><BR>◆ 그루비 정규식(regular expression) <BR>import java.util.regex.Matcher <BR>import java.util.regex.Pattern <BR><BR>pattern = ~"연습"    # java.util.regex.Pattern의 인스턴스 <BR>assert pattern instanceof Pattern <BR>assert pattern.matcher("연습").matches() <BR><BR>matcher = "GroovyGroovy" ="Groovy"   # java.util.regex.Matcher의 인스턴스 <BR>assert matcher instanceof Matcher <BR><BR>answer = matcher.replaceAll("Groovy")   # 모두 바꾸기 <BR>assert answer == "GroovyGroovy" <BR><BR>result = ("하루하루" ="하루").replaceFirst("오늘") <BR>assert result == "오늘하루" <BR><BR>그루비에서는 정규식을 위한 구문을 지원한다. <BR><BR>~regularExpression             # java.util.regex.Pattern의 인스턴스 <BR>string =regularExpression    # java.util.regex.Matcher의 인스턴스 <BR><BR>◆ 파일 입출력 <BR>import java.io.File <BR>new File("foo.txt").eachLine { | line | doSomething(line) } <BR><BR>new File("foo.txt").withReader { | reader | <BR>   while ((line = reader.readLine()) != null) { <BR>      doSomething(line) <BR>   } <BR>} <BR><BR>def doSomething(s) { <BR>   println(s) <BR>} <BR><BR>그루비에서는 입출력 코딩을 편하게 하기 위해 File, Reader 등에 유익한 메쏘드들을 추가해 놓았다. <BR><BR>◆ 외부 파일 실행 <BR>process = "cmd.exe /c dir /w".execute() <BR>process.in.eachLine { |z| println z } <BR><BR>소스가 단 2줄 뿐이다. 자바로 작성한 것보다는 상당히 간단함을 알 수 있다. <BR><BR>◆ args는 Groovy의 예약어 <BR>// 실행: groovy argsTest.groovy 1 2 3 4 <BR>for (x in args) { println x } <BR>sum = 0 <BR>for (x in args) { sum += x.toInteger() } <BR>println sum <BR>println args <BR>println args.class <BR>println args.toList() <BR><BR>args는 명령 프롬프트에서 실행시 옵션으로 넣어준 스트링의 배열이다. 즉, 자바 애플리케이션에서 다음과 같은 main 메쏘드의 인자 args에 해당한다. <BR><BR>      public static void main(String[] args) <BR><BR>다음은 그루비를 실행한 출력이다. <BR><BR>1 <BR>2 <BR>3 <BR>4 <BR>10 <BR>[Ljava.lang.String;@1394894 <BR>class [Ljava.lang.String; <BR>[1, 2, 3, 4] <BR><BR>◆ 그루비 SQL <BR>// 실행: groovy argsTest.groovy 1 2 3 4 <BR>for (x in args) { println x } <BR>sum = 0 <BR>for (x in args) { sum += x.toInteger() } <BR>println sum <BR>println args <BR>println args.class <BR>println args.toList() <BR><BR>args는 명령 프롬프트에서 실행시 옵션으로 넣어준 스트링의 배열이다. <BR><BR><B>그루비 더 잘 쓰기</B> <BR>그루비 소스 파일을 컴파일 도구 groovyc로 컴파일하면 JVM에서 동작할 바이트 코드를 만들 수 있다.   <BR><BR>◆ groovyc 명령으로 컴파일하기 <BR># 파읾명: Sample.groovy <BR>package hello <BR>msg = "Hello" <BR>println "${msg}, I am Groovy!" <BR><BR><FONT color=#2e3192>컴파일하기</FONT> <BR>C:\test>groovyc Sample.groovy <BR><BR>컴파일되고 나면 현재 디렉토리에 hello라는 서브 디렉토리가 생기면서 이곳에 Sample*.class가 2개가 보일 것이다. 이제 이를 java 명령으로 실행한다. 실행하기 전에 다음 jar 파일이 CLASSPATH에 잡혀 있는지 반드시 확인하자. <BR><BR>      %GROOVY_HOME%\groovy-1.0-beta-6.jar <BR>      %GROOVY_HOME%\lib\asm-1.4.1.jar <BR>      %GROOVY_HOME%\lib\commons-cli-1.0.jar <BR><BR>다음과 같이 실행한다 <BR><BR>C:\test>java hello.Sample <BR><BR>이번에는 build.xml 파일을 작성하여 jakarta-ant 도구로 빌드해 보자. <BR><BR>◆ Ant로 빌드하는 데 필요한 build.xml 파일의 내용 <BR><project name="BuildTest" default="build"> <BR>   <!-- Test classpath --> <BR>   <path id="test.classpath"> <BR>      <pathelement location="${grovoy-1.0-beta-6.jar}"/> <BR>      <pathelement location="${asm-1.4.1.jar}"/> <BR>      <pathelement location="${commons-cli-1.0.jar}"/> <BR>   </path> <BR><BR>   <taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" <BR>            classpathref="test.classpath" /> <BR><BR>   <target name="build"> <BR>      <groovyc destdir="${basedir}/build" <BR>               srcdir="${basedir}/src" listfiles="true"> <BR>               <classpath refid="test.classpath" /> <BR>      </groovyc> <BR>   </target> <BR></project> <BR><BR>우선 현재 디렉토리 아래에 다음과 같은 디렉토리를 만들어 둔다. <BR><BR>    myWork <BR>    myWork\build <BR>    myWork\src <BR><BR>그리고 앞의 내용을 작성하여 myWork 디렉토리에 build.xml이라는 이름의 파일로 저장한다. 앞에서 작성되었던 Sample.groovy 파일을 myWork\src 디렉토리에 복사해 둔다. 그리고 myWork 디렉토리에서 다음의 Ant 실행 명령을 내린다. %ANT_HOME% 은 Jakarta-ant가 설치된 디렉토리이다. <BR><BR><FONT color=#2e3192>빌드하기</FONT> <BR>C:\test\myWork>%ANT_HOME%\bin\ant <BR><BR><FONT color=#2e3192>빌드 후 실행하기</FONT> <BR>C:\test\myWork>java -cp build;%CLASSPATH% hello.Sample <BR><BR>◆ 자바에서 그루비 임베딩하기(1) <BR>1: // EmbedBindingTest.java <BR>2: // <BR>3: //    자바 코드에서 그루비 표현식을 실행하는 예 <BR>4: //    Changed from http://viva.sourceforge.net/talk/jug-mar-2004/slides.html#groovy-1 <BR>5: // <BR>6: //        set CLASSPATH=%GROOCVY_HOME%\groovy-1.0-beta-6.jar;%CLASSSPATH% <BR>7: //        set CLASSPATH=%GROOVY_HOME%\lib\asm-1.4.1.jar;%CLASSSPATH% <BR>8: // <BR>9: // 컴파일하기: javac -source 1.4 EmbedBindingTest.java <BR>10: //   실행하기: java EmbedBindingTest <BR>11: <BR>12: import groovy.lang.*; <BR>13: <BR>14: public class EmbedBindingTest { <BR>15:    public static void main(String[] args) { <BR>16:       Binding binding = new Binding(); <BR>17:       binding.setVariable( "foo", new Integer(2) ); <BR>18:       GroovyShell shell = new GroovyShell( binding ); <BR>19:       try { <BR>20:          Object value = shell.evaluate( "println 'Hello Groovy!'; x = 123; return foo * 10" ); <BR>21:          assert value.equals(new Integer(20)); <BR>22:          assert binding.getVariable("x").equals( new Integer(123) ); <BR>23:       } <BR>24:       catch (org.codehaus.groovy.control.CompilationFailedException ex) { <BR>25:          System.out.println(ex.getMessage()); <BR>26:       } <BR>27:       catch (java.io.IOException ex) { <BR>28:          System.out.println(ex.getMessage()); <BR>29:       } <BR>30:    } <BR>31: } <BR><BR>◆ 자바에서 그루비 임베딩하기(2) <BR>1: // 파일명: RunScriptTest.java <BR>2: // 자바 코드에서 그루비 스크립트 파일을 탑재하여 실행하는 예 <BR>3: // <BR>4: // 컴파일하기: javac -source 1.4 RunScript.java <BR>5: <BR>6: import groovy.lang.*; <BR>7: import java.io.*; <BR>8: <BR>9: public class RunScriptTest { <BR>10:    public static void main(String[] args) { <BR>11:       GroovyClassLoader loader = new GroovyClassLoader();  // Groovy 클래스 로더를 인스턴스한다. <BR>12:       try { <BR>13:          // 그루비 클래스 로더가 그루비 스크립트 소스 파일을 파싱하여 클래스를 생성한다, <BR>14:          Class groovyClass = loader.parseClass( new File("switches.groovy") ); <BR>15:          // 파싱하여 생성된 클래스로부터 GroovyObject를 인스턴스한다, <BR>16:          GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); <BR>17:          Object[] arguments = {};   // 실행시 명령 행 아규먼트로 전달될 오브젝트 배열 <BR>18:          // 스크립트를 실행한다. run은 스크립트 내의 실행될 메쏘드명 <BR>19:          groovyObject.invokeMethod( "run", arguments ); <BR>20:       } <BR>21:       catch (org.codehaus.groovy.control.CompilationFailedException ex) { <BR>22:          System.out.println(ex.getMessage()); <BR>23:       } <BR>24:       catch (java.lang.InstantiationException ex) { <BR>25:          System.out.println(ex.getMessage()); <BR>26:       } <BR>27:       catch (java.lang.IllegalAccessException ex) { <BR>28:          System.out.println(ex.getMessage()); <BR>29:       } <BR>30:       catch (IOException ex) { <BR>31:          System.out.println(ex.getMessage()); <BR>32:       } <BR>33:    } <BR>34: } <BR><BR>그루비에는 Ant, HTML, XML, Swing, SWT, SQL 등에 관한 소스를 편하게 작성하기 위해 Builder들을 별도로 만들어 놓았다. 이 중에서 SwingBuilder를 Swing GUI 애플리케이션으로 사용하는 예제를 하나 소개한다. 핵심부는 26행부터 36행까지이다. 이 부분은 파이썬 코드와 매우 닮았는데 실제로 이 소스는 참고자료 22의 9장에 있는 것을 그루비로 수정한 것이므로 자이썬과의 비교도 될 것이다. <화면 9>는 이 예제의 실행 결과이다. <BR><BR>◆ SwingBuilder 사용 예제 <BR>1: import java.awt.FlowLayout <BR>2: import javax.swing.* <BR>3: import groovy.swing.SwingBuilder <BR>4: <BR>5: incValue = { | tf | <BR>6:    value = Integer.parseInt(tf.getText()) <BR>7:    value++ <BR>8:    tf.setText("${value}") <BR>9:    println "value 증가. value = " + value <BR>10: } <BR>11: <BR>12: decValue = { | tf | <BR>13:    value = Integer.parseInt(tf.getText()) <BR>14:    value-- <BR>16:    tf.setText("${value}") <BR>17:    println "value 감소. value = " + value <BR>18: } <BR>19: <BR>20: clearValue = { | tf | <BR>21:    value = 0 <BR>22:    tf.setText("${value}") <BR>23:    println "value 초기화. value = " + value <BR>24: } <BR>25: <BR>26: sw = new SwingBuilder() <BR>27: frame = sw.frame( title:'Counter', size:[200,110], windowClosing:{ System.exit(0) } ) { <BR>28:    panel(layout:new FlowLayout() ) { <BR>29:       display = textField( preferredSize:[200,30], horizontalAlignment:SwingConstants.CENTER, editable:false ) <BR>30:       display.background = java.awt.Color.white <BR>31:       display.setText("0") <BR>32:       button( text:"Inc", size:[65,70], actionPerformed:{ incValue(display) } ) <BR>33:       button( text:"Clear", size:[65,70], actionPerformed:{ clearValue(display) } ) <BR>34:       button( text:"Dec", size:[65,70], actionPerformed:{ decValue(display) } ) <BR>35:    } <BR>36: } <BR>37: <BR>38: frame.setVisible(true) <BR><!-- 이미지 나란히 놓을때 사용하는 소스입니다. --><BR></P> <CENTER> <TABLE width=430 border=0> <TBODY> <TR> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/09.jpg"></TD> <TD width=10> </TD> <TD align=middle><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/10.jpg"></TD></TR> <TR> <TD class=bk vAlign=top align=middle><FONT face=돋움><화면 9> Swing 예제의 실행 모습</FONT></TD> <TD width=10> </TD> <TD class=bk vAlign=top align=middle><FONT face=돋움><화면 10> RunnerPad로 편집하기</FONT></TD></TR></TBODY></TABLE></CENTER> <P><BR>그루비를 연습하는데 GroovyConsole이 사용하기에 불편하여 필자가 순수 그루비로 RunnerPad.groovy를 만들어 보았다. RunnerPad.groovy의 전체 소스는 이달의 디스켓으로 제공된다. 이 소스는 지금까지 설명한 것들을 종합적으로 이용한 예제이므로 그루비를 이해하는 데 유익한 자료가 될 것이다. <화면 10>은 RunnerPad.groovy를 써서 편집 중인 화면이고, <화면 11>은 실행 결과가 출력된 명령 창 화면이다. 파이썬이나 루비처럼 인터렉티브한 셸은 <A target='_blank' class='con_link' href="http://wiki.codehaus.org/groovy/SimpleShell" target=zdnk><U><FONT color=#0000ff>wiki.codehaus.org/groovy/SimpleShell</FONT></U></A>에 있다. <BR><BR> <TABLE width=160 align=left> <TBODY> <TR> <TD align=left><IMG src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1220-2/11.jpg"></TD></TR> <TR> <TD class=bk align=middle><FONT face=돋움>   <화면 11> RunnerPad로 실행한 결과</FONT></TD></TR></TBODY></TABLE><B>그루비에 한 걸음씩 다가서자</B> <BR>아직 그루비에 관한 서적이 전혀 없고 정식 버전도 나오지 않아 세부적으로는 앞으로 무엇이 달라질 지 알 수가 없다. 하지만 그루비가 오픈소스로 개발되고 있으며 아파치와 같은 라이선스로 배포되고 있으니 개발 과정을 지켜보면서 한 걸음씩 접근하는 것은 즐거운 일이다. <BR><BR>미래를 위해 고급 수준의 언어를 미리 접하는 것은 시간과 경제적으로 틀림없이 이익을 안겨줄 것이다. 다음 호에서는 BSF, Groovlet, GSP에 관해 다루고자 한다. @ <BR><!-- 마소 저작권표시 --><BR><FONT color=#003399><I>* 이 기사는 ZDNet Korea의 자매지인 <A target='_blank' class='con_link' href="http://www.imaso.co.kr/" target=zdnk><U><FONT color=#0000ff>마이크로소프트웨어</FONT></U></A>에 게재된 내용입니다.</I></FONT></P>

</td> </tr>

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-2) was last changed on 06-Apr-2006 09:45 by 218.235.119.108