반응형


학교 다닐 때 다른 블로그에 등록했던 글 복사 ㅎㅎ - http://blog.naver.com/7dbwnckd/50012727041


널 문자 (='\0')와 널 포인터 (= NULL = (void*)0) 그리고 false 는

사실상 0x00 이라는 같은 값을 가집니다.


하지만 의미상 확연한 차이가 있기 때문에, 다르게 쓰입니다.


# 널 문자

널 문자는 보통, 문자열의 끝을 알리는데 쓰입니다.

char *str = "abcd";

-> [ 'a' | 'b' | 'c' | 'd' | '\0' ]




# 널 포인터

포인터 변수 초기화나 포인터 파라미터 전달 시에 주로 쓰입니다.


// 포인터 변수 초기화
char *pstr = NULL;

// 포인터 파라미터 전달
time_t time(time_t *); // time() 함수 프로토타입

time(NULL);



# 논리값 false

bool 형 변수에 값을 대입하거나, 함수 파라미터 전달 시에 쓰임.

void my_func(bool bExist); // 프로토타입

my_func(false);




모두 같은 값을 가지는 것들이지만...

상황에 따라 쓰이는 경우가 다르지요?


이렇게 의미상 구분이 되는 것들을 나누어 놓지 않으면,

큰 프로그램을 분석할때 아주 골치 아파 진답니다.

반응형
반응형


학교 다닐 때 다른 블로그에 등록했던 글 복사 ㅎㅎ - http://blog.naver.com/7dbwnckd/50013168713


 

standard input으로 쓰이는 scanf .. 이해를 바로 합시다..

 

간단한 예를 하나 들어보죠...

 

바로 아래의 예를 실행시켜 보면... char를 입력하지 못하고 바로 넘어갑니다.

 

void exScanf()
{

 int a;
 char ch;

 printf("enter a number : ");
 scanf("%d", &a);

 

 printf("enter a charac : ");
 scanf("%c", &ch);  

 printf("a: %d , ch: %c \n", a, ch);
}

 

왜냐하면... 첫 번째 입력후 엔터키를 입력하게 되는데요~

그 엔터기가 그 다음 scanf의 문자로 입력되어지는 결과가 나오거든요~

 

그래서 오류를 수정하면... 2가지 방법으로 수정할 수 있답니다.

둘 중 하나를 택일 하시면 됩니다. ^^;;

 

void exScanf()
{

 int a;
 char ch;

 printf("enter a number : ");
 scanf("%d", &a);

 

//  첫 번째 방법...

 fflush(stdin);  // 버퍼를 비워라.

 

 printf("enter a charac : ");

// 두 번째 방법
 scanf("%*c", &ch);  // * wild gey : 앞에 오는 \n 받지마라는 소리.

 printf("a: %d , ch: %c \n", a, ch);
}

반응형
반응형


예전 블로그 복사 - http://blog.daum.net/7dbwnckd/1616504


서버 설정이 잘 되어진다면 다른 설정은 필요가 없어진다.

 

sql 부르는 쿼리태그만 필요할 뿐. ^^;;

 

 <sql:query var="rs" dataSource="jdbc/dbwnckd">
      select host,db from db
 </sql:query>

 

아... 5.5 버전에서 주의할 점이 있다.

 

<taglib>
     <taglib-uri>http://java.sun.com/jstl/core
     </taglib-uri>
     <taglib-location>/WEB-INF/tlds/c-rt.tld
     </taglib-location>
 </taglib>

 

바로~ c.tld 같이 -rt가 아닌 것들은 쓰면 에러남 ㅡㅡ;; jstl버전인갑다.~ 즐하삼~

반응형
반응형


예전 블로그 복사 - http://blog.daum.net/7dbwnckd/4696550


GC(Garbage Colloection)는 언제 발생할까?

1. GC의 원리

 - 메로리 할당

 - 사용 중인 메모리 인식

 - 사용하지 않는 메모리 인식

 

 - JVM의 메모리는 크게 클래스 영역, 자바 스택, 힙, 네이티브 메소드 스택 4개 영역으로 나뉘지만, 가비지 컬렉터가 인식하고 할당하는 자바의 메모리 역역에 대해 공부하자!!(힙)

  Young, Old, Perm(permanent)의 세 영역으로 나누어지는데,

  Young 영역은 Eden, Survivor1, Survivor2

  Old 영역은 메모리영역

 * 일단 메모리에 객체가 생성되면, Eden영역에 객체가 지정된다. Eden영역에 데이터가 어느 정도 쌓이면, 이영역에 있던 객체가 어디론가 옮겨지거나 삭제된다. 이 때 옮겨지는 위치가 Survivor영역이다. 우선순위는 없으며 두 개의 영역 중 한 영역은 반드시 비어 있어야 한다. 그 비어 있는 영역에 Eden 영역에 있던 객체가 할당된다. 할당된 Survivor 영역이 차면, GC가 되면서 Eden 영역에 있는 객체와 꽉 찬 Survivor 영역에 있는 객체가 비어 있는 Survivor 영역으로 이동한다. 그러다가 더 큰 객체가 생성되거나, 더 이상 Young 영역에 공간이 남지 않으면 객체들은 Old 영역으로 이도하게 된다.

 

2. GC의 종류

 - 마이너 GC : Young 영역에서 발생하는 GC

 - 메이저 GC : Old 영역이나 Perm 영역에서 발생하는 GC

 이 두 가지 GC가 어떻게 상호 작용하느냐에 따라서 GC 방식에 차이가 나고, 성능에도 영향을 준다. GC가 발생하거나 객체가 각 영역에서 다른 영역으로 이동할 때 애플리케이션의 병목이 발생하면서 성능에 영향을 주게 된다. 그래서 핫 스팟(Hot Spot) JVM에서는 스레드 로컬 할당 버퍼(TLABs: Thread-Local Allocation Buffers)라는 것을 사용한다  이를 통하여 각 스레드별 메모리 버퍼를 사용하면 다른 스레드에 영향을 주지 않는 메모리 할당 작업이 가능해진다.

 

 

반응형
반응형

오픈 소스 자바 프로젝트를 응용한 웹 어플리케이션개발

-마크 이글(Mark Eagle)


04/07/2004

 자바로 어느 정도 규모의 웹 어플리케이션을 개발하는 일은 보통 일이 아니다. 어플리케이션이 개발될 아키텍처를 만드는 데에는 무수히 많은 고려할 사항이 있기 때문이다. 높은 레벨에서 살펴보면 개발자들은 사용자 인터페이스를 어떻게 제작할 것인지, 비즈니스 로직은 어디쯤에 위치할 것인지, 그리고 어플리케이션 데이터를 어떻게 퍼시스턴스 상태로(물리적 저장 공간에 저장하는 것) 유지할것인지에 대한 결정에 직면하게 된다. 이 각각의 계층들은 그 각자의 계층들만으로도 해결되어야 할 문제들을 가지고 있다. 그것들을 질문으로 표현하면 다음과 같다. 각각의 계층을 연결하는 데 있어 어떤 기술이 사용될 것인가? 변화에 유연하게 대처하기 위하여 어떻게 하면 각각의 계층들간의 결합도를 약하게(원문:loosely coupled) 할 수 있을 것인가? 그 구조가 각각의 계층들에 변화를 주지 않고 특정 계층을 교체할 만큼 유연할 수 있을까? 컨테이너 레벨의 서비스들을 트랜잭션으로 처리하기 위해서는 어떻게 해야 할 것인가?


 당신의 웹 어플리케이션 아키텍쳐를 생성하는 데 있어 나열되어야 할 질문들에는 한도 끝도 없다. 다행히도 그런 과정에 있어 반복적으로 재기되는 문제들의 해결을 위해 일해온 많은 개발자들이 있다. 좋은 프레임웍은 복잡한 문제들에 대한 부품들을 재개발해야하는 문제로부터 개발자들을 좀 더 편안하게 해 준다. 좋은 프레임웍의 요건들은 다음과 같다 : 내부 커스터마이징에 있어 유연해야 한다. 그리고 그 프레임웍을 지원하는 강력한 유저 커뮤니티가 있어야 한다. 각각의 프레임웍들은 일반적으로 한 가지 문제에 대한 효과적인 해결책을 제시해 준다. 그렇지만 당신의 어프리케이션은 그 어플리케이션만의 프레임웍이 필요로하는 여러 층의 계층이 존재한다. 단지 UI 문제를 해결한다는 것은 UI컴포넌트에다 비즈니스 로직과 퍼시스턴스 로직(persistence logic)을 집어넣어 개발하는 것을 의미하는 것은 아니다. 예를 들면,  당신은 JDBC코드를 포함한 비즈니스 로직을 컨트롤러에다 집어넣으면 안되는데, 왜냐하면 이것은 컨트롤러가 제공하려는 기능에 맞지 않기 떄문이다. UI 컨트롤러는 다른 어플리케이션 계층을 UI 계층의 요청으로부터 분리하는 가벼운 컴포넌트로써 그 의미를 가지기 떄문이다. 좋은 프레임웍은 자연스럽게 어떤 코드가 어디에 위치해야하는지의 가이드라인을 형성하게 된다. 더 중요한 점은, 프레임웍은 개발자로 하여금 동일한 패턴의 코드를 계속적으로 제작하는 작업을 줄여 주며 훨씬 더 중요한 어플리케이션 로직 자체에 집중할 수 있는 여유를 준다는 점이다.


 이 글은 약한 결합도(loose coupling)를 가진 아키텍처를 구성하기 위해 잘 알려지 몇몇의 프레임웍을 결합하는 법에 대해 기술하고 있다. 그러기 위하여 어떻게 아키텍처를 설계하는지, 그리고 각각의 어플리케이션 계층간의 디자인을 일관되게 유지하는 방법에 대해 알아볼 것이다. 프리젠테이션 계층에는 스트럿츠(Struts), 비즈니스 계층에는 스프링(Spring), 퍼시스턴스 계층에는 하이버네이트(Hibernate)를 사용할 것이다. 물론 각각의 계층에 사용된 프레임웍을 다른 것으로 교체해서 사용할 수도 있다. 그림 1은 이 프레임웍들이 결합되었을 때 어떤 모양을 이루는지를 보여준다.


