블로그 이미지
Xeon의 세상 Xeoness

카테고리

Xeon World (23)
Diary (1)
Tuning (0)
Project (0)
Scrap (0)
Media (0)
L ♡ L (0)
일상생활 (4)
Web Programming (14)
IT 강국? 노가다 강국 (4)
Linux (0)
아리아리 동동~ (0)
Total
Today
Yesterday

퍼플린님께서 잘 정리해 주셨다.

아래는 원본 글.

 

CCL을 그대로 따왔으므로 원본 글을 보고 싶으신 분들께서는 http://rinn.kr/49 로 접속하셔서 보시기 바랍니다.

==========================================================================================================================

원래 마이그레이션 포스팅부터 다룰려고 했으나.. 이게 공식위키에서는 엄청 쉽게 이야기 한것과 달리 그냥 라이브러리 교체 정도로 끝나는게 아니라서 일단 바뀐 용어와 개요부터 정리를 좀 해야 할 필요성을 느꼈다.

myBatis로 바뀌면서 기본 용어들이 조금씩 차이가 나기 때문에.. 주의가 필요하다.

기존 SqlMapConfig은 Configration로 변경되었고 sqlMap은 mapper로 변경되었다. 다른 용어들이 변경된 상황이나.. 내부적으로 사용하는 것들(ex. isEqual 을 아에 if 로 바꾼거라던지)을 보면 좀더 범용적으로 알아보기 쉽게 바꿔가는 것을 목표로 가고있는 듯 하다.
익숙해지면 아무래도 코드 읽기도 만들기도 쉬울것으로 보인다.

큰 변화중 하나는 자바 애노테이션을 사용해서 xml을 사용하지 않고 모든것을 자바로만 할수 있게 되었다.
물론 Configration.xml 도 자바에서 직접 DataSource, Environment 등을 선언해서 클래스화 시킬수 있다. xml 스트링으로 설정값등을 저장해야 한다는 것에 부담을 느꼈다면 좋은 변화라고 할수 있겠다.

주의할점은 xml로 Configure를 만들고 환경변수와 property를 클래스로도 만들었다면.. 클래스쪽이 나중에 읽어지게 되서 xml로 되어있는 세팅이 자바 클래스에서 선언해놓은것으로 덮어써지게 된다. 혼란을 줄수 있으니 한가지 방법만으로 프로젝트를 구성하는것이 좋을것이다.

그리고 Configuration configuration = new Con.... 형식으로 선언을 하고 나서는 mapper도 xml이 아니고 configuration.addMapper(UserMapper.class) 형식으로 추가 해야 하기 때문에 어느쪽으로 할것인지 확실하게 결정을 하고 나서 진행해야 한다.


네임스페이스
방식도 변경되었는데.. sqlMap 파일별로 줄여놓은 이름을 사용했다면 이제 풀경로로 사용하게 된다. 공식 설명서에서는 혼란을 줄이고 어떤것이 호출되는지 정확하게 알수 있으니 좋다라고 해놨지만 아무래도 길어지니 쓰기에 불편하기는 하다..
기존에 <sqlMap namespace="User"> 이렇게 쓰던것을
<mapper namespace="myBatis.mapper.UserMapper"> 이렇게 풀 경로로 쓰게 된다.

실제 자바쪽에서 호출할때도

list = session.selectList("myBatis.mappers.UserMapper.getUserList");
 


이렇게 길게 호출 하게 되는데.. 그냥 string 이라서 입력이 여간 불편하다.

이런 경우에 위에서 이야기한 자바 애노테이션 (@Select)을 사용해서 mapper 파일을 xml이 아니고 자바로 만들어놓으면 코드힌트까지 사용해서 편하게 쓸수있다.
UserMapper mapper = session.getMapper(UserMapper.class);

list = mapper.selectUserList(); 


권장사항은 xml 이라고 되어있었던거 같은데.. 편하기는 자바쪽이 편한 구조랄까..;;



기본 용어

