2014년 11월 12일 수요일

[SPRING] AOP (Aspect Oriented Programming)

[SPRING] AOP (Aspect Oriented Programming) 


1. AOP 목적


AOP 개념을 이해하기 전에 "횡단관심사"라는 단어를 이해할 필요가 있다.

횡단관심사란 보안, 로깅, 트랜젝션등과 같은 기능들처럼 한 애플리케이션의 여러부분에 걸쳐 있는 기능을 의미한다. 
즉, 횡단관심사는 한마디로 한 애플리케이션의 여러부분에 영향을 주는 기능이라고도 할 수 있다.



[참조: 스프링 인 액션]

위 그림을 보면 한 애플리케이션이 여러모듈로 분해된 모습을 보여준다.
각 모듈들은 각자 자기가 맡은 서비스 제공을 위하여 사용되지만 이 모듈들은 모두 보안과 트랜젝션관리 같은 보조 기능을 필요하다.

공통기능을 재사용하는 상속같은 개념도 있지만 상속은 객체의 정적구조에 의존하기 쉽기 때문에 복잡하고 깨지기 쉬운 구조로 되어있다.

물론 AOP도 공통적으로 한 곳에 공통기능을 정의한다는 것은 같다 

하디만 이 기능을 어디에 어떻게 적용할 지 선언할 수 있고 대상 클래스를 전혀 수정할 필요가 없다는 것이 가장 큰 차이점이다. 

정리하자면 AOP는 이러한 횡단관심사의 분리를 위하여 나왔으며 , 횡단관심사를 모듈화를 하기 위하여 AOP라는 개념이 등장하였다.



2. AOP 개념 



AOP 목적에서 우리는 횡단괌심사를 모듈화하기 위하여 AOP를 만들었다고 하였다.
여기서 우린 AOP의 원론적인 의미를 알아야 할 필요가 있다.

Aspect 지향프로그래밍 

횡단 관심사를 모듈화할 때 특별한 클래스로 모듈화 하는데 그 특별한 크래스가 바로 애스팩트라고 부른다.


3. AOP 용어 


애스팩트를 이해하기 위해서는 우리가 이해해야할 용어들이 몇 개 존재한다.

AOP에서 가장 중요한 용어는 어드바이스(Advice), 포인트 컷(Point Cut), 조인 포인트( Join Point) 이 3가지이다.
꼼꼼히 읽어 보길 권고한다.

[참조: 스프링 인 액션]


ㄱ. 어드바이스 

애스팩트(Aspect)는 자신이 무엇을 해야할 지 알고 있어야 한다.
이때 애스팩트가 해야할 작업을 AOP용어로 어드바이스(Advice)라고 한다.

어드바이스는 애스팩트가 해야하는 작업에 대하여 언제 그 작업을 수행해야하는지 정의를 해준다.
어드바이스가 정의하는 언제는 메소드가 호출이전인지 이후인지, 아니면 이전/이후 모두인지 그것도 아니면 예외를 던졌을 때인지를 의미한다.

그 언제를 표현하기위해서는 아래와 같은 선언방식을 사용한다.


* 이전(Before) : 어드바이스 대상 메소드가 호출되기 전에 어드바이스 기능을 수행한다.
* 이후(After) : 결과에 상관없이 어드바이스 대상 메소드가 완료된 후에 어드바이스 기능을 수행한다.
* 반환 이 후 (after-returning) : 어드바이스 대상 메소드가 성공적으로 완료된 후에 어드바이스 기능을 수행한다.
* 예외 발생 이후(after-throwing) : 어드바이스 대상 메소드가 예외를 던진 후에 어드바이스 기능을 수행한다.
* 주위(around) : 어드바이스가 어드바이스 대상메소드를 감싸서 어드바이스 대상 메소드 호출 전과 후에 몇가지 기능을 제공한다??  


ㄴ. 조인 포인트

애플리케이션 하나에도 어드바이스를 적용할 있는 곳이 무수히 많으며 적용할 수 있는 곳을 조인 포인트라고 말한다.
즉 조인포인트는 애플리케이션 실행에 에스팩트를 끼워 넣을 수 있는 지점이며 이러한 조인 포인트 지점은 메소드 호출지점이나 예외발생 , 필드값 수정등이 있다.