Figure 1
그림 1. 스트럿츠, 스프링, 하이버네이트로 구성된 아키텍처의 개략적 구조


어플리케이션 계층화

대부분의 중,대규모 웹 어플리케이션들은 많은 경우에 있어 4개의 계층으로 구성된다 이 계층들은 프리젠테이션, 퍼시스턴스 비즈니스, 도메인 모델(Domain model) 계층들이다. 각각의 계층들은 어플리케이션에서 명확히 구별되는 기능을 가지고 있으며 서로 다른 계층을 침범하거나 그 기능적인 면에 있어 중복되는 점이 없어야 한다. 각각의 어플리케이션 계층들은 다른 계층들과  완전히 분리되어 있지만 각 계층들간의 통신을 위하여 인터페이스를 제공한다. 각각의 계층들을 개괄적으로 훑어보고 각 계층들이 제공해야 할 것이 무엇인지, 제공하지 말아야 할 것이 무엇인지를 알아보자.

프리젠테이션 계층(표현 계층)

Related Reading

Hibernate: A Developer's Notebook

Hibernate: A Developer's Notebook
By James Elliott

일반적인 웹 어플리케이션의 맨 끝에는 프리젠테이션 계층이 존재한다. 많은 자가 개발자들은 스트럿츠가 제공하는 것이 무엇인지 이해하고 있지만 많은 경우에 있어 비즈니스 로직에 관한 코드를 org.apache.struts.Action 클래스를 확장한 Action에다가 같이 집어넣어 구현하는 우를 범하는 것이 사실이다. 그래서 스트럿츠와 같은 프레임웍이 제공해야 할 것이 무엇인지에 대하여 먼저 생각해 보도록 하자. 여기에 스트럿츠가 제공해야 할 것들을 나열해 보았다.

  • 사용자를 위한 request와 response의 처리
  • 비즈니스 로직과 다른 상위 프로세스로의 호출을 웹 환경으로부터 분리하기 위한 컨트롤러 제공
  • 다른 계층(tier)로부터 스트럿츠 액션으로 던져지는 익셉션들을 처리하는 기능
  • 뷰에 표현될 모델들을 논리적으로 엮는 기능
  • UI 검증(UI validation) 수행

보통 스트럿츠를 사용한 계층 안에  같이 코딩되면 안되는 것을 집어넣는 경우가 있다. 그 예들은 다음과 같다.

  • JDBC호출과 같은 데이터베이스와의 직접적인 통신
  • 비즈니스 로직이나 어플리케이션과 관련된 request 검증
  • 트랜잭션 관리

이런 코드들을 프리젠테이션 계층에다 넣는 것은 각 계층들을 복잡하게 엮이게 만들어 유지보수시 성가신 문제를 발생시킨다.

퍼시스턴스 계층(영구 저장 계층)

웹 어플리케이션의 또 다른 끝 계층은 퍼시스턴스 계층이다. 여기서도 흔히 제어권을 벗어난 일들이 발생하는 경우가 있다. 개발자들은  그들 자신만의 퍼시스턴스 프레임웍을 구축하는 데 드는 비용을 경시하는 경향이 있다. 그 상황에 특수화되고 시스템 안에 심어진 퍼시스턴스 계층은 단지 엄청난 개발 시간을 필요로 할 뿐만 아니라 기능도 부족하고 또한 통제 불가능한 상황이 되는 경우가 종종 있다. 이런 많은 문제에 도움이 되는 오픈 소스 객체-관계 맵핑(object-to-relational mapping, 역자주: 자바의 객체를 RDB의 테이블형태로 맵핑시키는 것을 말함))  - ORM - 프레임웍이 다수 있다.  특별히 하이버네이트(Hibernate) 프레임웍은 객체-관계 퍼시스턴스와 자바를 위한 쿼리 서비스를 제공한다. 하이버네이트는 이미 SQL와 JDBC API에 익숙한 자바 개발자들이 익히기에 중간 정도의 노력을 필요로 한다. 하이버네이트 퍼시스턴스 객체(Hibernate persistent objects)는 일반적인 형태의 자바 객체와 자바 콜렉션에 기반을 두고 있다. 게다가 하이버네이트와 흔히들 사용되는 IDE툴을 같이 사용하는 것은 문제가 되지 않는다.  다음에 나열된 것은 퍼시스턴스 프레임웍에 코딩해야할 것들이다.

  • 관계형 정보를 빼내어 객체화 시키는 작업. 하이버네이트는 이것을 HSQL이라 불리는 OO 쿼리를 쓰거나 criteria API를 써서 작업을 수훨하게 한다. HQL은 테이블명 대신에 객체명, 컬럼명 대신에 객체의 필드명을 사용한다는 것만 빼고는 SQL과 아주 유사하다. 몇몇 새로이 익혀야 할 HQL 언어 항목들이 있지만 배우기도 쉽고 HQL 에 관한 문서도 많기 때문에 걱정할 거리가 안 된다.

  • 데이터베이스의 자료를 저장하고, 수정하고, 삭제하는 작업.

  • 하이버네이트와 같은 진보된 객체-관계 맵핑 프레임웍은 대부분의 SQL 데이터베이스를 지원한다. 또한 객체의 부모/자식 관계, 트랜젝션, 상속,  다형성등을 지원한다.

퍼시스턴스 계층에 넣지 말아야 할 것들을 살펴보자.

  • 비즈니스 로직은 더 높은 계층에 포함되어야 한다. 퍼시스턴스 계층엔 단지 데이터 억세스에 관련된 작업만 허용된다..

  • 프리젠테이션 로직과 퍼시스턴스 로직을 뒤섞어서 코딩하면 안 된다. JSP나 서블릿 같은 프리젠테이션 컴포넌트에다 직접적으로 데이터 억세스를 수행하는 코드를 넣지 말아야 한다. 퍼시스턴스 로직을 퍼시스턴스 계층 안에만 한정시킴으로써 어플리케이션은 다른 계층의 변화에 구애받지 않고 퍼시스턴스 계층을 변화시킬 수 있는 유연함을 지니게 된다. 예를 들면 하이버네이트는 다른 계층의 어떤 코드도 바꾸지 않고 다른 퍼시스턴스 프레임웍으로 교체될 수 있다.

비즈니스 계층