SqlSessionFactory : SqlMapClient가 SqlSessionFactory로 변경되었다. 어플리케이션과 같은 라이프사이클을 가지게 된다. 한번만 생성되면 되므로 Manager 클래스에서 싱글톤으로 구현하면 된다.

SqlSessionFactoryBuilder : 환경 값(디비 및 트랜잭션 설정등..)을 읽어와서 SqlSessionFactory 인스턴스를 만들어준다. 기존의 SqlMapClientBuilder 대신 사용된다.

String resource = "org/mybatis/example/Configuration.xml";

Reader reader = Resources.getResourceAsReader(resource);

sqlMapper = new SqlSessionFactoryBuilder().build(reader);


SqlSession : SqlSessionFactory 에서 세션을 하나씩 열어서 개별 쓰레드 별로 사용한다. 세션을 열고나서 실제 쿼리를 수행하게 된다. 하나의 리퀘스트에 하나의 세션을 가지게 되고 사용후에는 꼭 닫아줘야 한다.

mapper : 기존의 sqlMap이 변경된 것이다. 실제 쿼리들이 들어있게 되고 위의 SqlSession을 열어야 호출할 수 있다. method scope를 가지게 되고 해당 메서드가 사용되고나면 사라진다. 별도로 닫거나 할 필요는 없고 SqlSession이 함께 관리 한다.

SqlSession session = sqlSessionFactory.openSession();

try { 

    UserMapper mapper = session.getMapper(UserMapper.class);

    // do work

} finally {

    session.close();

}



변경되거나 추가된 속성들

기존에 조건에 따라 변하는 쿼리를 만들기 위해서 사용되던 태그들이 변경되었다. 조금더 직관적으로 바뀌었고 해당상황(Update, Select)등에 맞춰서 사용할 수 있는 태그들도 추가되었다.

parameterMap은 더이상 사용하지 않게 되었다. parameterMap과 parameterClass 대신 parameterType 하나로 사용한다.
resultMap은 여전히 남아있지만 resultClass 는 resultType 으로 변경되었다.
parameterType과 resultType에는 기본형(int, byte, .... )부터 클래스 명까지 기존처럼 사용할 수 있다.

기존에 procedure를 호출하기 위해 사용하던 <procedure>가 사라지고 statementType 속성이 생겼다. PREPARED, STATEMENT, CALLABLE 중에 하나를 선택할 수 있고 기본값은 PREPARED이다.

파라미터를 매핑하기위해서 사용하던 #var# 형태는 #{var} 로 바뀌었다. $var$ 역시 ${var} 형태로 사용하면 된다.

참고) #{var}와 ${var}의 차이는 prepredStatement의 파라미터로 사용할 것인가.. 그냥 String 값으로 때려박을것인가 하는 것이다. order by 같은 경우에 사용하기 위해서는 order by ${orderParam} 처럼 사용해야 한다. 이 방법을 사용하는 경우 myBatis가 자체적으로 쿼리의 적합성여부를 판단할 수 없기 때문에 사용자의 입력값을 그대로 사용하는 것보다는 개발자가 미리 정해놓은 값등으로 변경하도록 해서 정확한값이 들어올수 있도록 해야 한다.



sqlMap쪽에서 사용하던 typeAlias가 sqlMap이 바뀐 mapper 에서 사용되지 않고 Configration 파일에서 정의하도록 변경되었다.

<typeAliases>
<typeAlias type="vo.UserVO" alias="User"/>
< /typeAliases>

Configration 파일에 위의 형식처럼 Aliase를 정의하면 전체 mapper 에서 사용할 수 있다.



Dynamic Statement의 변화

<isEqual> , <isNull> 등의 구문이 <if>로 통합되었다. 이전보다는 확실히 직관적으로 쓸수 있을듯 하다.
<if test="userID != null"> 형태로 간단하게 사용할 수 있다. (스트럿츠2에서 사용하는 형태 처럼 보이는데..;;)

<dynamic > 형태로 해서 where 조건절이나 and , or 를 동적으로 만들던것이 <where>나 update에서 사용할 수 있는 <set> 등으로 변경되었다.