ㄷ. 포인트 컷 

한 애스팩트가 전체 애플리케이션의 모든 조인포인트를 다 어드바이스 할 수 없다. 이 때문에 포인트 컷은 에스팩트가 어드바이스할 조인포인트의 영역을 좁혀주는 역할을 한다.

어드바이스가 애스팩트가 무엇을 언제할지 정의한다면 포인트 컷은 어디서를 정의하는 역할은 한다고 보면된다.

포인트 컷을 지정하는 방법은 클래스나 메소드 명을 직접 사용하는 것이지만 정규표현식으로 정의하는 방법도 있다.

ㄹ. 애스팩트

애스팩트는 어드바이스와 포인트 컷을 합친 것이다.
두가지 정보가 합쳐지면 무엇을 언제할지에 대한 모든 정보가 정의된다.

ㅁ. 인트로덕션

인트로덕션을 앞서 설명했던 AOP장점중 기존 클래스에 코드 변경없이 새 메소드나 멤버 변수를 추가하는 기능이다.
예를 들어 어떤 객체의 상태가 언제 마지막으로 변경되었다라는 정보는 추가하는 경우를 생각해보자
각 클래스마다 해당 정보를 저장하는 대신, auditable 어드바이스 클레스를 생성하여 setLastModified(Date) 메소드와 이 상태를 저장하는 멤버변수를 정의한다. 그 다음 인트로덕션을 적용하면 기존 클래스에 소스코드 변경없이 새로운 메소드와 멤버변수를 사용할 수 있다.


ㅂ. 위빙

어드바이스를 핵심코드 로직에 적용하는 것을 위빙(weaving)이라고 한다.

어드바이스를 위빙하는 방식은 3가지 방식이 존재한다.

* 컴파일 시에 위빙하기

컴파일 시 코드를 삽입하는 방법은 aspectJ에서 사용하는 방식이다.
컴파일 방식에서는 핵심 오직을 구현한 자바 코드를 컴파일 할 때 알맞은 위치에 공통코드를 삽입한다.
공통코드는 횡단관심사를 모듈화한 코드를 말한다.

이렇게 컴파일된 코드는 AOP가 적용된 클래스 파일이 생성된다.
컴파일 방식을 제공하는 AOP 도구는 공통코드를 알맞으 위치에 삽입할 수 있도록 도와주는 컴파일러나 IDE를 제공한다.

* 클래스 로딩시에 위빙하기 

AOP 라이브러리는 JVM이 클래스를 로딩할 때 클래스 정보를 변경할 수 있는 에이전트를 제공한다.
이 에이전트는 로딩한 클래스의 바이너리 정보를 변경하여 알맞은 위치에 공통 코드를 삽입한 새로운 클래스 바이너리 코드를 사용하도록 한다.

* 런타임 시에 위빙하기 <제일중요: 스프링은 자체적으로 프록시 기반의 AOP를 지원하고 있음>

런타임시 AOP를 적용할 때는 소스코드나 클래스 정보 자체를 변경하지 않는다. 대신 프록시를 이용하여 AOP를 적용한다. 프록시 기반의 AOP는 핵심로직을 구현한 객체에 직접 접근하는 것이 아니라 중간에 프록시를 생성하여 프록시를 통해 핵심로직을 구현한 객체에 접근하게 된다.
이때,  프록시는 핵심 로직을 실행하기 전 또는 후에 공통기능을 적용하는 방식으로 aop를 적용하기 된다.
프록시 기반에서는 메서드가 호출될 때에만 어드바이스를 적용할 수 있기 때문에 필드 값 변경과 같은 조인 포인트에 대해서는 적용할 수 없는 한계가 있다. 


4. Spring에서의 AOP 의 특징



이번엔 Spring에서 지원하는 AOP 특징에 대해서 정리해보자.

1. 스프링은 자체적으로 프록시 기반의 AOP를 지원하고 있다 