일반적인 웹 어플리케이션의 중간 계층에는 비즈니스나 서비스 계층이 존재한다. 코딩에 대한 관점으로 볼 때 이런 서비스 계층은 대부분의 경우에 있어 무시되는 경우가 많다.  비즈니스 계층의 코드들이 UI계층이나 퍼시스턴스 계층에 여기저기 흩어져 있는 어플리케이션을 찾아보기란 그리 어려운 일이 아니다. 이런 구조는 어플리케이션의 시스템이 스파게티처럼 이리저리 뒤섞여 각각의 계층을 모호하게 만들어 유지보수시 많은 시간을 필요로 하게 만든다. 다행히도 이런 문제를 해결하기 위한 몇몇 프레임웍이 있다. 가장 유명한 두가지가 스프링(Spring) 프레임웍과 피코컨테이너(PicoContainer) 프레임웍이다. 이것들은 어떻게 객체들을 엮는지를 결정해주는 조그만 마이크로컨테이너(microcontainer)라고 불리기도 한다. 이런 프레임웍들은 연관성 삽입(dependency injection, inversion of control)이라는 간단한 개념 위에서 동작한다. 이제부터는 스프링 프레임웍에서 빈의 프로퍼티를 동적으로 세팅하는 기능, 즉 설정 파일에서 그 이름을 변경할 수 있는 빈의 프로퍼티의 삽입 기능에 촛점을 맞추어 얘기할 것이다. 스프링은 빈의 setter를 사용한 빈의 프로퍼티 동적 삽입 방식 외에도 생성자를 사용한 방법 또한 지원한다.(역자주: 지금은 무슨 말인지 잘 이해 안가셔도 계속 읽다 보면 이해가 가실 겁니다.^^). 객체들은 트랜잭션 관리자, 객체 Factory, 비즈니스 로직을 담고 있는 서비스 객체, 그리고 퍼시스턴스 계층에 속하는(data access object, DAO) 객체의 레퍼런스를 명시하고 있는 간략한 XML파일에 의하여 그 구조를 형성하게 된다.  그리고 스프링이 사용하고 있는 개념들은 예제를 통하여 훨씬 더 쉽게 알아볼 수 있을 것이다.

그리고 비즈니스 계층은 다음과 같은 요건을 가져야 한다.

  • 어플리케이션 비즈니스 로직 처리와 비즈니스에 관련된 빈의 적합성 검증
  • 트랜잭션 처리
  • 다른 계층들과 통신하기 위한 인터페이스 제공
  • 비즈니스 레벨에 있는 객체들간의 관계를 관리
  • 프리젠테이션 계층과 퍼시스턴스 계층 사이의 다리 역할을 해 그 둘이 직접 통신하지 않도록 함으로써 어플리케이션에 유연성을 더함.
  • 비즈니스 서비스를 얻기 위하여 프리젠테이션 계층으로부터 컨텍스트 객체를 비즈니스 계층으로 넘겨주는 기능
  • 비즈니스 로직과 퍼시스턴스 계층 사이의 실제 구현 관리

도메인 모델 계층

마지막으로 우리는 중대규모의 웹 어플리케이션을 얘기하고 있기 때문에 도메인 객체 계층은 OrderOrderLineItemProduct 객체들과 같은 실제 비즈니스 객체를 표현하게 된다. 이 계층은 개발자가 도메인 객체와 일치시키기 위해 불필요한 데이터 전송용 객체(data transfer objects, DTO) 를 제작하는 것을 막아 준다.  예를 들어 하이버네이트는 데이터베이스의 정보를 도메인 객체에 저장하여 UI 에 표현할 수 있도록 해 준다. 그리고 이 객체들은 수정되거나 하여 다시 퍼시스턴스 계층, 하이버네이트로 돌아와 데이터베이스의 정보를 업데이트하는 데 사용된다.  그리고 여러 계층을 통과하면서 계층들간의 통신시 데이터 전송용 객체(DTO)를 사용하였을 때 발생할 수 있는 데이터의 유실 때문에 데이터 전송용 객체를 사용하지 말 것을 권한다. 이 모델은 자바 개발자들이 별다른 코딩 없이도 객체지향적 방식으로 일할 수 있도록 도와 준다.

간단한 샘플 예제를 통한 각 계층 엮어 보기

이제 고수준 관점에서 각각의 계층을 알아보았으니 실제로 적용해 보도록 하자. 다시 얘기하지만 이 예제에서 스트럿츠, 스프링, 그리고 하이버네이트 프레임웍을 사용할 것이다. 각각의 프레임웍에 대해서 자세히 다루기에는 이 글 하나로는 너무도 부족하고 단지 여기서는 각각의 프레임웍을 어떻게 엮어서 사용하는지를 살펴보기로 한다. 샘플 어플리케이션은 사용자 요청이 각각의 계층을 어떻게 통과하는지를 보여 줄 것이다. 이 샘플 어플리케이션의 사용자는 새로운 주문(Order)를 데이터베이스에 저장하고 이미 데이터베이스에 존재하는 주문(Order)를 살펴보는 기능을 사용하게 될 것이다. 게다가 보강된 버젼에서는 주문(Order)에 대한 수정과 삭제도 지원하게 될 것이다.

이 샘플 어플리케이션의 소스 코드는 여기서 다운받을 수 있다. 

 

샘플 어플리케이션을 제작할 때 우리는 먼저 각각의 계층들이 상호협동하여 동작하기 위해 필요한 도메인 객체들을 생성할 것이다. 이 도메인 객체들은 도대체 어떤 데이터가 DB에 저장될 것인지, 그리고 어떤 비즈니스 로직이 필요할 것인지, 그리고 그 객체들을 보여주기 위해서는 어떠한 화면들이 필요할 것인지를 우리가 정의하는 데 있어 기초가 된다.

다음으로 우리는 퍼시스턴스 계층들 세팅할 것이며 하이버데이트를 통하여 OR 매핑 규칙을 정할 것이다.

그 다음으로는 비즈니스 로직이 포함된 비즈니스 객체를 정의한다.

그 다음으로는 스프링을 사용하여 이 두 개의 계층, 즉 퍼시스턴스 계층과 비즈니스 계층을 역을 것이다.

마지막으로 스트럿츠를 사용하여 프리젠테이션 계층을 생성할 것이다.

도메인 객체 계층(Domain Object Layer)

이 객체들이야말로 각 계층들간을 자유롭게 오가며 상호교류할 수 있게 하는 객체이므로 코딩을 시작하기에 있어 좋은 것들이다. 이 샘플 도메인 모델은 주문(Order)과 주문 항목(OrderLineItem) 객체들로 이루어져 있다. Order객체는 OrderLine객체에 대하여 일대다 관계를 가지고 있다. 예제 코드는 도메인 객체 계층에 대한 간단한 코드를 포함하고 있다.

  • com.meagle.bo.Order.java: 주문에 대한 헤더 정보를 포함
  • com.meagle.bo.OrderLineItem.java: 주문에 대한 자세한 세부정보를 포함

어플리케이션이 어떻게 계층화되어있는지를 알아보기 쉽게 어플리케이션의 페키지 명을 정하는 것이 좋다. 예를 들면 샘플 어플리케이션에서는 도메인 모델 객체들은 com.meagle.bo 패키지 안에 포함되어 있다. 그리고 더 세부화된 도메인 모델 객체들은 아마도 com.meagle.bo 패키지의 서브 패키지로 생성될 패키지 이래에 포함되게 될 것이다. 비즈니스 로직이 포함된 패키지는 com.meagle.service 로 패키지명이 시작되며 DAO 객체들이 포함된 패키지는 com.meagle.service.dao.hibernate 패키지이다. 프리젠테이션 클래스들은  com.meagle.action 과 com.meagle.forms 패키지 아래에 위치하게 된다. 정확한 패키

지 네이밍 룰을 적용하게 되면 각 클래스들이 제공하는 기능들에 대한 명확한 구분이 되며 유지 보수시에 상당한 비용 절감의 효과를 기대할 수 있다.


퍼시스턴스 계층 설정

 하이버네이트를 가지고 퍼시스턴스 계층을 세팅하려면 몇 가지 과정을 거쳐야 한다. 첫 번째 과정은 영구 저장 매체에 저장될 도메인 모델 객체를 설정하는 일이다. 왜냐하면 하이버네이트는 퍼시스턴스 객체로 사용할 도메인 객체로 POJO(Plain, old Java object) 를 사용하기 때문이다. 따라서 Order와 OrderLine객체는 그 객체들의 필드에 대하여 getter와 setter 메소드들을 가진 빈 형태의 객체여야만 한다.  Order객체는 표준 자바빈 스펙의 객체와 같이 ID,UserNameTotal, 그리고 OrderLineItems 프로퍼티에 대한 getter와 setter 메소드들을 가지고 있다.  물론 OrderLine객체 또한 그 객체의 필드들에 대하여 자바빈 스펙을 따른다.

