110525_egovFramework 세미나

  • 제목 : Dive into Maven
  • 장소 : 청계광장 정보화진흥원 지하1층 세미나실
  • 발표내용
    • 표준프레임워크 오픈커뮤니티를 통해서 프레임워크연구개발이 활성화되길 바란다.
    • Maven is ...
      • 프로젝트 관리(Project Management) 와 빌드 자동화(Build Automation)
      • 2002년, Apache Turbine 에서 비롯되었다.
      • Maven 도입이유
        • 라이브러리 관리의 문제점
          • commons.fileupload 1.0 버그 -> 1.1 해결
          • classpath : 같은 패키지 상에서는 제일 상단에 존재하는 패키지 부터 실행됨
        • 오픈소스를 사용하는 경우 의존성을 지니게 되는 라이브러리
        • 자유도(Ant 확장성이 뛰어남, Maven 정형화 되어 있음)
    • Maven Simple Project
      • project home : pom.xml
      • src/main/java
      • src/main/resource
      • src/test/java
      • src/test/resource
    • Maven vs Ant
      • Maven is formal convensions.
      • Ant isn't formal conventions.
      • Ant is procedural, Maven is declarative
      • Maven has a lifecycle(Ant를 잘 구성하면 lifecycle 구현이 가능하다)
    • Super POM(CoC)
      • 모든 프로젝트의 POM은 SUPER POM을 상속 받는다(All project POMs extends Super POM
    • Simple POM
    • POM.xml
      • POM 의 구조 설명
    • Library Search Path
      • Repository
        • Local repository
          • maven -> installation -> setting.xml
        • Remote repository
          • Repository with WebServer
          • Repository with Nexus
    • Repository
      • <repositories> ~~ </repositories>
      • snapshot 은 상속받지 않는 것으로 되어 있다.
    • Repository with WebServer
      • Maven은 인터넷이 안되면 쥐약
      • 인터넷이 안된다면, 자체적인 저장소를 생성하여 관리한다.
        • Local 저장소에서 복사하여 사용하는 방법
        • Webserver : Apache / document_root / 에 저장
        • apache 에 index를 볼 수 있도록 설정되어 있느냐? search가 안됨
    • Repository with Nexus
    • Nexus 관련 주의사항
      • 플러그인이 설치되지 않는 경우...
      • 넥서스를 이용하여 업로드한 경우
      • <pluginRepositories></pluginRepositories>를 선언해줘야한다.
      • maven_home/sonatype_work/nexus/storage 에 넣은 뒤에는 Nexus를 재기동 시켜줘야 한다.
    • Dependency Scope
      • 종류
        • compile(default)
        • provided : 컴파일과 유사하나 패키지에는 포함되지 않음
        • test
        • runtime
        • system
      • Specify dependency range
        • [,]
        • (,]
        • (,)
    • Transitive Scope
    • Conflict Resolution
      • Exclude Transitive scope
        • <exclusions> ~~ </exclusions>
    • Build LifeCycle
      • phases, goals, plugin
      • Lifecycle을 가지고 있는 장점 : 테스트를 돌릴 수 있다. TestCase를 작성해야 한다.
    • Developing java plugin for Maven
      • Maven Project 생성방법
      • Create Simple Mojo
    • Complie Configure
      • <plugin>
      • Maven plugin <source>, <target>
    • Skip Test
      • <configuration>
 <skipTest>
</configuration>
    • ProGuard
      • 역컴파일 방지기
      • Ddependency, plugin에 넣기
    • Site Reporting
    • PMD
      • plugin rulesets ㅇ르 정의해줘야 한다.
    • Maven Archetype
      • Maven을 이용하여 목적에 따라 Archetype들을 사용하여 지정할 수 있다.
      • 전자정부용 Archetype가 존재한다.
      • 초창기에 만들었는데 알려주지 않는 이유
      • 필요에 따라서 만들면 된다.
    • m2Eclipse
      • Maven projects를 만들고 첨가하는 경우
      • 의존성 저장 및 갱신
      • SCM 저장소로부터 maven Porject 추가
      • WTP에서 통합 -> WTP 쪽 Runtime 에서 오류가 발생, 톰캣 실행시 오류가 발생한다. 오류 가능성을 숙지하고 있을 것
      • 의존성 그래프를 프래픽적으로 추가
      • Maven 의 기능은 다양하다. 많이 써보고, 필요한 기능을 능숙하게 다루면 되겠지.
    • Maven 3.x new Feature
      • dependency 일 경우에는 프로젝트에만 영향을 미치지만...
      • dependency-management 를 구분해서 사용하라.
  • 결론 : 전자정부 프레임워크에는 Maven을 사용했다. 



최근 스프링 프레임워크를 기반으로 하는 프로젝트를 진행하게 되면서 메이븐Maven의 사용이 익숙해져가고 있다. <dependency> 를 추가하는 것만으로 관련한 라이브러리들이 주루룩 다운로드 되는 그 맛이란...

가까운 곳에서 이런 Maven에 대한 내용으로 발표가 있다고 해서 참가했다. 샌드위치 때문에 참가신청(?)을 한 사람들이 많았는가 보다. 160명분을 준비했는데 모두 소진되었다고 하는 걸 보니... 봐도 넓은 회의실을 꽉채우고 있었다. 냉방시설을 가동시킬 수 없어서 꽤나 답답하고 더웠다. 

발표는 한시간, Qn A 시간이 한시간 잡혀 있었지만, 발표내용 자체가 워낙 Maven에 대한 개괄적인 발표이다보니 딱히 무엇을 물어야할지 애매했다. 발표내용도 애매모호한 부분들이 많았다. 차라리, 전자정부 프레임워크를 적용한 프로젝트들에서 Maven과 관련되어 발생한 문제들의 예시와 해결방법을 30분 정도 추가해서 설명하는 건 어땠을까 하고 생각한다.
 
  전체적으로 많이 아쉬운 세미나였다.
  크게 개선되지는 않겠지....

  메이븐Maven에 대해 궁금하시다면
메이븐
카테고리 컴퓨터/IT > 프로그래밍/언어 > 웹프로그래밍 > 웹프로그래밍일반
지은이 박재성 (한빛미디어, 2011년)
상세보기
 이 책과
책의 저자가 운영하던 스터디 사이트 : http://www.javajigi.net/display/IDE/Maven
Maven Project 사이트 : http://maven.apache.org/
에서 필요한 정보들을 찾아보기 바란다.
iBatis 를 처음 사용하면서 삽질을 통해서 모르는 것들을 하나하나 배워가고 있다. ㅡ0-);
어제는 parameterClass에 Map을 전달하는 과정에서 생기는 특이사항을 제대로 이해하지 못해서 생긴 해프닝을 기록한다.