그래서 스프링 AOP는 메서드 호출 조인포인트만을 지원한다. 
만약 필드 값 변경 같은 조인포인트를 사용하고 싶다면 AspectJ같은 풍부한 기능을 지원하는 AOP도구를 사용해야 한다.

책에 따르면 스프링 AOP는 JEE 어플리케이션을 구현하는데 필요한 수준의 기느만을 제공한다고 한다.

2. 스프링 AOP는 자바기반이다. 

AspectJ는 에스팩트를 위한 별도의 문법을 제공하고 있는 반명 스프링은 별도의 문법을 익힐 필요 없이 자바언어를 이용하면된다.

스프링은 3가지 방식으로 AOP를 구현할 수 있게 하고 있다.

* XML 스키마 기반의 POJO 클래스를 이용한 AOP 구현
Spring 2 버전부터 aop를 설정하기 위한 aop 네임스페이스 및 네임스페이스와 관련된 xml이 추가되었다.
aop 네임스페이스와 관련된 xml 스키마는 다음과 같이 bean 태그에 명시할 수 있다.

예제)



전체 적용 예시




 <aop:config>AOP 설정정보임을 나타냄
 <aop:aspect>한개의 aspect를 설정한다.
aspect 태그의 ref속성에는 공통기능을 구현하고 있는 빈을 전달한다. 
 <aop:pointcut>pointcut을 설정한다
point태그의 id 속성은 pointcut을 구분하는데 사용되는 식별값을 입력받고
expression속성은 pointcut을 정의하는 aspectJ의 표현식을 입력받는다. 
 <aop:around>around advise를 설정한다.  


point cut에 포함하는 대상 객체의 메서드가 호출될 때 <aop:aspect> 태그의 ref속성으로 지정한 빈 객체에서 어떤 메서드를 실행할지 지정한다.
즉 위 예제를 보면 <asp:before 안에 ref 속성으로  servicePointCut으로 지정한 빈 객체의 beforeServicePointCut메소드를 실행할지 지정했다는 의미이다.

* AspectJ 5.6에서 정의한 @Aspect 어노테이션 기반의 AOP 구현
@Aspect 어노테이션은 AspectJ 5버전에 새롭게 추가된 어노테이션으로서 @Aspect 어노테이션을 사용하면 XML파일에 Advice 및 pointCut 등의 설정을 하지 않고도 자동으로 advice를 할 수 있게 되었다.

스프링 2버전부터 @aspect어노테이션을 지원하고 있다.


* 스프링 API를 이용한 AOP 구현 

어떠한 방식을 이용하더라도 내부적으로는 프록시 서버를 이용하여 AOP가 구현되므로 메서드 호출시에만 AOP를 적용할 수 있는 것에만 유의하면 될 것같다. 

원문 : http://najuung.tistory.com/65

2014년 10월 28일 화요일

TOAD 단축키

## TOAD 단축키 ##

1. 테이블 정보 상세보기

F4 : Table, View, Proc, Funct, Package DESC(테이블명 위에 커서를 두고 F4)

2. 자동완성

Ctrl+. : Table Completion (매칭되는 테이블목록 출력)
Ctrl+T : Columns Dropdown (해당테이블의 컬럼목록 표시)

3. SQL문 실행

F5 : SQL Editor내의 모든 SQL문 실행
Ctrl+Enter : 현재 커서의 SQL문 실행
F9 : SQL문 실행 후 Grid에 출력

4. 히스토리(과거 수행SQL문 조회)

F8 : 과거에 실행한SQL HISTORY 목록
Alt+Up : History UP
Alt+Down : History DOWN

5. 텍스트 대/소문자 변환

CTRL+L : 텍스트를 소문자로
CTRL+U : 텍스트를 대문자로

6. 주석처리

Ctrl+B : 주석처리
Ctrl+Shift+B : 주석해제

7. 편집 창 전환(이동)

F6 : SQL Editor와 결과창간의 이동
F2 : SQL Editor창 전체화면 전환
Shift+F2 : Grid Output창 전체화면 전환

8. 기타 단축키