하이버네이트는 도메인 객체를 RDB로 맵핑하는 데 있어서 XML 파일을 사용한다. 우리의 Order와 OrderLineItem 객체에 대하여 각각에 대해 그 맵핑 관계를 설명하는 두 개의 XML파일이 있다. 필요하다면 그 맵핑 XML파일 생성을 도와주는  XDoclet 과 같은 툴을 사용할 수도 있다. 하이버네이트는 도메인 객체 - RDB 맵핑에 있어 다음과 같은 파일을을 사용한다.

  • Order.hbm.xml
  • OrderLineItem.hbm.xml

예제 어플리케이션에서 이렇게 생성된 파일을 WebContent/WEB-INF/classes/com/meagle/bo 디렉토리에서 찾을 수 있다. 하이버네이트 SessionFactory 는 그것이 어떤 데이터베이스와 통신할 것인가, 그리고 어떤 DataSource나 데이터베이스 커넥션 풀을 사용할 것인가, 그리고 퍼시스턴스 대상이 되는 퍼시스턴스 객체들에는 어떤 것들이 있는가를 설정함으로써 설정이 완료된다.  Session 객체는 SessionFactory객체에 의해 생성되는데, 그것은 자바 객체와 퍼시스턴스 계층의 기능들의 호출(selecting, saving, updating, deleting) 사이의 인터페이스를 제공해주는 객체이다. 우리는 뒤에 이어지는 섹션에서 하이버네이트가 Session객체를 생성하기 위해 어떻게 SessionFactory객체를 설정해야 하는지를 살펴볼 것이다.

비즈니스 계층 설정

이제 우리는 어플리케이션 로직을 수행하고 퍼시스턴스 계층의 작업을 수행하고 UI 계층으로부터 request를 받고 트랜젝션 서비스를 적용할 대상 도메인 객체들을 수중에 넣게 되었다.  이것들을 엮는 작업과 차후 관리를 좀 더 편하게 하기 위해서 스프링 프레임웍의 빈 관리 기능을 사용하면 된다. 스프링은 제어 역행화(inversion of control , IoC 역자주 : 마틴 파울러의 '리팩토링' 에 이 패턴에 대한 설명이 나옵니다. 한번 읽어보시는 것도 괜찮을 듯) 나 연관 삽입(setter dependency injection)을 사용하여 외부 XML파일에 기술된 대로 객체들을 엮어 준다. 제어 역행화(Inversion of control)는 어떤 객체로 하여금 더 고수준의 레벨에서 생성되는 객체들을 받아들여 사용하게 할 수 있는 간단한 개념이다. 이런 방법을 사용함으로써 어떤 객체의 인스턴스가 생성되어 사용될 것인지로부터, 그리고 객체들간의 연관성으로부터 객체들이 더 자유로워질 수 있다.

여기에 IoC를 사용치 않아서 객체들간의 연관성이 심화된 상태의 객체 관계에 대한 그림을 예로 들어 보았다.( 역자주: 그림에서 보듯이 객체 A가 B,C를 생성시키므로 A의 구현은 B와 C에 의존하게 됩니다.그림 3과 비교해서 보시면 됩니다.)

Figure 2
그림 2. IoC를 적용하지 않은 객체 관계. 객체 A가 객체 B와 C를 생성시키는 것을 볼 수 있다..

 

그리고 여기에는 고수준 레벨에서 생성된 객체들이 삽입되어 사용될 수 있도록 IoC패턴을 적용한 예제 그림이 있다. 그럼으로써 객체 A는 객체 B와 C의 구현을 직접적으로 사용할 수가 있다.

Figure 3
그림 3. IoC가 적용된 객체 관게. 객체 A는 객체 B와 C의 인터페이스를 받아들이는 setter 매소드를 가지고 있다. 물론 받아들이는 과정은 setter메소드를 통해서뿐만 아니라 객체 A의 생성자를 통해서도 가능하다.

비즈니스 서비스 객체 작성

비즈니스 객체의 setter에 실제 구현 클래스 대신 인터페이스를 사용하는 것은 실제로 구현될 버젼의 클래스를 비즈니스 객체로부터 분리시키는 역할을 한다.  예제에서는 도메인 객체들의 퍼시스턴스 작업을 처리하기 위한 DAO 객체를 서비스 객체가 받아서 처리하도록 할 것이다. 예제에서 다른 퍼시스턴스 프레임웍으로의 전환이 용이한 하이버네이트를 사용할 것이며 퍼시스턴스 프레임웍의 변화에 대해서는 단지 스프링의 설정을 새로운 DAO 객체 구현을 사용하도록 변경하기만 하면 된다. 예제에서 또한 퍼시스턴스 구조로부터 비즈니스 로직을 분리시키기 위하여 인터페이스와 연관성 삽입(dependency injection)을 사용하는 것을 볼 수 있을 것이다.

여기에 DAO객체 연관에 있어 기초가 되는 비즈니스 서비스 객체 코드가 있다.:

public interface IOrderService {
  public abstract Order saveNewOrder(Order order)
    throws OrderException,
           OrderMinimumAmountException;
  public abstract List findOrderByUser(
                                     String user)
                           throws OrderException;
  public abstract Order findOrderById(int id)
                           throws OrderException;
  public abstract void setOrderDAO(
                             IOrderDAO orderDAO);
}

위 예제 코드에 DAO 객체에 대한 setter메소드가 존재함을 주목하라. getOrderDAO 메소드는 없는데 한번 서비스 객체와 결합된 DAO 객체가 외부에서 참조될 일은 없기 때문에 DAO 객체에 대한 getter메소드를 생성하지 않은 것이다. DAO 객체는 우리의 퍼시스턴스 계층과 통신하이 위하여 사용될 것이다. 우리는 스프링을 사용하여 비즈니스 객체와 DAO 객체를 결합시킬 것이다. 그리고 인터페이스를 사용하였기 때문에 실제 구현을 제한되지 않는다.

다음 단계는 DAO 객체에 대한 실제 구현 객체를 작성하는 일이다. Spring은 자체 내장된 하이버네이트 지원 툴을 지니고 있기 때문에 이번 예제에서는 스프링의 하이버네이트 지원 DAO 클래스인 HibernateDaoSupport 를 확장하여 DAO 클래스를 작성하게 된다. HibernateDaoSupport 클래스를 확장하게 되면 HibernateTemplate 객체에 대한 레퍼런스를 얻어서 사용할 수가 있게 된다.   HibernateTemplate객체를 통하면 하이버네이트 세션과 HibernateExceptions을 처리할 수가 있게 된다. 여기에 DAO 객체를 위한 인터페이스가 있다.:

public interface IOrderDAO {
  public abstract Order findOrderById(
                                    final int id);
  public abstract List findOrdersPlaceByUser(
                           final String placedBy);
  public abstract Order saveOrder(
                               final Order order);
}

 아직도 비즈니스 계층을 위하여 결합되어야 할 몇몇개의 클래스들이 남아 있다. 그중에 HibernateSessionFactory 객체와 TransactionManager 객체가 있는데 이것은 스프링 설정 파일을 통하여 비즈니스 계층에 결합될 수가 있다.  스프링은 HibernateTransactionManager 을 제공하여 스레드에 바인드된 하이버네이트 세션의 트랜잭션 기능을 쉽게 사용할 수 있도록 해 준다. (더 자세히 알고 싶으면 ThreadLocal 를 참고하라.). 여기에 HibernateSessionFactory 과HibernateTransactionManager 를 설정하기 위한 Spring 설정 파일의 한 부분이 있다.:

<bean id="mySessionFactory"
       class="org.springframework.orm.hibernate.
              LocalSessionFactoryBean">
  <property name="mappingResources">
    <list>
      <value>
        com/meagle/bo/Order.hbm.xml
      </value>
      <value>
        com/meagle/bo/OrderLineItem.hbm.xml
      </value>
    </list>
  </property>
  <property name="hibernateProperties">
    <props>
      <prop key="hibernate.dialect">
        net.sf.hibernate.dialect.MySQLDialect
      </prop>
      <prop key="hibernate.show_sql">
        false
      </prop>
      <prop key="hibernate.proxool.xml">
        C:/MyWebApps/.../WEB-INF/proxool.xml
      </prop>
      <prop key="hibernate.proxool.pool_alias">
          spring
      </prop>
    </props>
  </property>
</bean>
<!-- 단지 Hibernate SessionFactory 만 사용할 때의 트랜잭션 매니져  -->
<bean id="myTransactionManager"
         class="org.
                springframework.
                orm.
                hibernate.
                HibernateTransactionManager">
  <property name="sessionFactory">
    <ref local="mySessionFactory"/>
  </property>
  </bean>