<select id="getUserList" resultType="User>
SELECT * FROM TR_USER
<where>
<if test="isAdmin != null">
authLevel = '1'
</if>
</where>
< /select>

trim, foreach 태그가 새로 추가 되었다.
trim은 쿼리를 동적생성할때에 쿼리를 연결하기 위해서 컴마(,)를 사용한경우 마지막항목이 조건을 만족하지 못해서 생성된 쿼리 끝에 컴마가 붙어있다던가 하는 경우에 잘라낼 수 있다.
foreach는 반복적인 항목을 동적으로 넣을때 사용할 수 있다. ( ex. where 조건절에서 in 을 사용하는 경우)

공식홈페이지의 위키에 기존 iBatis를 myBatis로 바꿀때 확인해야 할 부분들이 있으니 꼭 참고 하자.
http://code.google.com/p/mybatis/wiki/DocUpgrade3

ps.
지금 있는것도 못하고 있는데 항상 새로운 버전이 쏟아지니 미칠꺼같다 -ㅅ-;;
Flex4도 정식으로 손대보지 못했는데 5 소식이라니.. ㅠㅠ

 

 

Posted by Xeoness
, |

아래 글은 Creative Commons 규정에 맞춰 스토브님의 글을 스크랩 해온 글입니다.

원저작자 표기, 상업적 이용 불가, 컨텐츠 변경 불가입니다.

 

출처 : 스토브 홀로구 :: 64bit 버전 이클립스 바로가기 

Posted by 스토브

 

 

 

글 안 읽고 그냥 64bit 용 다운로드 할사람은

요기서 따운 바람. -> https://docs.google.com/open?id=0B4awPJTRX8X-RXBvYlFUZEZkQ1k


문득 전자정부 후레임워크로 뭐를 개발할게 생겨서 한번 살 시작해 볼려고 공식사이트로 보이는 곳에 가서


개발자용 개발환경 -_- 이라는걸 받았다. 용어를 한글화 한다고 한것 같은데 용어가 드릅게 헷깔리기 그지없다.





그런데 다운 받아서 문득 실행을 시켜보니 exit code=13 과 함께 실행이 되지 않았다.


※ exit code=13 은 jdk와 eclipse bit 버전이 일치하지 않아서 나는 에러이다.


64bit 윈도우를 쓰고 있어서 64bit jdk 를 설치했는데 아마 전자정부 후레임워크 이클립스가 32bit 기반 이클립스로 구성된것인가 보다.




찾아보니까 64bit 전자정부 후레임워크는 또 없단다..............................


할려면 32bit 용 jdk 를 설치해서 eclipse.ini 에 -vm 옵션으로 jdk 를 지정해 주던가 아니면 이클립스를 뽓 받아서 일일히 훌러그인을 설치해 주면 된다고 한다.


왠만하면 64bit 용도 쫌 맹글어서 배포해주지 왜 안해주는지 몰라..




※ 전자정부 후레임워크를 위해 설치할 훌러그인들에 대한 설명 :

http://www.egovframe.org/wiki/doku.php?id=egovframework:dev2:install_guide




요기 가보면 설치할 훌러그인들에 대해서 설명을 뽓 해놨다.


죠기 위 참고 사이트 가보면 이클립스 3.6.2 헬리오스를 기본 베이스로, Spring Core, Maven, eGovFrame, Subversive, PMD, FindBugs, Properties Editor, EclEmma 훌러그인을 설치하라고 한다.



헬리오스는 너무 오래된 것이기 때문에 별로 안땡겨서 최신 버전인 juno 에다 한번 설치를 해 봤는데 막상 다 설치하고 나니 eGovFrame 퍼스펙티브가 나오지 않앗다.


혹시 쥬노에다 설치할 사람들은 나 같은 삽질은 하지 않길 바란다.




그래서 쥬노에다 설치하는건 깔끔하게 포기하고 그 전 버전인 인디고(나는 eclipse-jee-indigo-SR2-win32-x86_64 요 버전에다 작업했음)에다 설치를 해 보니 잘 됐다~