F7 : 화면을 모두 CLEAR
Ctrl+Shift+F : 쿼리문을 보기좋게 정렬
Ctrl+F9 : SQL Validate (SQL문을 수행하지 않음)


2014년 5월 23일 금요일

이클립스 속도 향상 (eclipse.ini 수정)

이클립스 속도 향상 (eclipse.ini 수정)

eclipse.ini 수정

1) Before
-startup
plugins/org.eclipse.equinox.launcher_1.1.0.v20100507.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.1.R36x_v20100810
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m


2) After
-vmargs
-Dosgi.requiredJavaVersion=1.6
-Xverify:none
-XX:+UseParallelGC
-XX:-UseConcMarkSweepGC
-XX:PermSize=128M
-XX:MaxPermSize=128M
-XX:MaxNewSize=128M
-XX:NewSize=128M
-Xms512m
-Xmx512m



3) 설명
-Dosgi.requiredJavaVersion=1.6 => JDK 1.6 이상을 설치했을 경우에 1.6으로 설정하면 속도가 빨라진다.

-Xverify:none => 클래스의 유효성을 검사 생략. (eclipse 실행 시작 시간 단축)
-XX:+UseParallelGC => Parallel Collector를 사용. 병렬 가비지 컬렉션 사용. (병렬 처리로 속도 향상)
-XX:+AggressiveOpts => 컴파일러의 소수점 최적화 기능을 작동시켜 빨라진다.
-XX:-UseConcMarkSweepGC => 병행 mark-sweepGC 기능을 수행하여 이클립스 GUI의 응답을 빠르게한다.
-XX:+CMSIncrementalMode=true => 점진적인 GC

-XX:PermSize=128M    => eclipse 클래스 로딩 기본 메모리
                       Permanent Generation(영구 영역) 크기(Out Of Memory 에러시 크기 조절)
-XX:MaxPermSize=128M  => eclipse 클래스 로딩 최대 메모리
-XX:NewSize=128M         => New Generation(새 영역) 크기
-XX:MaxNewSize=128M   => New Generation(새 영역) 의 최대 크기

-Xms512m : eclipse 실행시 잡는 최소 Heap 메모리
-Xmx512m : eclipse 실행시 잡는 최대 Heap 메모리
                   최소와 최대를 같은 값으로 설정하면 오르락 내리락 하지않아 빨라진다.

[PC메모리에 따른 메모리 정의 예]
1 기가 이하 PC  => -Xms256m -Xmx256m
2 기가 ~ 3 기가 PC  => -Xms512m -Xmx512m
4기가 이상 PC   => -Xms1024m -Xmx1024m

[ 참고 ]
JVM 은 3가지 메모리 영역을 관리합니다.
 1. Permanent(영구) 영역 : JVM 클래스와 메소드를 위한 공간. = PermSize 설정
 2. New/Young 영역 : 새로 생성된 개체들을 위한 공간. = NewSize 설정
 3. Old 영역 : 만들어진지 오래된 객체들의 공간.(New 영역에서 이동해 온다)

2014년 3월 14일 금요일

[Cocos2d-x 3.0] Sprite

※ Sprite 
Sprite *spr = Sprite::create("Icon.png");
spr->setAnchorPoint(Point::ZERO);
spr->setPosition(Point(100, 100));
this->addChild(spr);

create() : 객체를 생성하는 메소드
setAnchorPoint() : 앵커포인트를 설정하는 메소드
setPosition() : 위치를 설정하는 메소드
addChild() : 객체를 화면에 출력하는 메소드


ㄱ. create()
Sprite를 생성하는 방법은 크게 3가지로 구분할 수 있는데, 위와 같이 파일명을 입력해서 만드는 방법과 SpriteFrame을 이용해서 만드는 방법, 마지막으로 텍스쳐를 가지고 만드는 방법이 있다.
단순하게 파일을 가지고 만드는 방법은 위와 같이 바로 파일명을 입력하는 방법이 있고, 아래 소스 코드처럼 파일명과 영역을 지정해서 이미지 파일에서 지정된 위치만 Sprite로 만드는 방법이 있다.

Sprite *spr = Sprite::create("Icon.png", Rect(0, 0, 100, 100));