각각의 객체들은 스프링 설정 파일의 <bean> 태그 안에서 레퍼런싱 될 수가 있다. 위 예제에서 mySessionFactory빈은 HibernateSessionFactory 타입의 객체를 나타내고 myTransactionManager빈은 하이버네이트 트랜잭션 매니저를 나타낸다. transactionManger 빈이 그 프로퍼티로써 sessionFactory를 가지고 있음을 유의해서 보라transactionManger 의 클래스인 HibernateTransactionManager 클래스는 sessionFactory에 대한 setter메소드와 getter메소드를 가지고 있다. setter와 getter를 가짐으로 인해서 스프링 프레임웍 컨테이너가 시작될 때 설정 파일에 설정된 대로 setter를 호출해서 실제 구현 객체를 HibernateTransactionManager에 집어 넣어 transactionManger 객체를 생성하게 된다. 이런 흐름을 바로 연관성 삽입(dependency injection)이라고 부른다. sessionFactory 프로퍼티에  mySessionFactory 빈이 삽입되게 되는 것이다. 이 두 객체들은 스프링이 초기화될 때에 setter메소드를 사용하여 결합된다.  이런 결합 방식은 싱글톤 객체를 생성하고 그러한 객체들의 생성에 사용되는 Factory를 작성하는 수고를 덜어 준다. mySessionFactory 빈은 두개의 로퍼티(mappingResources,hibernateProperte)를 가지고 있다. 보통 스프링을 사용하지 않고 하이버네이트를 단독으로 사용할 댸 이런 프로퍼티에 대한 설정은 hibernate.cfg.xml 에 저장된다. 그렇지만 스프링은 스프링 설정 파일에다 하이버네이트 설정을 결합시킬 수 있게 함으로써 좀 더 설정을 쉽게 할 수 있게 한다. 좀 더 많은 정보를 원한다면  Spring API 문서를 참고하라.

비즈니스 서비스 객체와 DAO 객체를 결합시키기 위해 필요한 컨테이너 서비스 빈의 설정을 완료했다. 그러면 여기에다가 트랜잭션 매니져 객체만 결합시키면 된다.

여기에 완성된 스프링 설정 파일이 있다.:

<!-- ORDER SERVICE -->
<bean id="orderService"
  class="org.
         springframework.
         transaction.
         interceptor.
         TransactionProxyFactoryBean">
  <property name="transactionManager">
    <ref local="myTransactionManager"/>
  </property>
  <property name="target">
    <ref local="orderTarget"/>
  </property>
  <property name="transactionAttributes">
    <props>
      <prop key="find*">
     PROPAGATION_REQUIRED,readOnly,-OrderException
      </prop>
      <prop key="save*">
     PROPAGATION_REQUIRED,-OrderException
      </prop>
    </props>
  </property>
</bean>
<!-- ORDER TARGET PRIMARY BUSINESS OBJECT:
Hibernate implementation -->
<bean id="orderTarget"
         class="com.
                meagle.
                service.
                spring.
                OrderServiceSpringImpl">
  <property name="orderDAO">
    <ref local="orderDAO"/>
  </property>
</bean>
<!-- ORDER DAO OBJECT -->
<bean id="orderDAO"
         class="com.
                meagle.
                service.
                dao.
                hibernate.
                OrderHibernateDAO">
  <property name="sessionFactory">
    <ref local="mySessionFactory"/>
  </property>
</bean>

그림 4는 우리가 결합시켰던 것들을 개괄적으로 보여준다. 이 그림은 스프링에 의해 각각의 객체들이 어떻게 연관되어 있고 다른 객체에 어떻게 setting되는지를 보여준다. 예제 어플리케이션의 스프링 설정파일과 이 그림에서의 연관 관계를 같이 참고하면서 보면 이해가 빠를 것이다.

Figure 4
그림 4. 스프링이 설정 파일에 기초하여 빈들을 결합시키는 것을 보여주고 있다.

이 예제는 우리가 이전에 정의했던 트랜잭션 매니져에 대한 setter메소드를 가지고 있는  TransactionProxyFactoryBean을 사용하고 있다. TransactionProxyFactoryBean는 선언자를 사용한 트랜잭션 처리와 서비스객체를 다루는 기능을 갖고 있어 사용하기 편리하다. TransactionProxyFactoryBean을 사용하게 되면 트랜잭션이 적용될 메소드의 패턴을 정의하고 어떤 트랜잭션 룰이 그 메소드 패턴에 적용될 것인지를 결정하는 transactionAttributes프로퍼티를 통하여 어떻게 트랜잭션이 처리될 것인지를 정의할 수가 있다. 설정 격리 레벨와 트랜잭션 커밋,롤백에 대한 더 자세한 정보를 얻기를 원하면 TransactionAttributeEditor 를 참고하라.

TransactionProxyFactoryBean 클래스는 target프로퍼티에 대한 setter메소드를 가지고 있는데, target 프로퍼티는 orderTarget이라고 불리는 우리가 정의하는 비즈니스 서비스 객체가 레퍼런싱된다. orderTarget 빈은 어떤 비즈니스 서비스 클래스가 사용될 것인를 결정한다. 그리고 그것은 setOrderDAO() 같은 setter메소드를 통해 접근될 수 있는 프로퍼티를 가지고 있게 된다. 이 프로퍼티에는 우리의 퍼시스턴스 계층과 통신하는 orderDAO객체가 세팅된다.

스프링과 빈에 대해 알아야 할 한가지 사항이 더 있는데 그것은 빈은 두 가지 모드로 작동한다는 것이다. 이것은 싱글톤과 프로토타입으로써 정의된다. 기본 모드는 모든 곳에서 동일한 객체의 레퍼런스를 가지고 작업하게 되는 싱글톤 모드이다. 이것은 무상태 세션 빈(EJB에서의)이 제공하는 것과 같은 무상태 작업을 요구할 떄에 사용된다. 그리고 프로토타입 모드는 스프링 설정파일을 사용하여 결합되는 객체를 스프링에 요구할 때마다 새로운 인스턴스를 만들어 돌려주는 방식이다. 각각의 사용자가 작업 처리를 위해 각각의 객체 인스턴스를 필요로 하면 이 모드를 사용해야 한다.

서비스 로케이터(Service Locator) 제공

서비스 객체들이 DAO 객체들과 연결되어 이제 서비스 계층을 다른 계층과 결합할 수가 있게 되었다. 아래에서 보게 될 코드들은 일반적으로 스트럿츠나 스윙을 사용한 UI 계층에서 보게 될 코드들이다. 서비스 로케이터를 사용하여 스프링 컨텍스트에서 자원들을 빼내어 사용하는 것을 좀 더 쉽게 만들 수 있다. 물론 bean의 ID를 사용하여 스프링으로부터 직접 요청하여 자원을 빼내어 사용할 수도 있다.

여기에 스트럿츠 액션에 서비스 로케이터를 사용하는 예가 있다.(orderService라는 Action클래스의 Property로 서비스가 세팅된다.)

public abstract class BaseAction extends Action {
  private IOrderService orderService;
  public void setServlet(ActionServlet
                                 actionServlet) {
    super.setServlet(actionServlet);
    ServletContext servletContext =
               actionServlet.getServletContext();
    WebApplicationContext wac =
      WebApplicationContextUtils.
         getRequiredWebApplicationContext(
                                 servletContext);
      this.orderService = (IOrderService)
                     wac.getBean("orderService");
  }
  protected IOrderService getOrderService() {
    return orderService;
  }
}

UI 계층 설정

이번 예제에서 UI 계층 프레임웍으로 스트럿츠를 사용한다. 여기서 어플리케이션 계층화에 있어 스트럿츠와 관련된 내용에 대해 이야기해 볼 것이다. struts-config.xml 파일의 Action 설정을 살펴봄으로 시작해 보자.

<action path="/SaveNewOrder"
    type="com.meagle.action.SaveOrderAction"
    name="OrderForm"
    scope="request"
    validate="true"
    input="/NewOrder.jsp">
  <display-name>Save New Order</display-name>
  <exception key="error.order.save"
    path="/NewOrder.jsp"
    scope="request"
    type="com.meagle.exception.OrderException"/>
  <exception key="error.order.not.enough.money"
    path="/NewOrder.jsp"
    scope="request"
    type="com.
          meagle.
          exception.
          OrderMinimumAmountException"/>
  <forward name="success" path="/ViewOrder.jsp"/>
  <forward name="failure" path="/NewOrder.jsp"/>