따로 훌러그인들을 설치하기 귀찮은 사람들은 내가 미리 맹글어 놓은 이클립 with eGovFrame 를 따운 받아서 쓰면 된다.


따운은 요기서 -> https://docs.google.com/open?id=0B4awPJTRX8X-RXBvYlFUZEZkQ1k





직접 자기가 쓰던 이클립스에 설치할 사람들은 요런 순서로 설치하면 된다.


1.

Help - Install New Software 에서 work with 로 Indigo - http://~~~ 어쩌고 하는거 선택해서 나오는 목록중


Collaboration > m2e 어쩌고 하는것 두개 체크, Subversive 어쩌고고 하는것 4개 체크(maven, subversive 훌러그인 설치)

Modeling > UML2 Extender SDK 체크( 이거 설치 안하면 eGoveFrame 가 설치 안됨)


요렇게 체크한 다음에 훌러그인을 설치하면 된다.





2.

고다음 Spring Core 설치( 요걸 설치해야 eGovFrame 를 설치할수 있음)

Spring IDE Core 체크 하고 그밖에 설치하고 싶은거 체크해서 설치하면 됨.





3.

eGovFrame 설치





6.

요까지만 설치하고 그냥 써도 될것 같음.

PMD, FindBugs, Properties Editor 는 설치하고 싶으면 설치하셈.


※ EclEmma 는 eGovFrame 설치하면서 설치가 되서 그런가 따로 설치할려면 에러남.




7.

요렇게 다 설치를 했으면 Window - Open Perspective - Other 에 eGovFrame 퍼스펙티브가 추가되 있음





이제 개발하면 됨. 끝~



※ 기타참고


2011/08/12 - [이클립] - Eclipse Indigo Maven Plugin 설치 & 웹프로젝트 생성


2011/07/28 - [이클립] - 후져진 Eclipse Indido 에디터 폰트를 다시 쪽바로 맨들기


2011/08/05 - [이클립] - 설치된 Plugin Uninstall

 

Posted by Xeoness
, |

Singleton과 Static의 차이점을 자세히 알아보고자 구글신의 도움을 얻어보려다 아래와 같은 좋은 자료 발견.

이제야 이해가 동동이 코딱지만큼 된다 -_-;;

 

싱글턴 패턴(Singleton Pattern) - for Beginner


 

사용자 삽입 이미지

이 문서는 GoF(Gang of Four) Design Patterns 에 정의된 패턴 목록 중 싱글턴 패턴(Singleton Pattern)을 다시 정리하면서 내용을 요약한 것이다. 개인적으로 자바와 닷넷 양진영에 모두 경험이 있다보니 동일 패턴에 대해서 상호 비교해보는 것이 어떨까 하는 생각이 들었다. 그래서 간략하지만 Java와 C# 양쪽에 걸쳐 내용을 작성하였으며, 소스코드 템플릿 또한 *.java, *.cs로 나누어 예를 제시하였다. 어쩌면 이 코드들 때문에 내용이 조금 더 복잡해 보일지도 모르겠다.


싱글턴 패턴의 개요

GoF의 23가지 디자인 패턴 중 개발자에게 가장 익숙한 패턴의 하나가 바로 '싱글턴 패턴(Singleton Pattern)'일 것이다. 싱글턴 패턴은 해당 클래스의 인스턴스(instance)가 하나만 만들어지고, 어디서든지 그 유일한 인스턴스에 접근할 수 있도록 하기 위한 패턴의로 정의된다.

GoF에 기술된 내용 중 싱글턴 패턴을 활용할 수 있는 상황은 다음과 같다.

  • 클래스의 인스턴스가 오직 하나여야 함을 보장하고, 잘 정의된 접근 방식에 의해 모든 클라이언트가 접근할 수 있도록 해야 할 때.
  • 유일하게 존재하는 인스턴스가 상속에 의해 확장되어야 할 때, 클라인트는 코드의 수정 없이 확장된 서브클래스의 인스턴스를 사용할 수 있어야 할 때.