또한, 일반적으로 코코스2d-x에서 사용되는 대부분의 객체는 create() 메소드를 통해서 생성을 하며, 이것을 통해서 생성된 메소드는 따로 메모리 관리를 하지 않아도 된다.


ㄴ. addChild()
addChild()은 단순하게 화면에 출력해주는 메소드가 아니라 위에 소스 코드에서는 spr이라는 Sprite 객체를 this인 화면 레이어에 종속시키는 역할도 하는 메소드이다. 이러한 관계를 부모-자식(Parent-Child)관계라고 하고 자식은 부모에게 종속된다. 예를 들어 부모가 화면에서 안보여지게 되면 자식도 함께 보여지지 않으며, 부모의 좌표가 이동하게 되면, 따로 자식의 좌표를 이동시키지 않아도 부모에 종속된 모든 자식들도 이동하게 된다.

addChild()를 할 때 위와 같이 단순하게 객체를 입력하는 것외에 z-Order와 Tag라는 것을 추가로 입력할 수 있다. z-Order는 z축의 값을 말하는 것이며, 이 값이 클수록 위쪽에 위치하게 된다. 즉, 같은 위치에 이미지 같은 것이 겹쳐질때 z축의 값이 큰 것이 위에 놓이게 된다. 따로 z축의 값을 설정하지 않을때에는 addChild()를 나중에 한 객체가 위에 놓여지게 된다.

this->addChild(spr, 1);
this->addChild(spr, 2);
[ x, y, z 축 ]

Tag는 부모에 종속되어 있는 자식들에게 번호를 매기는 것으로 이렇게 매긴 번호로 아래와 같이 자식의 객체를 다시 리턴 받을 수도 있다.

this->addChild(spr, 1, TAG_1);
Sprite *pSpr_1 = (Sprite *)this->getChildByTag(TAG_1);

ㄷ. 기타 메소드들
setScale() : 확대, 축소하는 메소드
- setScale(0.5) : 0.5배 축소
- setScale(2.0) : 2배 확대
- setScaleX(0.5) : 너비만 0.5배 축소
- setScaleY(2.0) : 높이만 2배 확대

setRotation() : 회전하는 메소드, (0~360)
- setRotation(90) : 시계방향으로 90도 회전하기
- setRotation(-45) : 반시계방향으로 45도 회전하기
- setRotationX(45) : X 좌표축을 기준으로 45도 회전하기
- setRotationY(45) : Y 좌표축을 기준으로 45도 회전하기

setOpacity() : 알파값을 설정하는 메소드, (0~255)
- setOpacity(128) : 반투명상태 만들기
- setOpacity(0) : 투명상태 만들기
- setOpacity(255) : 불투명상태 만들기

setVisible() : 화면에 출력여부를 정하는 메소드
- setVisible(true) : 화면에 보임
- setVisible(false) : 화면에 안보임

setFlipX(), setFlipY() : 반전하기
- setFlipX(true) : x축을 기준으로 반전하기
- setFlipY(true) : y축을 기준으로 반전하기


※ Point, Size, Rect 관련
Point() : x좌표, y좌표 값을 가지는 자료구조형
- Point(100, 100) : (100, 100)의 좌표값
- point pos = Point(50, 50);
- Point::ZERO => Point(0, 0)
- pos.x, pos.y

Size() : 너비(width)와 높이(height)를 가지는 자료구조형
- Size(100, 100) : 너비 100과 높이 100의 사이즈값
- Size size = Size(50, 50);
- size.width, size.height;

Rect() : 역영의 값(위치와 사이즈)을 가지는 자료구조형
- Rect(0, 0, 100 ,100) : (0, 0) 좌표의 사이즈 (100, 100)를 나타내는 값
- Rect rect = Rect(0, 0, 100, 100);
- rect.origin.x, rect.origin.y, rect.size.width, rect.size.height;




[cocos2d-x 3.0] 사운드(Sound) 관련

cocos2d-x에서는 CocosDenshion이라는 사운드라이브러리를 사용한다.