</action>

SaveNewOrder 액션은 UI 계층에서 사용자가 전송한 order를 퍼시스턴스 상태로 저장하기 위하여 사용된다. 일반적인 스트럿츠 액션이라고 보여지나 이 액션에 대한 exception 설정은 주목해서 볼 필요가 있다. 이 exception들은 역시applicationContext-hibernate.xml 같은 비즈니스 서비스 객체 생성을 위한 transactionAttributes 등의 프로퍼티를 설정하는 스프링 설정 파일에도 설정된다. 비즈니스 계층에서 이러한 예외가 발생하여 UI계층으로 그 예외를 돌려주면 우리는 UI계층에서 그것들을 적절히 처리할 수 있다. 첫번째 예외인 OrderException 은 order객체를 퍼시스턴스 계층에 저장시 실패할 때에 이 액션 객체에 의해 사용될 것이다. 이것은 트랜잭션을 rollback시키며 예외를 비즈니스 계층에서 UI계층, 즉 스트럿츠로 보낼 것이다. OrderMinimumAmountException 은 최소 order 총량에 맞지 않을 때 비즈니스 로직상에서 발생하며 역시 트랜잭션 레벨에서 처리된다. 이 예외가 발생하게 되면 또한 트랜잭션 rollbackwill 이 발생하게 되며 이 예외를 받게 될 UI 계층에서 알맞은 처리가 이루어질 것이다.

마지막 결합 과정은 프리젠테이션 계층과 비즈니스 계층을 엮는 것이다. 이것은 이전에 설명했던 서비스 로케이터를 사용함으로써 이루어진다. 서비스 계층은 우리의 비즈니스 계층과 퍼시스턴스 계층에 대한 인터페이스로써 동작하게 된다. 여기에 SaveNewOrder 액션이 비즈니스 메소드를 호출하기 위해 서비스 로케이터를 사용하는 것을 보여주고 있다.

public ActionForward execute(
  ActionMapping mapping,
  ActionForm form,
  javax.servlet.http.HttpServletRequest request,
  javax.servlet.http.HttpServletResponse response)
  throws java.lang.Exception {
  OrderForm oForm = (OrderForm) form;
  // 퍼시스턴스 계층에 저장될 Order객체를 생성하기
  // 위해 폼을 사용한다.
  // 샘플 어플리케이션의 풀 소스를 참고하라.
  // 결합된 비즈니스 객체를 BaseAction에서 생성된
  // 서비스 로케이터로부터 얻어 사용하면 된다.
  // Order 객체를 저장하기 위한 서비스 계층의 작업과
  // 더 윗단에 있는 작업을 분리하고 있다.
  getOrderService().saveNewOrder(order);
  oForm.setOrder(order);
  ActionMessages messages = new ActionMessages();
  messages.add(
      ActionMessages.GLOBAL_MESSAGE,
     new ActionMessage(
      "message.order.saved.successfully"));
  saveMessages(request, messages);
  return mapping.findForward("success");
}

결론

이 글은 기술과 구조의 측면에서 상당히 많은 넓은 부분을 다루고 있다. 기본 개념은 이렇다. 더 좋은 어플리케이션을 만들기 위해서는 유저 인터페이스 계층과 퍼시스턴스 계층과 또 다른 계층들을 분리해야만 한다는 것이다. 그런 것을 잘 하는 것은 코드량을 줄일 수가 있고 새 컴포넌트의 추가를 용이하게 만들며 차후에 있게 될 유지보수를 쉽게 만든다. 여기서 다루어진 기술들은 특별한 분야에 대한 문제를 잘 해결해 줄 수도 있다. 하지만,  이런 구조를 사용함으로써 각각의 어플리케이션 계층에 다른 기술을 사용할 수도 있다. 예를 들면 당신은 퍼시스턴스 계층의 구현을 위해 하이버네이트 프레임웍을 사용하고 싶지 않을지도 모른다. DAO 객체 구현에 있어 인터페이스를 사용하여 코딩하고 있기 때문에 거기에 다른 기술이나 프레임웍( iBATIS 등) 을 사용하는 법은 어떻게 보면 명백하리만큼 쉬운 것인지도 모른다. 아니면 UI 계층을 스트럿츠 말고 다른 프레임웍으로 교체하고 싶을지도 모른다. 단순히 UI 계층의 구현을 변경하는 것은 비즈니스 로직이나 퍼시스턴스 계층에 영향을 미치지 않는 것이 우리가 지금까지 설명했던 구조의 특징이다.  역시 퍼시스턴스 계층의 변경은 UI 계층이나 서비스 계층에 영향을 미치지 않을 것이다.  웹 어플리케이션을 제작한다는 것은 쉬운 일이 아니다. 하지만 어플리케이션의 각 계층들을 분리하여 제작하고 적절한 프레임웍을 사용하여 결합함으로써 어플리케이션을 제작하는 것이 그 쉽지 않은 작업들을 좀 더 편하게 만들어줄 수 있다.

마크 이글 은 Atlanta, GA.소재의 MATRIX Resources 의 선임 소프트뤠어 연구원으로 일하고 있다.


Return to ONJava.com.

Copyright © 2004 O'Reilly Media, Inc.

반응형
반응형

예전 블로그 복사 http://blog.daum.net/7dbwnckd/2762431 


VTL 문서에는 없어서 정리해봄!

 

1. velocity macro 의 사용

 

#macro(test)

  <tr>

      <td>test</td>

  </tr>

#end

 

 #test() 라고 사용한다.

 

또한 파라메타를 받을 수 있음

 

#macro(test $a)

  $a

#end

이렇게도 된데요 ㅋㅋ 해보지는 않았어요.

반응형
반응형


* 예전 블로그 복사 - http://blog.daum.net/7dbwnckd/7972581 


아래와 같은 에러는...

 

심각: Error reading tld listeners java.lang.NullPointerException
java.lang.NullPointerException
 at org.apache.log4j.Category.isEnabledFor(Category.java:746)
 at org.apache.commons.logging.impl.Log4JLogger.isTraceEnabled(Log4JLogger.java:327)
 at org.apache.catalina.startup.TldConfig.tldScanResourcePaths(TldConfig.java:581)
 at org.apache.catalina.startup.TldConfig.execute(TldConfig.java:282)
 at org.apache.catalina.core.StandardContext.processTlds(StandardContext.java:4307)
 at org.apache.catalina.core.StandardContext.start(StandardContext.java:4144)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1014)
 at org.apache.catalina.core.StandardHost.start(StandardHost.java:736)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1014)
 at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
 at org.apache.catalina.core.StandardService.start(StandardService.java:448)
 at org.apache.catalina.core.StandardServer.start(StandardServer.java:700)
 at org.apache.catalina.startup.Catalina.start(Catalina.java:552)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:295)
 at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:433)

 

-------------------------------------------------------------------------------------------------

log4j 1.2.x버전과 1.3.x버전을 쓰실 때 
현재 배포된 commons-logging-1.1.jar파일과 문제를 일으켜
웹 컨테이너 리로딩 시 불필요한 Exception이 발생합니다.
Apahce site에서 확인 한 결과
[1.0.4 Release - 16 Jun 2004]
"The 1.0.4 release of commons-logging is a service release containing support for both the 1.2.x and 1.3.x series of Log4J releases. "
log4j 1.2.x와 1.3.x를 commons-logging-1.0.4에서 지원합니다.
원래는 1.0.4 이상에서도 지원 한다고 되어 있는데
commons-logging-1.1과 commons-logging-1.1.1에서는 위와 같은 문제가 발생하고 있습니다.

-------------------------------------------------------------------------------------------------

는 내용을 알게 되었다.

반응형
반응형


* 예전 블로그 복사 - http://blog.daum.net/7dbwnckd/1616463


java.lang.UnsupportedClassVersionError

 

(Unsupported major.minor version 49.0)

 

 

 

이 에러는 자바의 컴파일 버전이 충돌이 나서이다.

 

하위버전의 클래스파일을 상위버전이 읽어들일때는 상관없지만

 

상위버전의 클래스파일을 하위버전이 읽어올때는 위와 같은 에러를 낸다

 

 

< 에러 상세코드 >


version 50.0   컴파일 버전 : 1.6

version 49.0   컴파일 버전 : 1.5

version 48.0   컴파일 버전 : 1.4

 

해결책>>

 

내텀퓨터 ->속성 -> 고급-> 환경변수에서

 

자바의 버전을 알맞게 셋팅한다.

 