이를테면 쓰레드 풀, 캐시, 대화상자, 사용자 설정이라든가 레지스트리 설정을 처리하는 객체, 로그 기록용 객체, 프린터나 그래픽 카드 같은 디바이스를 위한 디바이스 드라이버 같은 것들이 좋은 예가 될 것이다.

싱글턴의 기본적인 구조(Structure)는 그림과 같다.

사용자 삽입 이미지

싱글턴 패턴의 구조

그리고 싱글턴 패턴을 구현하는 고전적인 자바 코드의 기본 템플릿은 아래와 같다.

[자바 코드 1]


// NOTE: This is not thread safe!
public class Singleton {
private static Singleton uniqueInstance;

// other useful instance variables here

private Singleton() {}

public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance
= new Singleton();
}
return uniqueInstance;
}

// other useful methods here
}



아래는 동일한 형태의 C# 버전으로 된 코드이다.

[C# 코드 1]


// NOTE: This is not thread safe!
public sealed class Singleton
{
static Singleton instance=null;
Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance==null)
{
instance
= new Singleton();
}
return instance;
}
}
}



이 코드에서 Singleton 클래스는 private 변수와 생성자를 갖고 있으며 클라이언트에서 인스턴스를 요청할 때까지 Singleton 객체의 생성을 지연(lazy instantiation)하고 있다.

그런데 위의 코드 형태는 주석에도 달려있듯이 멀티(다중)쓰레딩 환경에서의 잠재적 문제를 안고 있기 때문에 실전에 절대 사용하면 안된다. 두개 이상의 쓰레드가 인스턴스를 획득하기 위해 getInstance() 메서드(C#의 경우 Instance 속성(Property))에 진입하여 경합을 벌이는 과정에서 서로 다른 두개의 Singleton 인스턴스가 만들어지는 좋지 않은 상황이 발생할 여지가 있다.

멀티쓰레드 환경에서의 싱글턴(Multithreaded Singleton)

위에서 제기한 문제를 해결하기 위해서는 다음 세가지의 해법을 사용할 수 있다.

  1. 인스턴스를 필요할 때 생성하지 않고, 처음부터 인스턴스를 만들어 버린다. 다시 말해서 lazy instantiation을 포기하고 static 멤버필드를 사용항여 언과 동시에 초기화하는 것이다. 단, 인스턴스를 미리 만들어 버리게 되면, 특히 해당 인스턴스가 자원을 많이 차지하는 컴포넌트일 경우에는 시스템 리소스가 쓸데없이 낭비될 가능성이 있다.
  2. getInstance() 메서드(C#의 경우 Instance 속성)를 동기화시킨다. 단, 동기화시키고자할 때는 getInstance()의 속도가 그렇게 중요하지 않다고 판단될 경우이며 동기화로 인한 오버헤드를 감수해야 한다. - 메서드를 동기화 시키면 일반적으로 성능이 100배 정도는 저하된다고 한다.
  3. DCL(Double-checked Locking) 기법을 사용한다. 단, 자바의 경우 DCL은 자바 5 버전 이상의 JVM 환경에서 인스턴스 변수에 volatile 키워드를 사용해야만 한다. voatile 키워드는 멀티쓰레드 환경에서도 uniqueInstance 변수가 원자성을 유지하도록 하여 올바른 싱글턴 인스턴스의 초기화가 진행되도록 한다(The volatile keyword in Java를 참고하라). 하지만 자바 1.4 및 그 이전에 나온 JVM에서는 메모리 모델의 문제로 제대로 동작하지 않는다는 것에 주의해야 한다(자세한 내용은 The "Double-Checked Locking is Broken" Declaration 참고하라).

설명보다는 코드를 보고 이해하는 것이 빠를 것 같다. 각 해법을 적용하여 멀티쓰레드 환경에서 제대로 동작(thread-safe)하는 싱글턴 구현의 예제 코드들이 아래에 있다.

1. 처음부터 인스턴스를 생성하는 예제 코드

[자바 코드 2]


public class Singleton {
private static Singleton uniqueInstance = new Singleton();

private Singleton() {}

public static Singleton getInstance() {
return uniqueInstance;
}
}



[C# 코드 2]


public sealed class Singleton
{
static readonly Singleton uniqueInstance = new Singleton();

// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}

Singleton()
{
}

public static Singleton Instance
{
get
{
return uniqueInstance;
}
}
}



2. 동기화 예제 코드

[자바 코드 3]


public class Singleton {
private static Singleton uniqueInstance;

// other useful instance variables here

private Singleton() {}

public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance
= new Singleton();
}
return uniqueInstance;
}

// other useful methods here
}



[C# 코드 3]


public sealed class Singleton
{
static Singleton uniqueInstance = null;
static readonly object padlock = new object();

Singleton()
{
}

public static Singleton Instance
{
get
{
lock (padlock)
{
if (uniqueInstance == null)
{
uniqueInstance
= new Singleton();
}
return uniqueInstance;
}
}
}
}



3. DCL(Double-checked Locking) 예제 코드

[자바 코드 4]


//
// Danger! This implementation of Singleton not
// guaranteed to work prior to Java 5
//
public class Singleton {
private volatile static Singleton uniqueInstance;

private Singleton() {}

public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance
= new Singleton();
}
}
}
return uniqueInstance;
}
}