그래서 네임스페이스를 매번 입력하지 않으려면 상단에 using namespace CocosDenshion;이라고 선언해야 합니다.

사운드는 크게 배경음악효과음악으로 구분한다.

1. 재생 관련(Play)
void playBackgroundMusic(const char *pszFilePath, bool bLoop)
파일명과 반복여부를 입력하면 된다. 배경음악의 경우, 한번에 1개의 배경음악만 플레이된다. 즉, 동시의 2개 이상의 배경음악을 플레이 할 수는 없다.
SimpleAudioEngine::getInstance()->playBackgroundMusic("music.wav", false);

unsigned int playEffect(const char *pszFilePath, bool bLoop)
위와 동일하다. 다만, 효과음의 경우는 동시에 여러개의 플레이가 가능하다. 플레이하면 지정된 효과음의 고유번호가 리턴된다.
SimpleAudioEngine::getInstance()->playEffect("effect.wav", false);



2. 정지 관련(Stop)
stopBackgroundMusic()
stopBackgroundMusic(bool bReleaseData)
배경음악을 정지한다. 또한 종료할때 로딩된 배경음악을 완전히 해제할지를 지정할수 있다.
SimpleAudioEngine::getInstance()->stopBackgroundMusic();

stopEffect(unsigned int nSoundId)
효과음의 번호를 지정해서 해당 효과음만 정지한다.
SimpleAudioEngine::getInstance()->stopEffect(soundID);

stopAllEffects()
현재 플레이되고 있는 모든 효과음을 정지한다.
SimpleAudioEngine::getInstance()->stopAllEffects();



3. 일시 정지, 재시작(Pause, Resume)
pauseBackgroundMusic()
현재 플레이되고 있는 배경음악을 일시정지한다.
SimpleAudioEngine::getInstance()->pauseBackgroundMusic()

resumeBackgroundMusic()
일시정지한 배경음악을 정지된 위치부터 다시 플레이한다.
SimpleAudioEngine:: getInstance()->resumeBackgroundMusic()

pauseEffect(unsigned int nSoundId)
해당되는 효과음의 플레이를 일시정지한다.
SimpleAudioEngine:: getInstance()->pauseEffect(unsigned int nSoundId)

resumeEffect(unsigned int nSoundId)
일시정지된 해당음을 정지된 위치부터 다시 플레이한다.
SimpleAudioEngine:: getInstance()->resumeEffect(unsigned int nSoundId)

pauseAllEffects()
현재 플레이되고 있는 모든 효과음의 플레이를 일시정지한다.
SimpleAudioEngine:: getInstance()->pauseAllEffects()

resumeAllEffects()
일시정지한 모든 효과음을 정지된 위치부터 다시 플레이한다.
SimpleAudioEngine::sharedEngine()->resumeAllEffects()




4. 볼륨(Volume)
setBackgroundMusicVolume(float volume)
배경음악의 볼률을 지정한다. 범위는 0.0 ~ 1.0이다.
SimpleAudioEngine:: getInstance()->setBackgroundMusicVolume(float volume)

setEffectsVolume(float volume)
효과음의 볼륨을 지정한다.
SimpleAudioEngine:: getInstance()->setEffectsVolume(float volume)

getBackgroundMusicVolume()
배경음악의 볼륨 값을 가져온다.
float SimpleAudioEngine:: getInstance()->getBackgroundMusicVolume()

getEffectsVolume()
효과음의 볼륨의 값을 가져온다.
float SimpleAudioEngine:: getInstance()->getEffectsVolume()




5. 로딩(preLoad)
preloadBackgroundMusic(const char *pszFilePath)
배경음악을 미리 로딩해둔다.
SimpleAudioEngine:: getInstance()->preloadBackgroundMusic(const char *pszFilePath)

preloadEffect(const char *pszFilePath)
효과음을 미리 로딩해둔다.
SimpleAudioEngine:: getInstance()->preloadEffect(const char *pszFilePath)




6. 재생여부확인
isBackgroundMusicPlaying()
배경음악의 플레이 여부를 리턴한다.
bool SimpleAudioEngine:: getInstance()->isBackgroundMusicPlaying()