즉... 상위 버전에서 컴파일된 파일들은 모두 자신이 현재 쓸려고 하는 하위버전대로 다시 컴파일 하여야 한다.

반응형
반응형


* 예전 블로그 복사 -  http://blog.daum.net/7dbwnckd/1616449


/conf/catalina/localhost/ContextName.xml 을 넣어야 잘 돈다. Root에서는 다시 해 보겠음.

 

 


<Context path="/framework" docBase="${catalina.home}/webapps/framework" debug="5" reloadable="true" crossContext="true">

 <Logger className="org.apache.catalina.logger.FileLogger" prefix="localhost_dbwnckd_log." suffix=".txt" timestamp="true"/>

 <Resource name="jdbc/dbwnckd" auth="Container" type="javax.sql.DataSource"/>

 <ResourceParams name="jdbc/dbwnckd">
  <parameter>
  <name>factory</name>
  <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
  </parameter>

  <!-- Maximum number of dB connections in pool. Make sure you
  configure your mysqld max_connections large enough to handle
  all of your db connections. Set to 0 for no limit.
  -->
  <parameter>
  <name>maxActive</name>
  <value>100</value>
  </parameter>

  <!-- Maximum number of idle dB connections to retain in pool.
  Set to -1 for no limit.  See also the DBCP documentation on this
  and the minEvictableIdleTimeMillis configuration parameter.
  -->
  <parameter>
  <name>maxIdle</name>
  <value>30</value>
  </parameter>

  <!-- Maximum time to wait for a dB connection to become available
  in ms, in this example 10 seconds. An Exception is thrown if
  this timeout is exceeded.  Set to -1 to wait indefinitely.
  -->
  <parameter>
  <name>maxWait</name>
  <value>10000</value>
  </parameter>

  <!-- MySQL dB username and password for dB connections  -->
  <parameter>
  <name>username</name>
  <value>root</value>
  </parameter>
  <parameter>
  <name>password</name>
  <value>admin</value>
  </parameter>

  <!-- Class name for the old mm.mysql JDBC driver - uncomment this entry and comment next
  if you want to use this driver - we recommend using Connector/J though
  <parameter>
  <name>driverClassName</name>
  <value>org.gjt.mm.mysql.Driver</value>
  </parameter>
  -->

  <!-- Class name for the official MySQL Connector/J driver -->
  <parameter>
  <name>driverClassName</name>
  <value>com.mysql.jdbc.Driver</value>
  </parameter>

  <!-- The JDBC connection url for connecting to your MySQL dB.
  The autoReconnect=true argument to the url makes sure that the
  mm.mysql JDBC Driver will automatically reconnect if mysqld closed the
  connection.  mysqld by default closes idle connections after 8 hours.
  -->
  <parameter>
  <name>url</name>
  <value>jdbc:mysql://localhost:3306/test?autoReconnect=true</value>
  </parameter>
 </ResourceParams>
</Context>

반응형
반응형


* 예전 블로그 복사 - http://blog.daum.net/7dbwnckd/1616426


이번에 다시 sql과 연동을 시도하면서 새로운 문제에 부딪히게 되었는데~

 

예전 처럼(Tomcat 5.0) 시도하면 Tomcat 시작 시 Warning이 뜨게 된다.

 

따라서 다른 방법으로 시도해야 하는데~

 

바로... 아래와 같다.

 

 

* 각각의 context밑의 web.xml의 설정

 

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <description>
      JSP 2.0 Examples.
    </description>
    <display-name>JSP 2.0 Examples</display-name>


 <resource-ref>
  <description>DB Connection</description>
  <res-ref-name>jdbc/dbwnckd</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
 </resource-ref>


</web-app>


* 각각의 context밑의 context.xml의 설정

 

<Context path="" docBase="emergency" debug="5" reloadable="true" crossContext="true">

 <Logger className="org.apache.catalina.logger.FileLogger" prefix="localhost_emergency_log." suffix=".txt" timestamp="true"/>
 
 <Resource name="jdbc/dbwnckd" 
   auth="Container" 
   type="javax.sql.DataSource"
   maxActive="100" 
   maxIdle="30" 
   maxWait="10000"
     username="root" 
     password="admin" 
     driverClassName="com.mysql.jdbc.Driver"
     url="jdbc:mysql://localhost:3306/mysql?autoReconnect=true"/>
      
   <WatchedResource>WEB-INF/web.xml</WatchedResource>

 

</Context>

 

반응형
반응형


1. 튜플의 연산

- 튜플은 임의의 객체의 순서를 가지는 모음으로 리스트와 유사한 면이 많다. 차이점은 변경 불가능 형이라는 것이다. 또한 튜플은 리스트가 가지고 있는 것과 같은 메소드를 쓰지 않는다. 튜플은  시퀀스 형이므로 시퀀스 형이 가지는 일반적인 연산을 모두 가진다. (인덱싱, 슬라이싱, 연결, 반복, 길이 연산 등) 튜플은 ()로 표현한다.

 

아래의 문법은 모두 튜플이다.

>>>t =()

>>>t=(1,2,3)

>>>t=1,2,3

>>>r=(1,)

>>>r=1,

 

튜플은 중복과 좌우변 복수개의 자료를 치환할 수 있다.

>>>t=(12345, 54321, 'hello!')

>>>u=t,(1,2,3,4,5)

>>u

((12345, 54321, 'hello!'),(1,2,3,4,5))

>>>x=1

>>>y=2

>>>x,y = y,x

>>>x,y

(2,1)

 

 

2. 패킹과 언패킹

t=1,2,'hello!'

x,y,z=t

a=['foo','bar',4,5]

[x,y,z,w] = a

 

 

3. 리스트와의 공통점과 차이점

 

3-1. 공통점

 - 임의의 객체를 저장할 수 있다는 것과 시퀀스 자료형이라는 것

 - 인덱싱,슬라이싱,연결,반복지원

3-2. 차이점

- 문자열과 같은 변경불가능 시퀀스형(튜플의 한 요소의 값을 인덱스 참조로 바꿀 수 없다.) 따라서, 튜플 아이템을 변경하려면 슬라이싱과 연결(Concate-nation)을 이용해야 한다.

- 메소드를 가지지 않는다.

- 튜플은 포맷 문자열 지원(문자열 부분 참조), 함수 호출시 가변 인수 지원 기능 등이 있다.

 

튜플과 리스트는 상호변환이 가능하다.

>>>T=(1,2,3,4,5)

>>>L=list(T)

>>>L[0]=100

>>>L

[100,2,3,4,5]

>>>T=tuple(L)

>>>T

(100,2,3,4,5)

 

4. 튜플을 사용하는 경우

 - 함수에 있어서 하나 이상의 값을 리턴하는 경우

 - 문자열 포매팅

 - 튜플에 있는 값들을 함수 인수로 사용할 때

 - 그 이외에 고정된 값을 표현하기 위하여 튜플을 사용한다.

 

5. 경로명 다루기

 os.path 모듈의 경로명(pathname)을 다루는 함수(split)가 튜플을 사용한다. 

 

6. url 다루기

urlparse(), urlunparse(), urljoin() 

반응형
반응형


1. 파이썬 리스트

- 리스트는 순서를 가지는 객체들의 집합으로, 파이썬 자료형들 중에서 가장 유용하게 활용된다. 리스트는 시퀀스 자료형이면서 변경 가능형이다.(내장 자료형 중 변경 가능 자료형은 리스트와 사전뿐이다.)따라서 시퀀스 자료형의 일반적인 특징(인덱싱, 슬라이싱, 연결, 반복, 멤버십 테스트 등)을 지원하며, 변경이 가능한 특성에 따라 자료의 크기를 동적으로 임의 조절하거나, 내용을 치환하여 변경할 수 있다. 리스트는 []로 표현된다.

 

 

2. 중첩리스트

>>>s=[1,2,3]

>>>t=['begin',s,'end']

>>>t

['begin',[1,2,3],'end']

>>>t[1][1]

2

 

3. 리스트의 메소드들

 - append, insert, index, count, sort, reverse, remove, pop, extend(리스트를 추가)

 

4. 리스트의 정렬

- 기본적으로 오름차순 정렬

>>>L=[1,5,3,9,8,4,2]

>>>L.sort()

>>>L

[1,2,3,4,5,8,9]

- 내림차순정렬

>>>L=[1,6,3,8,6,2,9]

>>>L.sort(reverse=True)

>>>L

[9,8,6,6,3,2,1]

 

5. 리스트 내장