[C# 코드 4]


public sealed class Singleton
{
static Singleton uniqueInstance = null;
static readonly object padlock = new object();

Singleton()
{
}

public static Singleton Instance
{
get
{
if (uniqueInstance == null)
{
lock (padlock)
{
if (uniqueInstance == null)
{
uniqueInstance
= new Singleton();
}
}
}
return uniqueInstance;
}
}
}



아래 C# 코드는 위 코드와 동일하게 DCL을 사용하지만 volatile을 사용하는 다른 버전의 예제이다.

[C# 코드 5]


public class Singleton
{
private static volatile Singleton uniqueInstance = null;

protected Singleton()
{
}

public static Singleton Instance()
{
if (uniqueInstance == null)
{
lock (typeof(Singleton))
{
if (uniqueInstance == null)
{
uniqueInstance
= new Singleton();
}
}
}
return uniqueInstance;
}
}


 

싱글턴 레지스트리(Singleton Registry)

서두에서 "유일하게 존재하는 인스턴스가 상속에 의해 확장되어야 할 때, 클라인트는 코드의 수정 없이 확장된 서브클래스의 인스턴스를 사용할 수 있어야 할 때" 싱글턴을 활용한다고 하였다. 이때에는 서브클래스를 만드는 것이 중요한 게 아니라, 이 새로운 서브클래스의 유일한 인스턴스를 만들어 클라이언트가 이를 사용할 수 있도록 하는 것이 관건이다.

싱글턴의 서브클래스를 만들 때 가장 유연한 방법은 싱글턴에 대한 레지스트리를 사용하는 것이다. 아래 자바 예제 코드는 레지스트리를 갖고 있는 싱글턴으로 특정 클래스 객체의 인스턴스를 생성하기 위해서 리플렉션을 사용하고 있다. 'classname'은 Singleton의 서브클래스 이름이다. 이렇게 하면 서브클래스의 선택에 있어서 런타임에 싱글톤을 결정하는 유연성을 가질 수 있다(자세한 내용은 Simply Singleton을 참고하라).

[자바 코드 5]


import java.util.HashMap;
import org.apache.log4j.Logger;
public class Singleton {
private static HashMap map = new HashMap();
private static Logger logger = Logger.getRootLogger();
protected Singleton() {
// Exists only to thwart instantiation
}
public static synchronized Singleton getInstance(String classname) {
Singleton singleton = (Singleton) map.get(classname);
if (singleton != null) {
logger
.info("got singleton from map: " + singleton);
return singleton;
}
try {
singleton
= (Singleton) Class.forName(classname).newInstance();
}
catch(ClassNotFoundException cnf) {
logger
.fatal("Couldn't find class " + classname);
}
catch(InstantiationException ie) {
logger
.fatal("Couldn't instantiate an object of type " + classname);
}
catch(IllegalAccessException ia) {
logger
.fatal("Couldn't access class " + classname);
}
map
.put(classname, singleton);
logger
.info("created singleton: " + singleton);
return singleton;
}
}


 

결론

이상으로 멀티쓰레딩 환경에서의 싱글턴 패턴 구현 코드를 들여다 보았다. 그렇다면 이 세가지 중 어떤 코드 템플릿을 사용하는 것이 좋을까?

자바에서는 Double-checked locking과 Singleton 패턴 등 (조금 오래되긴 했지만) DCL과 관련한 문서들을 참고해보면 멀티쓰레드 환경에서 제대로 동작하는 싱글턴을 만들기 위한 최상의 솔루션은 동기화를 수락하거나 static 멤버필드를 사용하는 것을 권장하고 있다. 닷넷의 경우 The Correct Double Checked-Lock Pattern Implementation를 보면 [C# 코드 2]와 같은 형태의 코드를 사용할 것을 권장하고 있다.

싱글턴 구현에 있어서 반드시 DCL을 사용해야 하는 특별한 경우가 아니라면 대부분의 상황에서는 static 변수를 사용하거나 동기화 블럭을 사용하는 것으로도 충분할 것 같다. 성능의 저하는 다소 존재하겠지만 다양한 java 및 .net 버전과 메모리 모델에 종속적이지 않은 싱글턴을 구현하는 잇점도 있다고 생각한다. DCL을 적용해야한다면 특히 자바의 경우 volatile 키워드와 함께 반드시 자바 5 버전 이상을 사용해야 한다는 것을 잊지 말아야 한다.

마지막으로 참고가 될만한 두가지 사항을 덧붙이며 싱글턴 패턴에 대한 요약을 마무리한다.

싱글턴 패턴 사용 시 주의할 점(Java 기준)

  • 중복되는 얘기지만 DCL을 사용하려면 자바 5(1.5) 이후 버전을 사용해야 한다.
  • 클래스 로더가 여러개 있으면 싱글턴이 제대로 작동하지 않고, 여러 개의 인스턴스가 생길 수 있다. 이 경우 클래스 로더를 직접 지정해서 사용해야한다.
  • 개인적으로 최근 프로젝트 환경을 보면 슬슬 자바 5 버전으로 많이 갈아타고 있는 듯 하다. 정말 오래된 시스템을 유지 보수하는 경우가 아니라면 자바 1.2 이전 버전을 사용할 일은 없겠지만, 혹시라도 자바 1.2 이전 버전의 환경에서 작업한다면 JVM의 가비지 컬렉터 관련 버그 때문에 싱글턴 레지스트리를 사용해야할 수도 있다.

아래 코드는 클래스 로더를 직접 지정하는 예제이다. 이 코드는 Class.forName() 메서드를 대체할 수 있다(자세한 내용은 Simply Singleton을 참고하라).

[자바 코드 6]


private static Class getClass(String classname) throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader
= Singleton.class.getClassLoader();
}
return (classLoader.loadClass(classname));
}

정적 클래스 변수(메서드) vs. 싱글턴 패턴

굳이 싱글턴 패턴을 사용할 필요없이 전역 클래스 변수(static 멤버필드)를 사용하면 되지 않을까 하는 의문이 들 수도 있다. lazy instantiation을 구현하는 싱글턴 패턴에 비해서 전역 변수를 사용하는 경우 다음과 같은 단점들이 있을 수 있다.

  • 싱글턴 패턴은 static 인스턴스를 미리 생성해놓는 경우를 제외하고는 객체가 필요한 상황이 되었을 때에 비로소 인스턴스를 생성한다. 반면 전역 변수를 사용하면 대부분의 경우는 어플리케이션을 시작할 때 미리 객체가 생성한다. 그런데 그 객체가 자원을 많이 차지하고, 실제로 어플리케이션을 종료할 때까지 한번도 쓰지 않게된다면 괜한 자원만 낭비하는 꼴이 되고만다(이러한 상황은 시스템 플랫폼에 따라 달라질 수도 있다. 어떤 JVM은 객체를 나중에 필요할 때 생성하기도 한다고 한다).
  • 전역 변수를 사용하다 보면 간단한 객체에 대한 전역 레퍼런스를 자꾸 만들게 되면서 네임스페이스를 지저분하게 만드는 경향이 생긴다. 물론 싱글턴도 남용될 수 있지만, 네임스페이스가 지저분해지게 되는 것을 부추길 정도는 아니다.


 

참고 자료

아래는 이 포스트를 작성하기 위해 참고한 도서와 관련 사이트의 목록이다. 영어가 짧고 스크롤의 압박이 심하다보니 사이트의 글들을 죄다 꼼꼼하게 읽어보지는 못했다. ^^; 하지만 정독해보면 분명 도움이 될 내용들이라고 장담한다. ^^

Books

  • GOF의 디자인 패턴, 피어슨에듀케이션 코리아
  • Head First Design Patterns, 한빛미디어
  • 예제로 배우는 C# 디자인 패턴, 정보문화사 (비추. 자바와 닷넷 관련한 더 좋은 패턴 책들이 많이 있다.)
  • J2EE 패턴 (GoF & J2EE), SUN SL-500
  • The Design Patterns Java Companion

Terms

Articles


P.S. 내용 중 잘못된 부분이 있다면 지적 바랍니다. ^^

'Web Programming > Java EE' 카테고리의 다른 글

64bit 버전 이클립스 설치(with eGovFramework)  (0) 2013.02.07
Posted by Xeoness
, |

그리드를 그리던 중 실수가 있었는지 상기와 같은 에러가 발생했다.

아무리봐도 잘못한거 없어 보였는데 ㅋㅋ

단순한 실수 ;;

The problem is that you're using the autoExpandColumn config option but haven't given the column an id - autoExpandColumn is based on 'id' not 'dataIndex'/'header'. Change the colModel to:

autoExpandColumn을 설정할 때 id 지정을 하면서 오타가 있었다. =_=)