iBatis에 com.google.common.collect.ImmutableMap 으로 생성한 Map 객체를 parameter로 넘겼다.
이때 들어간 객체들에는 Double형, String 형 두 가지가 있었다. 이 parameter들이 들어가는 위치가 계산식이냐 일반 키워드처럼 들어가느냐에 따라서 Double형과 String형의 표현 방식이다.

iBatis가 SqlMap에 작성한 쿼리에 파라메터를 넣을 때, 파라메터 객체의 속성에 따라서 Double 형은 그대로, String 형은 ''를 씌워서 넣어준다.
난 이걸 제대로 숙지하지 못해서 문제가 발생했다.

//properties 에 기록해둔 message 중에서 하나를 saveRate에 넣음
String saveRate = 3;
//메소드를 이용하여  산출된 수치
Double exchangeRate = 15.36;
 

   Select 절에 alias 형태로 들어갈 경우  
 
SELECT
    #saveRate# as save_rate
    , #exchangeRate# as exchageRate
FROM dual;

위의 형태에서는 String 형이건 Double 형이건 문제가 생기지 않는다. 

   계산을 하는 곳에 파라메터로 전달되거나 ISNULL 처리 등에 사용될 경우 
 

SELECT
    (100 - (5 * #saveRate#)) as product_price_rate
    , ( 14.55 * #exchangeRate# ) as product_exchange_rate
FROM dual;

 위의 형태로 했을 때는 별 문제가 없을까? ㅡ_-)?
 #exchageRate# 는 그대로 15.36 이 들어가면서 계산식에 문제가 없지만, #saveRate#의 경우에는 ( 100 - ( 5 + '3' ) ) 의 형태가 되면서 JDBC를 통해서 Exception 처리가 뜬다. 숫자형이 들어와야하는 곳에 문자열이 들어왔다고 하면서 파라미터가 잘못되었다는 메시지를 뿌린다.
췟... 이걸 제대로 알고 있지를 못해서 혼자 삽질을 하고 있었다. 
  위의 쿼리를 제대로 실행되게 하려면,

SELECT
    (100 - (5 * $saveRate$)) as product_price_rate
    , ( 14.55 * #exchangeRate# ) as product_exchange_rate
FROM dual;

String 형 파라메터를 계산식에 사용할 경우에는 $saveRate$ 처럼 $ $를 이용해서, 파라메터 클래스고 가지고 있는 값을 그대로(parameterClass의 종류에 상관없이) 입력하도록 만들면 된다. 이걸 제대로 이해하고 있지 못한 나의 무지함 때문에, 난 또 그렇게 3~4시간의 삽질을 혼자했던 거다...
크흑....

   결론 
 

1. 쿼리문을 제대로 읽어서 parameter 들이 들어가야하는 곳에 문자열이 들어가는 것인지 숫자형이 들어가는지 파악한다.
2. iBatis를 통해서 받는 parameterClass="Map"인 경우에는 Map에 담긴 객체들이 어떤 것인지 파악한다.
3. String으로 받은 파라메터 객체를 계산식에 사용할 경우에는, $ $를 이용해서 그대로 넣는다.



오랜만에 JCO가 열립니다. ^^ 자바 개발자분들이 오셔서 많은 이야기들을 듣고 느낄 수 있는 기회가 되었으면 합니다. ^^


public void given(String message, Object... args) {
....
}

이건 어디서 어떻게 쓰는 표현인고?

ellipsis (...) identifies a variable number of arguments, and is demonstrated in the following summation method.
ellipsis 라고 불리는 녀석인 것 같다.
이녀석의 특징은 메소드 등에서 동일한 객체의 파라메터(실행에 필요한 변수, 설정변수?)들을 처리할 때, 메소드마다 파라메터의 갯수를 늘려가며 설정하는 대신,
public void method(Int... args) {}  

로 설정해두면, int 형의 파라메터를 몇개를 받아도 처리가 가능하다.

간단정리 : Variable-Length Argument Lists

이 녀석의 정체를 파악해보기 위한 간단한 테스트 코드도 작성해본다.
 
package honeymon.java.study;

import org.junit.Test;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

public class TestEllipsis {
    @Test
    public void testEllipsis() {
	assertThat(lengthEllipsis(3, 4, 5, 6), is(4));
	assertThat(countEllipsis(2, 3, 4, 5, 6), is(20));
	assertThat(stringEllipsis("Korea", "Japan", "China"), is("Korea is Strong country."));
    }

    private String stringEllipsis(String...national) {
	String stmt = null;
	for (int i = 0; i < national.length; i++ ){
	    if("Korea".equals(national[i])) {
		stmt = national[i] + " is Strong country.";
	    }
	}
	return stmt;
    }

    private Integer countEllipsis(int... numberArray) {
	int sumresult = 0;
	for (int i = 0; i < numberArray.length; i++) {
	    sumresult += numberArray[i];
	}
	return sumresult;
    }

    private Integer lengthEllipsis(int... number) {
	return number.length;
    }
    
}
  이클립스(JDK 1.5 이상)에서 java.io.Serializable 인터페이스를 구현한 클래스를 작성할때마다 serialVersionUID를 생성하라는 경고가 뜬다. 처음에는 아무런 생각없이 무시하고 넘어갔었는데, 새롭게 프로젝트에 투입되어 선임 개발자가 작성한 소스를 보다가 도메인Domain 객체마다 선언되어 있는 serialVersionUID를 보면서 '어따 쓰는거지?'라는 궁금증이 생겨 여쭤보았다.
serialVersionUID == '분산처리 환경에서 유일한Unique 클래스라는 것을 증명하기 위한 신분증'
이라고 간략히 정의를 내렸다.

  참고사이트 : http://docs.xrath.com/java/se/6/docs/ko/api/index.html
  여기서 Serializable 인터페이스에 대한 설명을 볼 수 있다. 다만, 영어를 번역한 일어를 한글로 번역한 것이라 글의 설명이 어려운 느낌이다. 그래서 조금 순화해서 다시 써봤다.
 
  직렬화 런타임은, 각 직렬화가능Serializable 클래스에 버전번호serialVersonUID를 설정한다. 이 serialVersionUID는, 직렬화 복원 중에 직렬화객체의 송신측과 수신측이 사용하는 객체가 직렬화에 호환성이 있는 클래스인지를 확인하는 용도로 사용된다. 송신측에서 보낸 serialVersionUID와 다른 serialVersionUID를 가지는 객체를 수신측이 로드했을 경우, 직렬화 복원 중에 InvalildClassException이 발생한다.
필드명 serialVersionUID를 선언하게되면 직렬화가능Serializable 구현 클래스는, 중복되지 않는 독자적인 serialVersionUID를 가지게 된다.
※  serialVersionUID는 반드시 static final long 형으로 선언되어야 한다.

  Serializable 구현 클래스가 SerialVersionUID를 명시적으로 선언하지 않는 경우, 직렬화 런타임은 「Java(TM) 객체 직렬화 스펙」에서 설명된 것처럼, 클래스의 다양한 측면들을 근거로 클래스 serialVersionUID의 디폴트 값을 선언하여 사용할 수 있다. 그러나 가능하면 모든 직렬화 가능 클래스가 명시적인 serialVersionUID를 선언하는 것을 강력 추천(IDE에서 generate하여 선언)합니다.
  이것은, 디폴트의 serialVersionUID의 계산이, 컴파일러의 구현에 따라서 달라질 직렬화가능Serializable 클래스가 영향을 받기 쉽고, 직렬화 복원 중에 예기치않는 InvalidClassException을 발생시킬 수 있기 때문입니다. 따라서, Java 컴파일러에 상관없이 serialVersionUID의 일관성을 확보하기
위해서, 직렬화 가능Serializable 구현 클래스에서는 명시적으로 serialVersionUID를 명시적으로 선언하도록 하자.
  추가적으로, serialVersionUID의 명시적 선언에는 private 수식자를 사용하는 것을 추천합니다. 이 선언자를 사용하면, 이 속성에 대한 선언이 해당 클래스에만 적용되기 때문입니다. 즉, serialVersionUID 필드 값이 상속되지 않는다(serialVersionUID는 유일해야 한다).
  배열클래스는 serialVersionUID를 명시적으로 선언할 수 없기 때문에, 디폴트 값을 사용한다.

  IDE 내에서 serialVersionUID 선언 방법
 
1. 클래스에 Serializable 인터페이스를 구현하겠다고 선언한다.

2. Quick Fix(Ctrl+1)을 실행하고 Add generated serial versio ID(AspectJ)를 클릭한다.

3. 위의 사진처럼 private static final long serialVersionUID = 5294335241519103532L; 선언된 것을 확인할 수 있다.



나중에 추가적으로 더 알게되는 내용이나 잘못된 내용은 업그레이드 하겠습니다.

+ Recent posts