- range(x) 함수 # 0부터 x보다 작은 수의 정수 리스트 반환

>>>L=[k*k for k in range(10)]

>>>print L

[0,1,4,9,16,25,36,49,64,81]

 

6. 지역적으로 사용 가능한 이름 리스트 얻기

- 인수 없이 dir()하면 현재 지역적으로 사용 가능한 심볼 테이블(사용 가능한 이름 목록)의 내용을 알 수 있다. dir 인수에 임의의 객체를 전달하면, 그 객체 내에서 활용할 수 있는 어트리뷰트(함수,변수 등의 이름들)의 리스트를 리턴한다. 모듈에 어떤 함수나 변수가 정의되어 있는가, 클래스에 어떤 메소드를 활용할 수 있는가 등의 정보를 손쉽게 얻을 수 있다.

 

 

 

반응형
반응형


1. 시퀀스 자료형

 시퀀스 자료형이란, 여러 객체들을 저장하는 저장 자료형이며, 각 객체들은순서를 가진다. 그로인해 각 요소들은 첨자(Index)를 이용하여 참조가 가능하다. 특성을 정리하면 다음과 같다.

 - 여러 개의 객체를 저장할 수 있다.

 - 각 객체들은 순서를 갖는다.

 - 각 객체들은 첨자를 이용하여 참조 가능하다.

 

예)

>>>s = 'abcdef'

 

>>>s[0]    # 인덱싱(indexing)

>>>s[1:3]  # 슬라이싱(slicing)

 

>>>ss = 'abc' + 'def' # 연결하기(concatenation)

 

>>>ss * 4 #  반복하기(repetition) ss+ss+ss+ss 와 동일

 

>>> c in ss  # 멤버쉽 테스트 어떤 객체가 시퀀스 객체에 포함되었는지 검사

True

 

 

반응형
반응형


예전 블로그 복사 - http://blog.daum.net/7dbwnckd/7972577


1. 파이썬 수치 자료형의 표현 범위

 

 데이터형비트 수표현 범위 
 int32비트 -2147483648 ~ 2147483647
 long 무제한(메모리가 허용하는 한) 무제한
 float 64비트 유효자리 15자리, 약 10의+-308승
 complex 실수부 및 허수부 각각 64비트 유효자리 15자리, 약 10의+-308승

 

2. Decimal 클래스의 활용 : 오차 없는 계산 결과를 얻어야 한다면 사용하라.

반응형
반응형


* 예전 블로그 복사. - http://blog.daum.net/7dbwnckd/7972575


Eric Raymond씨도 "How To Become A Hacker"란 글에서 프로그래밍을 배우고 싶다면 python을 배우라고 쓴 적이 있습니다. 저도, 꽤 많은 언어를 쓰고 있다고 생각하지만, Python만큼 강력하며, 쉽게 배울 수 있는 언어를 본 적이 없습니다. Python 언어에 대한 자세한 사항은 Python 관련 책이나 문서에서 충분히 얻을 수 있을 것이므로, Python에 대한 특징을 바라보는 입장에서 정리해 보았습니다. 여가 시간이 있거나, 배우고 싶은 언어를 찾고 있다면, Python을 익혀보기를 강력하게 추천합니다.

 

Programming에 대한 경험이 없는 사람의 경우

  • 복잡한 문법(어느 정도 주관적인 기준으로 바라본 것이긴 하지만)을 필요로 하는 Perl이나 C, C++에 비해 문법이 간단하다. 따라서 배우기 쉽다는 장점이 있다.
  • C와 비교했을 때, 포인터와 같은 배우기 힘든 개념이 없기 때문에, 상대적으로 많은 시간을 프로그램 구조와 디자인 등에 투자할 수 있다.
  • C++과 비교했을때, OOP의 기본적인 사항들은 더욱 빠르게 배울 수 있다.
  • 기본적으로 인터프리터 방식이기 때문에, 코드의 결과를 바로바로 확인해 볼 수 있고, 다양한 운영체제를 지원한다. 또한 원할 경우, 바로 실행 파일(.exe)을 만들어 낼 수도 있다.
  • 다양한 라이브러리를 지원하기 때문에, 상대적으로 적은 양의 코드만으로도 GUI 프로그램, game, CGI 프로그램등을 빠르게 만들 수 있다.

C/C++ 프로그래머인 경우

  • C/C++ 그리고 Bourne shell과 유사한 문법을 가지고 있기 때문에, 기타 다른 스크립트 언어에 비해 익히는 속도가 매우 빠르다.
  • OS에 관련된 기능들은 (예: POSIX interface) 대부분 C/C++에서 제공되는 함수와 같은 이름을 쓰고, 심지어 인자 타입이나 의미까지 비슷한 경우가 많기 때문에, 익혀야하는 함수들이 타 스크립트 언어와 비교할 때 많지 않다.
  • class, virtual function, 제한적인 operator overloading을 지원하기 때문에 C++에서 썼던 디자인 방식 그대로 적용할 수 있다.
  • Mixed language programming -- Python은 기타 다른 스크립트 언어에 비해 C/C++로 python module을 작성하기가 매우 쉽다. (어느 정도 주관적인 견해 포함)
  • 제한적이나마 lambda expression을 제공하기 때문에, LISP/Scheme 등에 익숙한 사람들도 비슷한 코드를 쉽게 만들 수 있다. map(), apply() 함수 제공, closure 제공
  • 다른 스크립트 언어에 비해 문서화가 잘 되어 있으며 (Tutorial, Library Reference, Language Reference 제공), 문법 자체에 LISP/Scheme과 마찬가지로 documentation string을 집어 넣을 수 있고, built-in 함수인 dir()을 쓰면, 함수, 모듈, 오브젝트가 제공하는 심볼 테이블을 바로 볼 수 있기 때문에 다른 스크립트 언어를 쓸 때에 비해, 따로 문서를 찾아보는 빈도가 낮아진다.
  • 함수, 클래스 또는 변수에 Decorator를 직접 제작할 수 있다. Decorator란 C/C++ 문법상 qualifier에 해당하는 것으로 다양한 wrapper를 만들거나 class인 경우 static, class method를 지정할 수 있다. Python 2.4 Decorators 참고

기타 사항

  • Dictionary (Postscript의 dictionary나 다른 언어의 associative array에 해당) 타입이 제공된다. 또한 immutable list에 가까운 tuple 타입이 제공되며, 서로 대입이 가능하기 때문에, 한 줄의 코드로 변수 값을 치환할 수도 있다.
  • 모든 타입은 repr() 연산을 써서 문자열로 변경할 수 있다. 또한 eval() 연산을 써서 문자열을 평가한 후 python type으로 불러 올 수 있다. 따라서 이 기능과 여러 DB 모듈을 잘 활용하면, 모든 Python type을 DB에 저장/로드하는 것이 가능해진다.
  • GTK+ binding이 제공되며, GTK+ C API 또는 C++ API(gtkmm)에 비해 훨씬 간단하게 GUI application을 작성할 수 있다. 또한 이미 GTK binary가 MS Windows 용으로 제공되기 때문에, 간단하게 Windows application도 만들 수 있다. (Pygtk 참고)
  • Python은 SDL binding을 제공하기 때문에, 게임을 만들어 보고 싶은 개발자에게도 최적의 언어라고 할 수 있다. (PyGame 참고)
  • Python 자체적으로 cgi, urllib, httplib 등의 모듈을 제공하며, 다양한 XML parsing module도 제공하며, Berkeley DB, GDBM, sqlite, oracle, ODBC등의 DB 모듈도 제공하기 때문에, Web application을 쉽게 만들 수 있다.
  • zlib, bz2, gzip, zipfie, tarfile등의 모듈을 자체적으로 제공하기 때문에 압축 파일 관련 처리가 매우 쉽다.
  • 다양한 os 기능과 함께 curses 모듈도 제공, terminal에서 실행되는 installer나 administrative tool을 만들기가 편리하다.
  • Built-in source debugger인 pdb를 제공한다.
  • 실제 개발할 때 Emacs(Pymacs, python-mode package 활용)에서 완벽하게 interpreter를 지원하며, 다양한 형태의 (buffer, region)등을 python 실행 결과를 확인할 수도 있다. 또한 Emacs 내부에서 디버거를 실행할 수 있으며(M-x pdb), Web browser w3m package를 쓰면 따로 도움말을 보기 위해 browser를 띄울 필요도 없기 때문에 매우 편리하다! (python-mode, w3m, emacs-w3m 참고)


반응형

+ Recent posts