id만 맞춰주면 OK
Posted by Xeoness
, |

아래와 같은 에러가 뜰 때의 해결법.

예시 :
============================
HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Servlet execution threw an exception

root cause

java.lang.OutOfMemoryError: PermGen space

note The full stack trace of the root cause is available in the Apache Tomcat/5.5.25 logs.
Apache Tomcat/5.5.25
============================
Solution is :

catalina.sh 파일을 수정하여 메모리를 늘려준다.

아래와 같이 변경해 준다. :

1) vi /usr/local/jakarta/tomcat/bin/catalina.sh

2) Add following line into the catalina.sh file.

예시:
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms512m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC"

아래는 일반적인 catalina.sh 파일에 추가한 모습.
예시:
===========================================
# JSSE_HOME (Optional) May point at your Java Secure Sockets Extension
# (JSSE) installation, whose JAR files will be added to the
# system class path used to start Tomcat.
#
# CATALINA_PID (Optional) Path of the file which should contains the pid
# of catalina startup java process, when start (fork) is used
#
# $Id: catalina.sh 609438 2008-01-06 22:14:28Z markt $
# -----------------------------------------------------------------------------

JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms512m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC"


# OS specific support. $var _must_ be set to either true or false.
cygwin=false
os400=false
darwin=false

========================================
저장하고 빠져 나온 후 catalina를 재기동 한다.

예시:
root@server[~]# /usr/local/jakarta/tomcat/bin/./shutdown.sh
root@server[~]# /usr/local/jakarta/tomcat/bin/./startup.sh
root@server[~]# /usr/local/jakarta/tomcat/bin/./catalina.sh run
root@server[~]# /scripts/restartsrv tomcat

Posted by Xeoness
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함