애초 발단은..xml책을 보다가.. 


3tier를 구분하기 위한 디자인으로.. dbhandler, htmlwrapper 클래스를 만들어 서블릿의
역할을 래핑해서 분리하는 작업중.. 서블릿,디비핸들러,htmp래퍼간 어떤 방식으로 통신
하느냐에 대해 Env 클래스(HashTable파생해서 만든클래스)를 사용하겠다는 목적으로..(유연성)

디비핸들러와 html랩퍼를 만들어 두면.. sql쿼리와 html페이지만 만들어두면 쉽게 3tier app를
만들수 있다는 설명과 함께 구현을 보여주는데..(xml or 기타 파일을 이용한 스크립트 처리)


단락중에.. 환경설정을 저장하고 로딩할때 Env vs Properties 부분에서..

1.property가 문자열/문자열 이기에.. 문자열/문자배열까지 지원을 못한다는 문제점..
2.db핸들러 환경설정은 여러줄을 실행하는 sql쿼리들인 경우가 많고.. 프로퍼티의 load메소
드는 이들을 다 수용할 유연성이 없다고 하며.. (이게 오래전책이라 그런가? 1.5에서 도입된 loadFromXML 있는데..)
3.최종적으로 임의의 레벨을 갖는 환경 변수를 설정해야 하기 때문(Env가 subEnv를 가지고 subEnv가 다시 subEnv를 갖고..
트리형식)

이 말중.. 각 Env는 내부적으로 데이터를 교류하는 여러 JavaBeans들중 하나를 나타낸다. 사실 빈즈들은
끼워넣은 Env들의 구조로 변환된 XML 도큐먼트라고 할수 있고 , XML과 마찬가지로 요소들을 임의의 레벨에
넣을수 있다. 이것은 Env클래스도 마찬가지이다.

딱 요 단락을 보고.. 스윙의 컴포넌트들은 모두가 beans규약 이다는 글귀 + 내가 작업할때 컴포넌트들에 다들..
hashset형태의 테이블이 존재했었다는것.. propertyChangeSuporter를 써본 경험등.. 

그런 기억땜에 스윙 컴포넌트들의 베이스 클래스인.. jcomponent를  분석할 필요성이 느껴졌고.. 조금 살펴보다 .. 
이런저런 위임 객체들및 .. addNotify()를 보게 되었는데.. 예전에 제대로 이해 못하고 넘어간 Object클래스의
notify메서드및 옵저버 패턴이 떠올라.. 조금 살펴보던중.. 정신이 안드로메다로 떠나버렸음.. 

(아참.. Object클래스에서 notify와 wait가 있는데.. 
서로 다른 스레드간 공유되는 락객체를 만들고.. 이 락객체를 얻고, 놓아주고 하는 방법을 통해 스레드간 통신(동기화)을
하게하는 개념이다.
Object lock객체 = new Object();  syncronized(lock){lock.wait()를 해버리면.. 현재의 스레드가 대기+락객체lock를
놓아주어 다른 스레드가 락객체를 취득할수 있게 한다.}

다른 스레드에 의해 특정 이벤트 발생시.. syncronized(lock){lock.notify()식으로 하면.. 저 위에 멈췄던 스레드 다시
가동(throw InterruputException을 통해서 = 예외 핸들링 방식.. 물론 중간에 새로운 스레드를 생성및 동작시키는 등의 
처리도 가능하고.. 내 맘대로지..} => 결국 스레드간 이벤트 방식으로 동작시킬수 있음.

예전 단순 멀티스레드 서버 구현시 어셉,리드 작업의 비동기 처리를 위해 어셉 스레드에서 어셉후, 리드 스레드를
생성해서 동작시키는 방식이었지만.. wait,notify를 이용한다면.. 서버 처음 시작부터.. 어셉스레드 동작, 리드 스레드
동작시키고.. 지들끼리 내부적으로 wait/notify로서 생산자/소비자 방식으로 순차적 처리가 가능함. 

물론 위의과정은 스레드가 각각 하나씩인 단순한 경우로서.. 더 복잡해질 경우.. 어셉 스레드풀 + 어셉용 스레드 3개
리드용 스레드풀 + 리드용 스레드 10개라면.. 어셉 스레드들과 리드 스레드들간의 생산/소비자 방식의 순차적 처리+
어셉스레드는 자기들끼리, 리드스레드는 자기들끼리 동기화를 시켜줘야함.(지들끼린 코드를 공유하니.. 메서드의
선언에 synchronized를 한다던가 하는 식 또는 공유 데이터를 동기화 객체(콘커런시인가 하는 패키지)으로.. 동기화 처리)

실제 구현은 안해봄;;  결국.. 작업 시작해라=notify, 작업 잠시 멈춰라=wait 라는 .. 이벤트 객체인 셈임..
이벤트 처리 방식은 .. 전에 잠깐 살펴본 생산자/소비자 패턴임. = 예전 nio할때.. 어셉용 스레드가 큐=fifo에 클라이언트 
메세지들을 넣어두고.. 큐객체가 발송 작업용 스레드1놈만 호출해서 작업시키는 방식이랄까? 물론.. 큐의 원소 하나당
스레드 하나씩이지.. 전체를 스레드 하나가 처리하는건 아님;;)
*****************************************************************8

여튼 xml등 파일을 통한.. 설정의 저장/로드를 통한 초기화는 다른 프레임워크.. 스프링/스트럿츠등에서도 사용하는 개념
이기에 뚤어둘 필요가 있음;; ..초 간단하게 개념잡자면.. xml파일에 readObject/writeObject 함으로서 확장성 높이고,
결합성 줄이고..문자열이라 사람이 이해하기 쉽고..
(현재 xml책을 보다->grep코드를 보다->스윙책중 document부분을 보다.. -> 인터넷에서 jcomponent를 찾고있는중;;;)


결론: 자바 api클래스들중 특히 gui클래스들.. 정말 더럽게 복잡하고.. 거대하고.. 사람 환장하게 함;;

jcompent가 임포트하는 클래스만 해도.. OTL


 import java.util.HashSet;
29  import java.util.Hashtable;
30  import java.util.Dictionary;
31  import java.util.Enumeration;
32  import java.util.Locale;
33  import java.util.Vector;
34  import java.util.EventListener;
35  import java.util.Set;
36  import java.util.Map;
37  import java.util.HashMap;
38  
39  import java.awt.*;
40  import java.awt.event.*;
41  import java.awt.image.VolatileImage;
42  import java.awt.Graphics2D;
43  import java.awt.peer.LightweightPeer;
44  import java.awt.dnd.DropTarget;
45  import java.awt.font.FontRenderContext;
46  import java.beans.PropertyChangeListener;
47  import java.beans.VetoableChangeListener;
48  import java.beans.VetoableChangeSupport;
49  import java.beans.Transient;
50  
51  import java.applet.Applet;
52  
53  import java.io.Serializable;
54  import java.io.ObjectOutputStream;
55  import java.io.ObjectInputStream;
56  import java.io.IOException;
57  import java.io.ObjectInputValidation;
58  import java.io.InvalidObjectException;
59  
60  import javax.swing.border.*;
61  import javax.swing.event.*;
62  import javax.swing.plaf.*;
63  import static javax.swing.ClientPropertyKey.*;
64  import javax.accessibility.*;
65  
66  import sun.swing.SwingUtilities2;
67  import sun.swing.UIClientPropertyKey;


by givingsheart 2014. 1. 2. 09:41
멀티스레드 환경에서 이뮤터블 패턴이 장점을 가짐. 즉 스레드간 특정 자원을 공유하는
문제에 대해 방지가 가능. 물론 concurrent패키지 계열의 클래스들을 사용해도 될테지만..
그래서 string이 이뮤터블이 된듯(물론 풀링도 가능하고).. 흐음.. 원본을 두고 사본을 건낸다..
어제 ejb패턴에서도 봤듯.. 서버측에서 데이터에 대해 클라가 요청시 사본을 생성해서 보내주
는 의미를 고민해볼것


lock관련

http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html



동기화 관련

생산자,소비자 패턴


생뚱맞지만.. 예전에 bean xmlencoder xmldecoder .. 스윙 컴포넌트(bean베이스)의 정보를 xml로..


글고 property change 서포터..


오픈소스 관련


************************************************************************************

생뚱2.. 스윙 유틸의 메서드중.. addnotify..  awt.frame -> awt.window -> awt.container -> awt.component까지.. 환장함..

Makes this Component displayable by connecting it to a native screen resource. This method is called internally by 

the toolkit and should not be called directly by programs.
This method changes layout-related information, and therefore, invalidates the component hierarchy.

Since:
JDK1.0

See also:
isDisplayable()
removeNotify()
invalidate()


6855 
6856     public void More ...addNotify() {
6857         synchronized (getTreeLock()) {
6858             ComponentPeer peer = this.peer;
6859             if (peer == null || peer instanceof LightweightPeer){
6860                 if (peer == null) {
6861                     // Update both the Component's peer variable and the local
6862                     // variable we use for thread safety.
6863                     this.peer = peer = getToolkit().createComponent(this);
6864                 }
6865 
6866                 // This is a lightweight component which means it won't be
6867                 // able to get window-related events by itself.  If any
6868                 // have been enabled, then the nearest native container must
6869                 // be enabled.
6870                 if (parent != null) {
6871                     long mask = 0;
6872                     if ((mouseListener != null) || ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0)) {
6873                         mask |= AWTEvent.MOUSE_EVENT_MASK;
6874                     }
6875                     if ((mouseMotionListener != null) ||
6876                         ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0)) {
6877                         mask |= AWTEvent.MOUSE_MOTION_EVENT_MASK;
6878                     }
6879                     if ((mouseWheelListener != null ) ||
6880                         ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0)) {
6881                         mask |= AWTEvent.MOUSE_WHEEL_EVENT_MASK;
6882                     }
6883                     if (focusListener != null || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0) {
6884                         mask |= AWTEvent.FOCUS_EVENT_MASK;
6885                     }
6886                     if (keyListener != null || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0) {
6887                         mask |= AWTEvent.KEY_EVENT_MASK;
6888                     }
6889                     if (mask != 0) {
6890                         parent.proxyEnableEvents(mask);
6891                     }
6892                 }
6893             } else {
6894                 // It's native. If the parent is lightweight it will need some
6895                 // help.
6896                 Container parent = getContainer();
6897                 if (parent != null && parent.isLightweight()) {
6898                     relocateComponent();
6899                     if (!parent.isRecursivelyVisibleUpToHeavyweightContainer())
6900                     {
6901                         peer.setVisible(false);
6902                     }
6903                 }
6904             }
6905             invalidate();
6906 
6907             int npopups = (popups != null? popups.size() : 0);
6908             for (int i = 0 ; i < npopups ; i++) {
6909                 PopupMenu popup = (PopupMenu)popups.elementAt(i);
6910                 popup.addNotify();
6911             }
6912 
6913             if (dropTarget != null) dropTarget.addNotify(peer);
6914 
6915             peerFont = getFont();
6916 
6917             if (getContainer() != null && !isAddNotifyComplete) {
6918                 getContainer().increaseComponentCount(this);
6919             }
6920 
6921 
6922             // Update stacking order
6923             updateZOrder();
6924 
6925             if (!isAddNotifyComplete) {
6926                 mixOnShowing();
6927             }
6928 
6929             isAddNotifyComplete = true;
6930 
6931             if (hierarchyListener != null ||
6932                 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 ||
6933                 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)) {
6934                 HierarchyEvent e =
6935                     new HierarchyEvent(this, HierarchyEvent.HIERARCHY_CHANGED,
6936                                        this, parent,
6937                                        HierarchyEvent.DISPLAYABILITY_CHANGED |
6938                                        ((isRecursivelyVisible())
6939                                         ? HierarchyEvent.SHOWING_CHANGED
6940                                         : 0));
6941                 dispatchEvent(e);
6942             }
6943         }
6944     }



by givingsheart 2014. 1. 2. 09:40
심심해서 예전에 전혀 감을 못잡았던.. 머지소트 조인을 찾아보다 찾은 블로그;; (db.. 묵혀둬서 미안하다;;)

http://blog.naver.com/thesot?Redirect=Log&logNo=70130988563



웹 해킹관련.. (이것은 나~중에..)



(추가)

DB를 포기해야 한다. 혼자서 모든걸 할수가 없다. 이러다간 죽도 밥도 안된다.

by givingsheart 2014. 1. 2. 09:39

swing, xml, ejb 패턴.. db책.. jsp책.. 스트럿츠책..  이걸 최소 1~2독씩은 해야.. 스프링으로 넘어갈텐데...

아하하핳하하하하하하하하하하하하하핳하하하핳

스트럿츠 관련 유쾌한 분의 블로그 ㅎㅎ


(추가)
스트러츠1을 책을 구매해서 공부를 했다. 스프링도 함께 공부했다. 서버단 MVC가 구분이 되었으며,
각종 전략(바인딩,DI,템플릿)을 알게 되었다.


'프로그래밍 > struts' 카테고리의 다른 글

스트럿츠 교재 저자 웹사이트  (0) 2014.01.08
by givingsheart 2014. 1. 2. 09:38


중 아래 댓글들 참고

********************************************************************

이부분은 책의 내용을 그대로 발췌


ejb2.0로컬 참조와 cmr(container managed ralation)이 나타나기 전에, 엔티티 빈들은
큰단위의 도메인 객체들을 모델화 하기 위해 주로 사용되었다.

이것은 주로 원격 통신과 관련된 오버헤드 때문에, 클라이언트 티어의 객체가 엔터프라이
즈 티어에 작은 단위로 접근하는 것을 막기 위해서였다. 큰단위(coarse grained)로 된 설계의 
성능은 클라이언트 티어와 엔터프라이즈 티어 사이에 전송되는 모든 데이터를 캡슐화한
data transer object의 구현으로 한층 더 개선되었다. 비록 이것이 높은 퍼포먼스의 설계를
제공해주기는 했지만, 많은 도메인 객체를 가진 복잡한 시스템에서는 시스템 내에
dto의 과잉을 초래하였다.

또한, 이전의 ejb에서는 빈 공급자가 도메인 객체들 사이의 연관을 유지하기 위한 로직을 명시
적으로 제공해야 했다. 도메인 객체들 사이에 복잡한 관계가 있는 상황 안에서는 dto의 설계가
매우 복잡하게 되었다.

로컬 참조와 cmr의 출현은 ejb를 이용한 엔터프라지으 app 개발에 흥미진진한 새로운 길을 열었다.
여기에서 우리는 프리젠테이션 티어와 엔터프라이즈 티어 사이에서 전송될 수 있는 XML 기반의
동적인 데이터 구조를 생성하기 위한.. JAXP와 빈 인트로스펙션(refelct활용한거)을 연계하여
ejb2.0을 사용하는 강력한 길을 얻을 수 있을 것이다.

엔터프라이즈 티어에서 클라이언트 티어로 데이터를 전송하기 위한 XML의 사용은 app내에 들어
있는 다양한 티어들 사이의 느슨한 결합 구조를 가진 구현을 도와준다. 

하지만, 새로운 도메인 객체들을 엔티티 모델에 추가하려고 할때는 , 이것들을 위한 새로운 DOM
구조(예전에 한번 살펴봄..dom,sax등)를 생성할 책임이 있는 클래스를 추가할 필요가 있다.

우리는 주어진 로컬 ejb의 cmp와 cmr 필드들을 동적으로 네비게이션 할 수 있는 프레임워크를 개발
하고 ,app 내의 다양한 티어들 사이에서 전송될 수 있는 xml문서를 생성할 것이다. 이러한 방법에는
다음과 같은 이점들이 있다.

1.엔터프라이즈와 클라이언트 티어 사이에 결합을 느슨하게 한다.(스크립팅 형식이니..)
2.도메인 객체들 사이의 관계들을 관리하기가 훨씬 더 쉽다.(굿!)
3.시스템에서 복잡한 데이터 전송 객체들을 제거한다. (굿!)
4.xml이 cmp 그리고 cmr 필드들을 동적으로 네비게이션 할 수 있게 만들어졌기 때문에, 빈공급자는
새로운 객체들을 도메인 모델에 추가하려고 할대, 이들의 새로운 dom 구조를 생성할 책임이 있는
클래스를 만들 필요가 없다.

ejb2.0로컬 참조는 빈 컴포넌트들의 작은 단위 접근을 권장한다. 로컬참조를 가진 빈들은 컨테이너에
의해 관리되는 다른 빈들과의 관계에 포함될 수 있다. 예를 들면, 헬프 데스크 시스템에서, UserEJB는
ServiceRequestEJB와 일대 다의 양방향 관계를 가질수 있고, ServiceRequestEJB는 ProductEJB와
일대일의 단방향 관계를 가지고, ServiceRequestHistoryEJB와 일대 다의 양방향 관계를 가질수 있다.

UserEJB는 또한 PhoneEJB와 일대 다의 양방향 관계를 가질수 있다. 그래서 EJB 2.0 로컬 참조와
cMR을 사용하여, 연관된 엔티티들의 복잡한 집합을 설계할수 있다. cmp와 cmr 필드들은 빈클래스
안에서 추상 접근자 메소드(getter/setter)를 사용하여 정의 된다.

cmr필드들을 위한 접근자 메소드들은 관계의 기수성에 의존하여 일의 관계이면.. 빈의 로컬 인터페이스를
, 다의 관계이면 빈의 로컬 인터페이스의 컬렉션을 돌려보낸다. 이들 접근자 메소소들은 빈 컴포넌트들의 로컬 
인터페이스를 통해서 외부에 드러날 수 있다. ejb2.0의 더 깊은 범위는 이 책의 영역에서 벗어난다. 보다 상세한 
ejb2.0규약에서 제공한다. -_-;;;

효과적인 디자인 패턴은 facade 컴포넌트를 통해서 app의 큰 단위 유스케이스를 드러내며, 클라이언트 
티어로부터 엔티티 컴포넌트로의 직접적인 접근을 막는다.

이것은 비지니스 서비스를 제공하기 위해 로컬 엔티티 빈들이 협력하는 복잡한 계층 구조와
상호작용하는 리모트 세션빈 컴포넌트와 같은 facade 유스케이스의 구현에 의해 성취될 수 있다.

앞에서 언급된 헬프데스크 예제로 돌아가서 , 주어진 user의 자세한 정보를 얻기위한 하나의 유스케이스가
있다. facade 컴포넌트는 요청된 user엔티티 컴포넌트를 찾고, cmp와 cmr 필드들을 통하여 검색을 하여
필요한 데이터를 얻고, 이를 프리젠테이션 티어로 리턴한다.

데이터 전송 객체를 위한 확실한 서택은 일반 자바 빈이다. UserBean은 cmp와 cmr필드를 나타내는
특성들을 가질 수 있다. cmr 필드의 타입은 관계의 기수성에 따라 java.util.Collection 이거나, 다른 빈 컴포
넌트일수 있다. UserBean은 ServiceRequestBean과 PhoneBean 컬렉션을 가질 수 있다. 

ServiceRequestBean은 한개의 ProdctBean과 ServiceRequestHistoryBean의 컬렉션을 가질수 있다.
추가적으로 이들 빈들은 도한 cmp필드들을 표현하는 원시 타입의 어트리뷰트나 간단한 string을 가질수
있다.

이러한 선택의 중요한 단점은 엔티티 모델이 복잡해질수록 데이터 전송객체의 계층구조가 더 복잡해지는
것으로, 이것은 서비스(엔터프라이즈) 티어와 소비자(프리젠테이션)티어 사이의 결합을 단단하게 할 수 
있다는 점이다. 

관계들의 복잡한 계층 구조를 보면, 더 나은 선택은 데이터 전송 객체로서 XML,DOM 객체를 사용하는 것이다.
(세션빈에서 직접 jdbc에 연동해서 데이터를 가져올때 java.sql.resultset -> java.sql.rowset 사용하기도 함)

facade컴포넌트는 org.w3c.dom.Document 타입의 객체를 생산하고 프리젠테이션 컴포넌트는 xml을 인지하는
jsp커스텀 태크나(오옷!!) xslt(이게 xml변환하는 라이브러리였던가? 예전에 정리했었는데;;) 파일을 사용하여
그것들을 소비할 것이다.

다음과 같은 질문이 있다. cmp 로컬빈의 참조로부터 xml문서를 어떻게 생성할 수 있는가? 

우리는 dom컴포넌트의 서로 다른 타입을 생성하기 위해 팩토리(factory) 기반의 접근을 사용할 수 있다.
하지만, 이것은 팩토리 컴포넌트의 과잉을 생성하여.. 엔티티 모델을 확장할 때 새로운 팩토리 컴포넌트의
추가가 필요할 것이다. (아..하긴..) 

우리가 필요한 것은 cmr을 찾아서 동적으로 dom구조를 생성하기 위해 cmr엔티티 로컬 객체들을 인트로스펙트
(리플렉션)할수 있는 기능을 가진 유틸리티이다.

이 유틸리티는 무한 순환을 피하기 위해 양방향 관계에서 원형 참조를 조심해야하고, 또한 관계 엘리먼트
(realation ship element)들의 검색에서 환경설정이 가능한 drill-down depth (????)를 가져야 한다.

다음 섹션에서 이러한 기능을 제공하는 유틸리티 클래스를 보여준다.

package ws.business.service.util;
//jaxp
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
//dom
import org.w3c.com.Document; //오오.. 기억이 새록새록 내경운 jdom2를 썼었지..
import org.w3c.dom.Element;
//ejb
import javax.ejb.EJBLocalObject; //이거..자바ee6 받아서 설치후.. 외부 라이브러리에서 찾아야함;;
//collection
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
//빈 introspection
import java.beans.Introspetor; //오.. 이런 api들이 제공되었었군.. 나는 직접 reflect 쓰는줄..
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor; 
import java.beans.IntrospectionException;
//reflection 에잉.. 추가해주네..
import java.lang.reflect.Method; //예전 생각한대로.. 조회해가며 게터,세터 찾으려는건가? 찾아서 invoke하고
import java.lang.reflect.InvocationTargetException;

public class DOMGenerator
{
  //문서 만든다.
  private Document doc;
  //사용자가 drill-down depth를 정의한다.. .. 이거 element의 계층 구조 의미하는 거였나? xml이 데이터를 트리처럼 관리하니
  private int drillDownDepth;
  //특정 참조를 저장하기 위한 사적 인스턴스 변수
  private ArrayList _circularRef = new ArrayList();
  //현재의 depth of the drilldown으로 저장하기 위한 사적 인스턴스 변수
  private int _currentDepth;
  //getEJBLocalHome, getLocalHandle, getClass and getPrimaryKey 메소드들은 
  //처리하지 말아야 한다. why???
  private static String RESERVED = "EJBLocalHome^localHandle^class^primaryKey";
  //대박이다.. 예약어를 xor로 묶었어.. 헐.. 대박.. 천재다..

  public DOMGenerator(String docElementName, int drillDownDepth)
  {
     try
     {
        DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = fact.newDocumentBuilder(); //익숙해서 좋고~
        doc = builder.newDocument(); //이제 나도 팩토리 패턴에 익숙해진건가?
     }
     catch(ParserConfigurationException ex)
     {
        throw new RuntimeChainedException(ex); //오.. 체크드를 언체크드로 변환후 그래도 콜러에게 알리네? 워커가 착함;;
     }
     //drilldown depth를 저장
     this.drillDownDepth = drillDownDepth;
     //사용ㅈ가 정의한 이름을 사용하여 문서 요소를 만든다.
     doc.appendChild(doc.createElement(docElementName)); //아.. 어렴풋이 기억이 난다.
   }


   //이 메소드는 dom을 만들기 위해 로컬 참조를 넘긴다.
   public Document getDOM(EJBLocalObject local)
   {
      try
      {
         //cmp와 넘겨진 로컬 참조를 위한 관계 필드를 사용하여 요소를 만들기 위해 이메소드를 호출한다.
         populateElement(doc.getDocumentElement(), local); //먼가 심오한데?.. local 인스턴스를 통해 reflection으로 
         //클래스 정보에서 각종 메서드,관계들 파헤쳐서 doc에 넣어주는듯..
         //dom을 리턴
         return doc;
       }
      catch(IntrospectionException ex)
      {
         throw new RuntimeException(ex.getMessage()); //오 이런게 일반적 기법이구나~
      }
      catch(IllegalAccessException ex) //흠..리플렉션 패키지로 접근제한자 다 뚤을수 있는데?
      {
         throw new RuntimeException(ex.getMessage()); 
      } 
      catch(InvocationTargetException ex)
      {
         throw new RuntimeException(ex.getMessage()); 
      } 
   }


   //
   private void populateElement(Element parent, EJBLocalObject local) throws IntrospectionException,
   IllegalAccessException, InvocationTargetException
   {
      //현재 로컬 참조를 링크된 참조 목록에 추가한다.
      _circullarRef.add(local); //참조를 기억해둠
      //현재의 drilldown depth를 증가시킨다.
      _currentDepth++;
      //현재 로컬 참조에 대한 빈 정보를 얻는다.
      BeanInfo info = Introspector.getBeanInfo(local.getClass()); //오`~ 이해되고 있음..리플렉션 사용해 각종정보추출
      //속성 descrptors의 목록을 얻고 배열에서 반복시킨다.
      PropertyDescriptor[] properties = info.getPropertyDescriptors(); //굿굿!
      
      for(int i=0; i< properties.length; i++)
     {
         //속성 읽기 메소드를 얻는다. 프로퍼티 디스크립터라는 자료형이 편하긴 한듯.. 
         Method propReadMethod = properties[i].getReadMethod(); //메소드 순회하면서 어트리뷰트.. properties[i] 이름
         //과 일치하는 게터 메서드를 클래스에 선언된 메서드들을 탐색해서 찾고..실행(invoke)해서 값을 얻는듯.
         //속성 이름을 얻는다.
         String propName = properties[i].getName();
         //reflection을 사용하여 속성 값을 얻는다.
         Object prop = propReadMethod.invoke(local, null); 
         //예전되어 있던 속성을 건너뛴다.
         if(RESERVED.indexOf(propName) > = 0) continue; // 천재다..

         try
         {
            //ejb 로컬 참조로 속성을 캐스트 한다. 구현 방법이 아주 다양하기에 instanceof를 사용하지 말자!
            EJBLocalObject locProp = (EJBLocalObject)prop;
           //만일 링크 참조목록에서 로컬 참조를 이미 이용하고 있거나,
           //현재의 drilldown depth가 설정된 driildown depth보다 더 크다면.. 건너뛴다. = 트리 순회 로직
           if(isCircularRef(locProp) || _currentDepth >= drillDownDepth) continue;
           
           //속성으로 요소를 만든다.
           Element child = doc.createElement(propName);
           //자식 로컬 참조의 관계 필드와 연속 필드로 새로 만들어진 요소를 반복해서 만든다.(핵심= 재귀)
           populateElement(child, locProp); //내가 파일 시스템 트리 탐색할때 재귀 시도한거처럼..
         }
         catch(ClassCastException ex1)
         {
             //ClassCastException이 throw되었으면.. 핸들링! 내가 전에 깨달은 익셉션 핸들링
             //속성을 로컬 참조의 컬렉션으로 캐스팅하도록 한다.
             //이때 구현방법이 컨테ㅣ너마다 다른 instanceof는 사용하지 않도록 한다.
             try
             {
                 Collection colProp = (Collection)prop;
                 //현재의 drilldown depth가 설정된 driildown depth보다 크다면 처리과정을 건너띈다. =트리순회에서 제한조건
                 if( _currentDepth >= drillDownDepth) continue;

                 //컬렉션을 캡슐화할 자식 요소를 만든다.
                Element child = doc.createElement(propName);
                Iterator it = colProp.iterator(); 
                //당근 현재 catch된 블럭은 컨테이너 타입(트리에서 마지막 노드x)이니까.. 내부 요소를 접근해야지..
                while(it.hasNext())
                {
                    //컬렉션에서 각각의 로컬 참조를 얻는다.
                    EJBLocalObject locProp = (EJBLocalObject)it.next();
                    //만일 링크 참조 목록에서 로컬 참조를 이미 이용하고 있거나, 현재의 drilldown depth가
                    //설정된 drilldown depth보다 크다면 처리 과정을 건너뛴다. = 위에도 나왓지만 중복처리 방지이자 무한루프
                    //방지
                    if( isCircullarRef(locProp)) continue;
                     
                    //컬렉션에 현재 로컬 참조를 위한 지속 정보와 관계 정보를 포함할 요소를 만들고, 
                    //그것을 컬렉션을 나타내는 요소에 추가하ㅕ 컬렉션을 만든다.
                    Element grandChild = doc.createElement(propName + "-child");
                    child.appendChild(grandChild); //예전에 사용자 정의 익셉션을 스택및 재귀호출을 이용해 처리한 어떤
                    //분의 코드에선.. 트리의 깊이 * '\t' 함으로서 층을 표현햇지만.. dom구조의 xml은 계층구조가 알아서
                    //잘 표시되니.. 그런 구현까진 신경안써도 될듯
                    populateElement(grandChild, locProp); //손주 노드 탐색 ㄱㄱ (진짜 내가 예전에 파일 시스템에서 트리
                    //순회하려던 것과 유사하다...내 삽질도 의미가 있었다 ㅠㅠ)
                 }
                 //위의 while을 통과했다면.. 현재 노드의 하위 계층을 전부 추가했을테니..(재귀를 통해)
                 //자식들을 만든다.
                 parent.appendChild(child);
              }
              catch(ClassCastException ex2)
              {
                 //ClassCastException이 발생했다면.. 속성은 연속필드이고.. 
                 //그값이 애트리뷰트로 연재 노드에 추가된다. 헐.. 진짜 내가 구상했던 트리식 파일 시스템 처리와 거의 똑같네..
                 //isDirectory따라 재귀 순회하고.. isFile이라면.. 현재 노드의 데이터 필드에 추가하고;; 내가 대박친건가.. 아님
                 //사람들 생각이 다 비슷한건가;;
                 parent.setAttribute(propName, prop.toString() );
              }
          }
      }

      //순환 참조를 추적하기 위해 목록에서 현재의 로컬 참조를 삭제한다. <- 이해불가..내가 전에 이걸 몰라서 실패했나?
      _circularRef.remove(local); //하여간 심플한..순회 종료조건들이다.
      //현재의 drilldown depth를 감소시킨다. 
      _currentDrpth--;
   }

   //이것은 참조가 링크된 참조 목록에 있는지 여부를 검사하기 위한 유틸리티 메소드이다.
   private boolean isCircularRef(EJBLocalObject local)
   {
      Iterator it = _circularRef.iterator(); //전체 로직을 완벽히 이해는 못했지만.. 대박..
      while(it.hasNext())
      {
         if(local.isIdentical( (EJBLocalObject)it.next() ) ) return true;
         
         return false;
       }
   }
}

아래의 코드는 이 클래스를 사용하기 위한 방법을 보여준다.
User local = userHome.findByPrimaryKey("1");
return new DOMGenerator("user", 4).getDOM(local); //아름답다...

엔티티 모델에 의존하여 생성된 dom이 아래에 나와있다.


<?xml version="1.0" encoding="UTF-8" ?>
  <user firstName="Meeraj" id="1" lastName="Kunnu">
   <requests>
      <requests-child description="Outlook not working" id="2" status="p">
          <product description="Install Laptop" id="1" name="SVC01"/>
       </requests-child>
       <requests-child description="PC not booting" id="1" status="O".
           <histories>
              <histories-child description="Information requested" id="2" loggedAt="2000-12-12 12:!2:12.0" />
              <histories-child description="Request logged" id="1" loggedAt="2000-12-12 00:00:00.0" />
            </histories>
            <product description="Install Laptop" id="1" name="SVC01" />
         </requests-child>
     </requests>
     <phones>
         <phones-child id="2" number="0771 8210586" type="M" />
         <phones-child id="1" number="0231 2973536" type="W" />   
     </phones>
   </user>
                


우리는 j2ee app의 엔터프라이즈와 프리젠테이션 티어 사이에서 복잡한 데이터를 전송하기
위한 멋지고 유연한 모델을 보았다. 프리젠테이션 티어는 엔터프라이즈 티어에 의해 생성된
xml데이터를 xml을 인지하는 jsp 커스컴 태그와 xslt를 사용하여 클라이언트 디바이스(이를테면
file)상에 표현할 수 있다.

도메인 모델에 새로운 정의를 추가할때, 당신이 해야할 필요가 있는 유일한 일은 .. 작은 단위 로컬
엔티티 빈들을 사용하기 위한 그런 정의들을 정의하는 것과 cmr을 사용하기 위한 연관을 정의하는 것이다.

dom생성기(generator)는 동적인 xml문서들을 생성하기 위하여 그런 관계들을 검색하는 일반적인
방법을 제공한다.

하지만, 임의의 다른 설계 솔루션처럼... 이러한 접근은 또한 약점과 결정들을 가지고 있다. 

첫번째 명백한 측면은 xml기반의 data transfer object에 대해 개발자들이 자주 걱정하는 퍼포먼스
이다. app서버 (wls 6.1)와 데이터 서버(adaprive sql anywhere)가 동시에 돌아가는 1ghz,256mb의
windows mf 컴퓨터 상에서 복잡한 관계들을 가진 천개의 레코드 집합을 처리하는데 0.5초 이하 정도의
시간이 걸렸다.

두번째 명백한 측면은 타입 안정성이다. xml이 가장 높은 레벨의 데이터 추상화를 제공하기 때문에 
어트리뷰트나 텍스트노드들의 값은 항상 string 문자처럼 다루어진다. 

만약 당신이 엔터프라이즈 티어로부터 조회된 dto상에서 비지니스 연산을 수행하고자 한다면,
자바빈  컴포넌트(일반 자바클래스)를 사용하는 dto패턴을 채택하는 것이 더 좋다.

하지만, xml스키마는 xml문서상의 타입 안정성을 위한 강력한 메커니즘을 제공한다. 또한 이문서에서
설명된 접근 방법에서, 엔티티와 그것의 종속적인 엔티티에 연관된 대부분의 비지니스 로직은
엔티티 그 자체 내에 구현될 것이고, 독립적인 엔티티들과 연관된 비지니스 로직은
session facade에서 구현될 것이다. 두 경우 모두 모데인 객체로서 로컬 엔티티의 객체를 사용한다.

이러한 접근방법의 가장 큰 단점중 하나는 xml기반의 데이터 모델링을 위해 잘 정의된 기술이 없다
는 것이다. xml을 사용하여 도메인 객체의 관계를 모델링하기 위한 어떤 uml표기법이나 대중적인
스테레오 타입을 찾아내지 못했다.


'프로그래밍 > ejb' 카테고리의 다른 글

해쉬맵의 활용 전략(map dto, dto factory)  (0) 2014.01.02
ejb관련 - EJB.. 그만 공부하자..  (0) 2014.01.02
by givingsheart 2014. 1. 2. 09:37
정확치 않은 이해를 스케치 하는것임을 주의!

목적:

서버,클라간 요청/응답 횟수를 줄이고, do들과 dto들 사이의 의존성 줄임

전제:
클라의 ui에 표시되는 데이터들은 서버측 데이터를 이용해 초기화된다.

서버측에 여러 do들의 모임..(게임이라면.. 캐릭터정보do, 맵정보do, 아이템정보do, 몬스터정보do등등)
을 관리하는 객체가 있다면 (facade 세션빈.. 메디에이터)

요놈에 대해 정보를 요청할때.. 전체 정보를 요청할 것인가? 아니면 개별 do정보를 요청할 것인가?
개별 do중 각각의 어트리뷰트를 요청할 것인가에 대해..


컨셉:
1.클라측에서 해당 유스케이스A에 해당하는 dto를 요청(캐릭정보중 a,b 맵정보중 a,b 몬스터정보중 a,b)

2.서버에선 유스케이스별로 dto를 해쉬맵에 구성해둔후 맵을 통채로 클라에 전달

물론 이작업 역시.. 팩토리 클래스가 담당
글고 여기서 제네릭 엑세스 패턴이 활용.. 컨셉은 전체 집합에서 찾아낼 집할을 의미하는 키값의 집합을 매개
변수로 get메서드를 호출하면.. 내부에서 전체 조회를 통해 일치하는 키에 해당하는 집합을 새로이 해쉬
맵으로 구성해 리턴하는 전략.. 컨테이너의 생성자등 메서드의 매개변수로 다른 컨테이너를 받는 의미가
이러한 의미임!

아참.. 타입을 제너릭하게 사용시..Object 타입들이 왔다 갔다 하니..  형변환이란 노가다 작업이 필요해지긴하
다.. 큰 목적을 이루기 위해 이정도 수고쯤음 -_-a

제네릭 엑세스 인터페이스 형태

public interface AttributeAccess
{
  public Map getAttributes(Collection attributeKeys);
  public Map getAllArrtibutes();
  public void setAttributes(Map attributes); //셋과 비교해 맵의 장점 = 덮어쓰기 가능!(예전에 맵의 put을 잘못 이해했었지..)
}

글고.. dto에 맵적용 패턴활용시 타입점검의 기능이 약해짐.. 단순하게 구성하면.. key도 object형이기 
때문에.. 해당 맵엔 모든 타입(do)들이 들어갈수 있음.. 이걸 방지하려고.. 상위 타입을 만들고 key값에
<? extends BaseA>가 가능하긴 하지만.. 이렇게 되면.. 너무 복잡해질듯.. 직접 구현할 레벨이 안되기 
땜에.. 막연한 느낌이랄까..?

컨테이너들이 직렬화를 구현한 이유는 원격 송수신 이란.. 기본 전제가 있기 때문임.. 스윙의 컴포넌트
들.. 역시.. bean 형태로서 직렬화및, 각종 셋/겟지원.. + key/value로서 내부에 해쉬셋을 가지고 있다는
점.. (프로퍼티란 데이터 타입은 해쉬셋의 일종으로 키와 값을 문자열로 다룬다는 점만 특이점임.. 문자열
타입의 집합은 xml과 연동이 쉽고..)
추가로 키값을 개발자가 알지 못할 경우를 위해 해당 컨테이너(빈클래스,스윙컴포넌트) 클래스에선
static final String XXXX = "xxaasasa"; 처럼 키값을 지원함..  예전에 워드 + 포맷 객체 프로젝트 진행시
포맷 객체를 외부에서 생성후 전략 패턴을 사용했지만.. 내가 생각했었던.. 즉..외부에서 type을 지정해
주고.. 내부에서 switch case..  사용시 word객체.(Format.NORMAL, "안녕하세요") 처럼.. 요렇게 사용할
수 있게끔.. 타입(key)를 지원해주는것임.. 

물론 타입 안정성을 더욱 엄격히 해주려면.. 예전에 구상했던.. 채팅 프로그램에서 메세지를 계층
구조화 한것처럼.. enum을 사용해서.. 정확한 구현은 기억안나지만.. enum KeyType{A,B,C}로..
구현하고 위에서 생각한 것처럼.. 매개변수를 받을때 extends 상위 타입 또는 매개변수의 타입을 KeyType
으로 .. 요게 될런지는 모르겠음..


3.클라에선 해당 맵에서 알아서 꺼내씀.. 캐릭정보라면.. dto객체에 get("character")해서 캐릭터 해쉬맵
을 얻고, 캐릭터 정보중 상태정보를 원하면.. 캐릭터 해쉬맵에 대해 get("status")를 해서 상태정보(이걸
do로 구분할지, 어트리뷰트로 구분할진..모르겠음) 해쉬맵을 얻고.. 캐릭터의 hp가 필요하다면.. -_-;; 
int hp = statusMap.get("hp"); 요런식으로 ??  하여튼.. 모든 어트리뷰트에대해 set/get 추가가 불필요하
단.. 장점이 있음.. 

(주의할게.. bean managed  vs container managed 에서 전문가들은 cmp를 권하는 것의 의미를 상기해
야함.. ejb 패턴.. 너무너무 복잡하고.. 개념이 명확히 서질 않고 혼동되고 잇음 ㅠㅠ DTO Factory패턴과
DTO hashmap 패턴이 짬뽕이 된듯.. 이책은 3번쯤 읽어봐야 감좀 잡을듯;; 내수준에 너무 벅참;;)

2번에서 유스케이스별(몬스터와 싸우다 = 캐릭터 정보, 몬스터정보, 아이템정보, 지형정보등) 필요한 데이터를
이뮤터블로서(원본/사본) 묶어준후에.. 클라에 전송하면.. 클라는 필요한 정보를 뽑아내서 사용하면 될테고..
중요한 판정,유효성 검증등은 서버측에 맡기고.. (이것도 애매함.. 서버와 클라간 통신 횟수를 줄이는게 주요
목적인데.. 데이터를 받는게 아닌, 판정및 유효성을 맡기는 것이라.. 게임을 예로 들기엔 이상하단 느낌..OTL)

1.클라측의 ui가 계좌 거래 화면이면.. 일단 서버측에서 계좌정보란 do를 얻어와야 할것이고(로그인등 인증 생략)
.. 이것을 do통채로 전달하냐, dto로 필요정보만 추출하냐, 또는 계좌외 다른 do의 정보도 추가로 필요하냐에 따라 
dto용 데이터를 구성한후..(물론 dao를 통해 얻어온 데이터로) 클라에게 전달하고 클라는 잔고,이체가능액수
기타등등을 뿌려줄것이고

2.클라측에선 해당 계좌 정보를 사용자에게 비쳐주며.. 사용자의 유스케이스(이체,조회,출금...)를 선택받으면..
서버에 이체란 사용자의 커맨드를 전달하고. 서버는 세션빈 + 비지니스를 의미하는 엔티티빈 등을 이용해..
아.. 생각이 막혔다.. 나중에 다시 정리..


by givingsheart 2014. 1. 2. 09:35
레이어                                      책임                                                   구현 기술

프리젠테이션                 사용자 인터페이스                                 jsp,html,javascript,swing/awt중
                                                                                             일반 component 계열
애플리케이션                유스케이스,워크플로,입력검증,                 servlet,<usebean>타겟,swing/awt중
                                  서비스와 상호 작용                                 frame,panel등 component 계열

서비스                         트랜잭션 제어하기,비지니스/워크플로        ejb 세션빈
                                  로직호출,facade로 역할
                             
도메인                         도메인모델,도메인/비지니스로직/입력         ejb엔티티빈, 일반 자바 객체
                                  검증


퍼시스턴스                   도메인 객체 상태의 영속적인 저장소            o/r매퍼(object,relation,mapping),oodbms,ejb
                                                                                               엔터티빈 bmp(bean manage persistance)
                                                                                               엔터티빈 cmp(container m p)

**********************************************************
서비스 레이어: 유스케이스와 비지니스 로직을 호출하는 방법을 제공한다.
즉.. 유스케이스가 실행하는 트랜잭션(계좌이체:pk조회,계좌정보조회,잔금
확인...)을 제어하고, 유스케이스가 충족되는데 필요한 도메인 객체들 사이의
워크플로와 도메인 객체로의 위임을 다룸.(도메인객체가 유스케이스를 다룰
수 있게끔)

음.. 예전에 파일 시스템에서.. 내부의 복잡한 작업용 객체, 각종 비지니스
를 감추고 클라이언트(사용자)에 대해 copy,delete,rename등을 인터페이
스를 제공한 느낌이랄까? 한마디로 클라이언트측에 대해 서브시스템들을
캡슐화 + 단순 인터페이스로 제공함으로서.. 뭐랄까.. 의존성을 줄인다?
내 경운 클라에게 노출되는 개념은 최대한 직관적,현실적으로 제공하자는
생각였었음..(채팅프로그램이라면.. 클라이언트라면.. client 객체 생성후
start()만 제공..즉 서브시스템들을 클라이언트로부터 감춘다는 의미~)

즉.. 사용자가 이 파일들을 이 디렉토리에서 저 디렉토리로 옮겨라는 
비지니스에 대해.. copy(srcPath, destPath)만 받고.. 내부에서 작업할
copy용 워커를 팩토리에서 생성하고, 파일 작업을 워크 팩토리에서
생성하고.. 워커에게 실제 작업을 시키고.. 이런 과정은 클라에게서 
숨겨졌었음. 역할별로 분리하고, 캡슐화하고.. 소통의 창구를 단일화한다.. 
이 개념들이 디자인 패턴에서 복잡성,의존성을 줄여주는데 사용되는 여러 
패턴들의 기본 컨셉이라 생각함. 

ejb의 경우.. 도메인 레이어에 업무(비지니스)를 의미하는 객체(빈)들이
존재함.(일반적으론 풀을 사용) 빈을 이용해 각 도메인의 처리 결과를
얻고, 그것을 조합해 전체 서비스를 구성하는 것이.. 서비스 레이어의 역할인
듯..  

글고 도메인영역.. ejb등은 app로부터 독립적임 = 재사용
(계좌이체 빈이라면.. 이 빈은 .. 여러 다양한 비지니스에서 사용이 가능)

순수 자바라면 이부분이 지난번 배웠던 dao들의 영역인듯.. 

물론 하이버네이트,아이바틱스의 경우 아직 거의 모르지만, 선생님 말씀으론
도메인과, 퍼시스턴스(db) 사이에 끼어서.. db종류별, 도메인 종류별.. 의존성
및 .. 반복되는 작업을 처리해주는 미들웨어인듯..

******************************************************

동시 트랜잭션의 문제.. 버전 번호

상황:여러사람이 동시에 접근해 수정이 가능한 게시판이 있을때
a라는 사람이 작업하는 도중 b라는 사람도 작업을 하게 되었고
a가 작업완료후 b가 작업을 완료했으면?

1.서버에서 읽기를 통해 엔터티 빈에서 데이터를 가져오면서 버전번호를
같이 가져온다.

2.갱신한 데이터(편집한 게시판 내용을 의미하는 엔터티빈)와 버전 번호를 
서버로 돌려보낸다.

3.서버에서 갱신을 수행할때 1에서 발송한 버전 번호와 같은지 판단해서
같을 경우만 갱신한다.

4.버전 번호가 다를경우 갱신을 거부한다.(물론 뒤에 작업 하던 사람의
데이터를 완전히 날려버리지 않고.. 새로운 버전번호를 보내주어 재갱신
시도를돕는다)

=>이문제는..jsp에서 트랜잭션 처리에 대해.. http가 상태를 갖지 않는다는
특성때문에.. 브라우저 에서 하나의 요청후 f5등 새로고침, 뒤로가기 등을 하면 
요청이 2번 되는 문제를 해결하기 위한.. token 발행/검증 기법과 같은
개념일 것이다. (한번에 하나의 처리만 하게끔..) jsp 교재에선 클라이언트
의 request 아이디,현재 시간(timestamp)를 md5를 통해 토큰을 만들었다.
(서블릿or 스클립틀릿으로 지속성 있는 세션에 토큰을 심어놓고.. 리퀘스트/
리스폰스를 통해 토큰을주고 받아가며.. 세션에 있는 토큰과 비교하는 방식이었는듯?)

ejb에선 과연 어떤 방법을 쓸라나? 흥미 진진..

아 글고.. dto factory,session facade(결합성 분리)를 사용하는 의미를 잊지말것..
(ejb 패턴책 너무 어렵 ㅠㅠ)

발췌:
public void setMessagDTO(MessageDTO messageDTO) throws NoSuchMessageException
{
  if(messageDTO.getVersion() !=  this.getVersion() )
    throw new NoSuchMessageException();
   
  this.setSubject( messageDTO.getSubject() );
  this.setBody(messageDTO.getBody() );
}

하지만, DTOFactory 패턴에서도 설명했듯이, 엔티티 빈에 직접 접속하는 방법으로 DTO를 사용
하게 되면 EJB 2.0처럼 기능이 저하된다. 대신 DTOFactory/Session Facade는 엔티티 빈에서
데이터를 얻어 엔티티 빈의 로컬 인터페이스를 통해 get/set 메소드를 직접 호출하는 방법으로
엔티티 빈을 갱신하는 작업을 한다. (reflection 중 getDeclateMethode()로 얻고.. 반복문에서
get/set 문자열로 게터,세터 찾아내고 , invoke 활용하겠지? 아님 말고 -_-;)

이런 패러다임을 사용하면, 세션 빈이 set 메소드를 통해 직접 엔티티 빈을 갱신하게 되어
엔티티빈이 더이상 갱신하기 전에 데이터의 버전을 자동으로 검사할수 없게됨으로.. 개발자가 
갱신절차 전에 갱신할 데이터의 버전을 넘겨야한다.

public void updateMessage(MessageDTO messageDTO) //서비스 영역중 세션빈 메서드임? 헷갈려 죽겟네..
{
  Message message = null;
  try
  {
     mesage = this.messageHome.findByPrimaryKey( new MessagePK(messageID) );
     message.checkAndUpdateVersion( messageDTO.getVersion() ); //불일치시 익셉션 발생 가능
     //메세지 갱신
     message.setBody( messageDTO.getBody() );
     message.setSubject( messageDTO.getSubject() );
   }
   catch(IncorrectVersionException e)
   {
      //트랜젝션 롤백.. 저 위의 b님.. 죄송합니다;;
      this.ctx.setRollbackOnly();
      throw new StaleupdateException(); //상위 콜러측에 알림
    } 
    catch(...)
  ...
}

public void checkAndUpdateVersion(long version) throws IncorrectVersion...
{
  long currentVersion = this.getVersion();
  
  if(version != currentVersion)
    throw new IncorrectVersion...();
  else
    this.setVersion(++currentVersion);  //초단순.. +1
}

=>위의 처리가 전문용어로.. 낙관적(optimistic) 동시성(concurrency) 획득이라함 -_-;;
(타임스탬프 쓰는 방식도 거론하는데.. 서버 시계 멈추거나, 시간 오차등.. 태클걸고 있음..)



*****************************************************

아이바틱스 - 하이버네이트 개념 이해..(한번 봣던 문서같은데..그새 생소해짐..)


******************************************************

bmp vs cmp(추가로 cmp에서 자동으로 값을 read/write하기 위해 reflection 개념을 사용.. 메서드중 setXXX만
추출등.. 글고 전문가들은 bmp 사용하지 말것을 권고.. cmp가 트랜잭션 처리도 알아서 해주고.. 요즘은 어떤지
모르겠음.. 하도 옛날 자료라..)


*******************************************************
이번에 ejb 실습하면서 추가한 외부 라이브러리.. (선에서 자바ee 다운및 설치후)

C:\glassfish4\glassfish\modules\javax.ejb-api.jar 를 외부 라이브러리로 추가함..
그외에도 엄청 많은 jre 파일이 있는데.. 구분을 못할 정도임..

*********************************************************8

java ee 용어;;(스윙에,xml에,ejb에.. 머리가 흡수를 거부하고 있음 OTL)

****************************************************8
중국산? 자바 코드 모음...


http://www.pudn.com/downloads3/ebook/detail10484.html


*******************************************************8

상태/무상태 세션빈(초 간단 결론?static으로 처리만 하면 무상태, 세션에 대해 로그인 정보등 의미있는 정보를 유지하고 
있으면 상태)


by givingsheart 2014. 1. 2. 09:33
JDesktopPane 메디에이터 패턴에 대해 좀 더 이해를 해보려다 찾게된 블로그
(웬지 메디에이터 클래스에 메서드가 무지하게 많더라니 ... 이런 심오한 이유가..)

http://www.buggymind.com/27


생각난 김에 예전 데브피아 디자인패턴 강의도 봐야겟음..

스윙에서 ContainPane인가 하는 메디에이터를 고민하다가.. 퍼사이드(facade)와 
구분이 제대로 안되고 있음.. 

(추가)
디자인 패턴이란, 특정한 문제 영역을 해결하기 위한 원리 이다. 장-단점과 , 이것이 활용될 상황을 기억하는게
중요하다. 


by givingsheart 2014. 1. 2. 09:31
어제도 이벤트 디스패치 스레드 구현 코드를 보던중.. 망할 시큐리티 매니저..   내 app의 입장을 넘어
jvm(여러 자바기반 app의 관리자 객체)의 입장에서 생각해 보았다.


내 app에서  클래스에 static을 사용한다는 의미, 클래스의 인스턴스(물론 refelct 관점에서 보면 클래스도 인스턴스(static

영역에 생성되는 object.. Class.forName("xxx.xx.a").newInstance)지만..논외) 를 static으로 접근하게 제공한다는것..

음.. 이해가 부족해 표현이 쉽지 않은데..

public class 계좌  //내 app의 모든 .class 파일에서 전역적으로 사용하기 위해 public 키워드
{
    public static 계좌 instance = new 계좌();
    public void 출금(){}
}

계좌클래스의 인스턴스는 어디에서건 계좌.instance로 "전역적=공유적"으로 접근및 계좌.instance.work() 서비스를 사용할수 
있다.(물론 패키지 선언및 다른 .class 파일에서 접근할땐 import를 하던지.. 아니면 패키지명.클래스명으로 사용하던지)

import 패키지.A;
public class 장호
{
   void 출금()
   {
       계좌.instance.출금();
    }
}


import 패키지.B;
public class 가짜장호
{
   void 출금()
   {
        계좌.instance.출금();
    }
}

물론 일반적으로 로그인 처리단계 -> 로그인 정보에 따라 서버단에서 db에 조회해서 dao를 통해 사용자의 
계좌 객체를 얻고 그것을 "서버단의 계좌 매니저" 객체에 보관하며, 로그인 결과에 따라 "검증하는 작업후" 인증된 사용자에 
대해 설정된 권만 만큼의 계좌 정보를 보여주고-> 사용자의 비지니스 로직(입금,출금,조회) 선택에 따라 다시 서버단에서 트랜
잭션및 예외등을 컨트롤해 가면서 dao를 통해 db단에 쿼리를 전달하고 -> 결과를 받아 사용자에게 피드백을 할것이다.
(뭐랄까.. 예전에 쇼핑몰 로그인 처리 구현했을때.. 19세 이상, 회원, 비회원 등으로 인증및 권한 설정을 통해 분기를 나누고 사용
자에 대한 view를 다르게 했던 것처럼..)

즉.. 장호의 계좌에 대해선 여러가지 비지니스 로직용 클래스의 객체가 공유할수 있지만.. 
장호의 계좌에 대해 "인가되지 않은 가짜장호가 접근"을 해서는 안될것이다.

아직 개념이 제대로 안섰는데.. 이걸 jvm과 여러 app 의 관계로 생각해보면
jvm은 서버의 입장, app는 클라이언트의 입장이 될것이다.
즉 jvm으로선 여러개의 app(app자체도 스레드를 여러개 사용가능)를 관리하게 되고.. 각각의 app는 서로에 대해 
"데이터에 대해 독립성 = heap 메모리, class 인스턴스라면 static 메모리 + 코드의 독립성 = stack 메모리"이 보장되어야 할 
것이다.

보안 개념(인증및 권한설정)을 좀 더 상위단에서 관리하기 위해.. 각 appcontext라는 걸 만들었고.. 각각을 컨테이너에
구성 요소로 관리함으로서 독립성을 보장할 것이다. (물론 이래야.. 여러 app들에 대해 시분할 처리가 될것이고..)
app라는건 jsp에 비유하면.. session의 개념이고 app내에서 발생하는 여러 이벤트(입,출력등 각종 처리)은 request의 개념일 
것이다.(정신이 점점 안드로메다로...OTL)

아직 시큐리티 매니저, appcontext, app의 eventQueue, 전체 시스템(os(jvm포함))의 eventQueue 에 대한 이해가
거의 없다. 또 한번 뜬구름을 잡는구나 ㅠㅠ


JNDI


JDBC와 JNDI

***** 
생각난 김에 예전에 보안문서중 자바 관련파트 확인 1회, java.security패키지와 관련 패키지 한번 더 체크


by givingsheart 2014. 1. 2. 09:30

1번의 경우는 헷갈릴만 했고.. 초기화 안하고 컴파일 해본적이 없어서.. 경험부족 +  사실 이클립스에서 자동 컴파일을

하니.. 스타트 버튼만 눌러버려서 이게 컴파일 실패인지, 컴파일 성공후 익셉션인지, 컴파일들 성공후 각 .class들을 링크하는 
과정상의 오류인지.. 구분을 못했다. 즉 내게는 컴파일 하다.->링크하다 (빌드)->실행파일-> 실행 파일로 파일형태니까.. 메모리
에 올리기 위해서 뭔가가 필요하고 -> 프로그램을 실행하다 에서 각 과정에 대한 개념이 부족한듯 싶다. 
(이클립스에선 컴파일할 class에 오류가 있어도 일단 스타트 버튼은 눌리니.. 그 결과가 컴파일 오류인지, 링크 오류인지,
런타임 오류인지를 구분을 못했었다)

그중 컴파일 과정에 대해선.. 오래전 간단한 계산기 프로그램 만들어 봤었는데..

구문을 분석해서 (1+2)*(3%2) 라면..  
1.우선 타입을 체크하고.. ()는 맞는지  , + % 등 연산자는 맞는지, 각 데이터는 타입과 값이 유효한지 검증할 것이고
2.()키워드,산술 연산자 키워드를 파싱(우선순위등 해석)해서 구문들을 분리(연산자 토큰,1,2,3등 데이터 토큰)하고 
3.스택에 연산자 토큰글과 참조할 데이터 토큰들으 넣어서 스택의 위부터 차례대로 꺼내어 계산 결과를
만들었던것 같은데.. 
(정확한 개념과 동작은 까묵..)

컴파일러 입장에서 클래스에 대해 1의 과정을 할때.. 데이터 타입에 대해 암시적으로 디폴트값을 넣어주는데..
메서드에 대해 1의 과정을 할땐.. 어째서 1의 과정을 생략할까? .. 단순하게 메서드의 타입 정의 (리턴형,메서드이름,
복귀 주소, 매개변수 타입, 매개변수 값들의 주소) 요것만 체크해주나? 어째서 메서드내 지역변수에 대해 디폴트 초기화
를 안해주는 것이냐!!! 해주려면 다해주던가!!!

=>좀 더 곰곰히 생각을 했다면.. 풀었을듯 하다. 내 경우엔 class 정의에서 필드에 초기값을 안 넣어도 컴파일러가 알아서
프리미티브 형이면 0,false,0.f 등 .. 레퍼턴스 형이면 null 로 알아서 초기화 해준다는 말을 너무 의식했다가.. 스택에서 
선언하는 지역 데이터에 대해선.. 컴파일러가 초기화 안해준다는걸 깜박했다. 
class A{}
class B
{
  int x; //여기에 예전엔 int a = 0; 이라고 클래스의 멤버 필드 정의와 함께 명시적으로 초기화를 해줬었는데.. 
          //이건 c스타일이라는 말에 ;;
  static int y;
  
  A a;
}

B b = new B();
sysout(b.x); //인스턴스 멤버 데이터
=> 0

sysout(b.y); //클래스 멤버 데이터
=> 0

sysout(b.a); //인스턴스 멤버 참조형 데이터
=> null

int c;
sysout(c); //메서드 지역 데이터
=> 왜 스택 변수는 알아서 초기화를 안해주고 빨간색으로 오류만 표시해주냣? 컴파일러는 각성하랏!
클래스 정의시엔 컴파일러가 알아서 디폴트값 세팅해는데.. 스택 변수도 알아서 0이던 null이던 넣어줄수
있을텐데.. 왜 안한거니??  괜한 혼란만 왔구만 -_-;

**************************************************************************************


2번 문제는 catch를 했으니.. finally 다음 일반 블럭도 당연히 수행되는걸 까묵 
catch()의 순서에 집중하다보니.. catch가 throw된 익셉션을 처리하는걸 까묵.. catch(Exception e)로 처리가 안되면..
exception이 아니라.. error이지.. 뭔가 함정이 있을거라 생각해서 풀었나.. 내가 제대로 몰랐으니.. 제대로 못푼거다;;

아까 dao볼때 .. 익셉션 처리catch 안하고 throws 로 넘겨버리는 잔상이 남았던듯.. 그때 구현에서도 이번 시험 예제
처럼 try{} 블럭과 finally{} 블럭 외에 다른 블럭도 있었나? 있을 필요가 있나? 시험 문제를 위한 코드 구현인가?

익셉션 발생 가능 코드를 try로 묶고.. DAO 클래스 처럼 자신이 익셉션 처리를 안하고 상위 콜러로 넘길것이면(=catch절 생략)
대신 finally로 현재 워커에서 열어 놓은 리소스등 종료 처리할 부분 처리. 이런 구성인데.. finally 블럭 아래의 일반 블럭이
필요한 경우가 있을지..? (글고 전에 찾아본 익셉션 문서를 상기하자. 책임 영역! , throws 로 콜러측에 강제할 상황의 구분!
=콜러측에서 예외에 대해 핸들링이 가능한 경우만 throws.. 기타 등등)

**************************************************************************************

8번 다형성 문제는.. 솔직히 내가 이걸 풀때 뭔 생각으로 풀었는지 기억이 안난다.

(1)Super super = new Sub1(); //이건 당연히 실제 인스턴스가 하위 타입이니까 상위 타입 참조에 캐스팅 없이 잘 들어가고..

(2)Super super = new Sub1(); //이것도 당연하지만.. 고려할게.. super 참조에 들어있는 실제 인스턴스는 Sub1타입..
Sub1 sub1 = (Sub1)super;  // 내경운.. 여기서 뭔생각을 했는지 모르겠다..  sub1 참조에 sub1이 당연 들어가는데..
                                       // 나는 sub1형 인스턴스를 캐스팅해서 sub1에 넣어야 한다는거에 이질감을 느꼈다. 참조가
                                       // super니까 형변환이 당연히 명시적으로 필요한데도 -_-;;; 솔직히 예제가 Animal형 , Dog형
                                       // Cat형이었다면.. 전혀 혼란이 없었을거라 생각한다. 
                                       //  그게 아니더라도 Object obj = new MyClass(); 
                                       //  MyClass my = (MyClass)obj; 정도만 되었어도 거부감이 없었을거라 생각한다;;
                                       //  (2)에 대한 진짜 별거 아닌 이질감이.. 보기 (4)를 볼때 엉뚱한 선입견을 심어놨다.

(3)Super super = new Sub1(); //이건 sub1 인스턴스를 sub2에 넣으려 하니.. 안되는거 당연히 인식했고..
Sub2 sub2 = (Sub2)super;

(4)Super super = new Super(); //이건 큰 타입을 작은 타입으로 캐스팅이 가능하다는 생각에.. (별 고민없이..) 요거 된다고
Sub2 sub2 = (Sub2)super;       //생각했는데.. 실제 인스턴스의 타입이 중요한거였다. -_-; 난 요걸 보며 뭘 생각한거지?
                                           // 참조형과 인스턴스형의 구분은 할줄 알았는데.. (2)번 보기에서의 괜한 거부감이 (4)번 보기를
                                           // 볼때 이건 맞는 답이라는 선입견을 심어준것 같다.

                                           // 이문제를 잘못 생각한 것은.. 인정을 해야할 부분이다. 내가 명확치 못했다.
                                           // 즉.. Super super 란 참조에.. new Sub1()을 해준다는 의미가 무엇인가?  heap에 Sub에
                                           // 특화된 메모리 공간을 할당함과 동시에.. 상속받은 상위 타입의 Super란 메모리 공간도
                                           // 할당이 됨으로서.. Super 타입의 참조로는 힙상의 Super 메모리 블럭을 사용이 가능하고
                                           // Sub타입의 참조로는 힙상의 Super 메모리 블럭 + Sub 메모리 블럭을 사용이 가능하단
                                           // 의미로서.. 한마디로 Super참조로 메모리를 가리켜도 super부분엔 접근이 가능하고, Sub
                                           // 타입의 참조로 메모리를 가리키면 super와 sub란 메모리 공간에 접근이 가능하기에 
                                           // 형변환시 오류가 날리 없음으로 컴파일러가 허용을 하는 것이다.

                                           // 반대로 뒤집어서 Sub sub 란 참조에.. new Super()를 해준다는 의미는.. new를 통해
                                           // 힙에는 super 형태의 메모리 블럭만 잡힐뿐 sub를 표현하는 메모리 블럭이 할당되지
                                           // 않는다. 즉 Sub 참조형으로 사용할수 있는 메모리가 존재하지 않는다는 의미이다.
                                           // 만약 Sub 참조로 Super의 인스턴스를 가리킬수 있게끔 컴파일러가 허용을 한다면..
                                           // Super의 인스턴스를 Sub의 참조로서 메모리 블럭을 접근 시켰다면.. sub.subMethod();
                                           // sub.subData = 0; .. 존재하지 않는 메모리 블럭에 접근하게 될것이다. 그 주소는 어떤
                                           // 위치일지.. 누구도 알수 없다. 그럼으로 아예 하위 타입의 참조로서 상위 타입의 인스턴스
                                           // 를 담을수 없게 지정한 것이다. (c/c++의 포인터와 혼동하지 말것! 자바는 나같은 허접 개발
                                           //  자를 믿지 않기에 내게 메모리를 맡기지 않는다. 내 경우엔 예전 c/c++ 할때 void*를 사용하
                                           // 듯이.. 4byte 포인터 형이라면.. 무조건 내 마음대로 static캐스팅이던  dinamic캐스팅이던
                                           // 을 했었다. 자바에선 타입 안정을 더욱 엄격하게 하는게 표준인듯 싶다.)
 
                                           //자식형 인스턴스엔 부모의 클래스 정보를 가리키는 추가 정보가 들어있을테니.. heap에선
                                           //메모리상 구조에 차이가 있을텐데.. 부모 인스턴스를 자식 참조로 받는 다는 것의 숨겨진
                                           //위험성을 인지못하고 형변환을 통해 담을수 있다고 판단했으니.. (예전 c의 영향같기도..)

                                           //내가 얼마나 무식햇는지 알수 있는 대목이다. 결국 몰랐던 지식은 아닌데.. 자바vs c/c++
                                           //이해및 경험이 부족했다. 일반적으로 상위 타입 참조에 구체 타입 인스턴스를 보관함으로서
                                           //컨테이너(동일 타입의 집합)에 관리하고 다형성(rtti)을 이용해 실제 타입의 데이터or 메서드
                                           //로 바인딩 되기에 상위 타입에서 work();라고 선언해두고 하위 타입에서 work(){}를 구현(
                                           //=재정의)시 내가 원한 하위 타입의 work()가 동작되게끔 구현하는 것이 일반적이라.. 물론
                                           // 인터페이스(메서드명)를 통일 안시켰으면.. instanceof 로 타입을 식별해서 각각의 메서드를
                                           // 호출할테고..

                                           // 결론은.. 내 경우엔 상위타입은 대부분 interface 또는 abstract + protected으로 처리를 해와
                                           // 서..(설계) 실제 상위 타입을 생성할 필요성도, 생성해서 형변환을 해본 경험도 없었다는 것
                                           // 이다.
                                            
                                           // 상위 타입의 참조에 상위타입을 생성한다는 것에.. 이질감을 못느끼다니.. 
                                           // 게다가 하위 타입의 참조에 상위타입의 인스턴스를 담게 할때의 위험성 때문에 자바에서 금지
                                           // 시킨것을 인식을 못했다니.. 아직 멀었다. OTL

                                           
**************************************************************************

글고 몇번 문제였더라.. 
콜러 측에서 int형 배열을 생성해주고 .. + 명시적 초기화 없이..
워커측에 배열의 참조를 전달해 워커측에서 [원소 접근 인덱스]++ 연산 해서 그 결과를 출력하는 것이었는데..

이경우도 1번과 마찬가지로.. new 키워드를 통한 메모리 블럭 할당과 자동 초기화에서 .. 이번엔 new 키워드라 인식을 했는데..
망할..
시험지엔 {0,0,0}으로 표시를 해두고.. 뭔 생각을 했는지 or 집중력이 떨어졌는지... 레퍼런스 형 배열의 new 와 착각
해서 {null,null,null}로 착각을 해버렸다. 워커측에서 null에 [] 인덱스 연산을 하려하니 당연히 뻑(널포인터익셉션)이 날거라 
생각했던거 같다.

뭐랄까.. 시험 보면서 논리적으로 꼼꼼히 따져가며 안풀고 대충 직관적 감각으로 푼듯한 결과랄까? (솔직히 swing 개념중
각 컴포넌트에 대한 이벤트 드라이븐 처리 방식 디자인 + 멀티스레딩 처리 개념을 이해하려다 머리에 필름이 끊겼었다 OTL..) 

글고 내가 일반적으로 코딩하면서 다뤄온 구현들이 아닌, 개념 이해를 테스트하기 위한 시험 문제 출제를 위한 구현이라.. 익숙
하지 못했다.

내 경우엔 배열을 생성하고 컴파일러 프리미티브 자동 초기화만 믿고 명시적을 초기화 안해주고 바로 넘겨주는 경우가 거의
없었던 걸로 기억한다. 

int[] arr = new int[3];  someMethod(arr); .. 사용해볼 엄두도 못냈다.

예전에 전산학원에서 배웠을때 데이터 초기화의 중요성에 대해 엄격히 가르침을 받았기에.. 나라면.. 워커에 넘기기 전에..
int[] arr = {0,0,0,0}; 또는 int[] arr = new int[4]; for(int i=0; i< arr.size; i++) arr[i] = 0;   또는 arr[0] = 0; arr[1] = 0; ...
이렇게 처리한 후에야 워커에게 넘겼을것이다. 

스트링형이라도 마찬가지.. String[] strs = {"",""}; 또는 String[] strs = new String[2]; for문에서 strs[i] = ""; ...

또한 배열보단 컨테이너를 배운후 부턴 컨테이너 생성 , 개별 인스턴스를 생성후 add던 append로 컨테이너에 넣어주고
ArrayList<Type> list = new ArrayList<Type>(capacity);
Type t1 = new Type(생성자 따라 초기화); // aggregation (composition 은 매개변수로 안받음)
 //t1.setXX(XX); //기타 필요한 세팅이 필요할 경우(association)
list.add(t1);                                           
someMethod(list);

또는 컨테이너 객체.add(new Integer(1));  컴파일러가  컨테이너 객체.add(1);을 암시적으로 변환해주는지는 기억이 안난다.

이런 프로세스가 몸에 배여있다고 할까?? 결국.. 프리미티브던 레퍼런스(프리미티브 배열)던 컴파일러의 암시적 초기화를 모르
는건 아닌데.. 내가 명시적으로 초기화해 주는게 습관이 된듯하다. (그래서 명시적으로 초기화 안해주는 코드를 보며 혼란이 
온거고)

컴파일러가 자동 초기화 해주는게 물론 편하긴 하다. 근데 초기화 해주는 경우, 안해주는 경우를 구분해야하니 기억할께
많아지지 않을까? 일관되게 인스턴스는 프리미티브건, 레퍼런스건, new로 힙 생성후  생성자가 호출됐던, 지역적으로 스택에 
생성했건, 전역적으로 static에 생성했건.. 일관되게 개발자가 명시적으로 초기화해주는게 명확하지 않을까..? 

이런 측면에서 암시적 생성자, 암시적 super 호출, 암시적 this 지원등.. 편하긴 한데.. 명확하진 않다. 글고 클래스 멤버 필드 
이름 지을때도 접두어m 를 안붙이는 것도.. 마음에 안들고.. m 이 this를 대신해 인스턴스 필드임을 의미하고.. s or g 가 클래
스 필드임을 의미하기에 괜찮은것 같은데.. 뭐 this.name = name;으로 구분이 되고, AClass.NAME = name; 처럼 클래스 필드
등은 대문자로 처리하니 구분이 되니까 .. 별문제는 없는데..

많은 선배 개발자,학자 분들이 논의를 통해 표준화 시켰을테니.. 내가 java 코딩 표준에 적응해야 하는것이 옳다고 생각한다.
(자바와 c++이 다른것이.. 많은 부분이 있지만.. c/c++ 에서는 암시적 초기화가 없었던것 같다. 그외에도 수많은 차이가 있다.
전처리기도 없고.. ex)#define MAX = 10   #pragma xxx  #if(debug) #ifndef 문법이 맞는진 모르지만.. 전에 assert등 .. 디버그
용 코드를 심으려 할때.. 개발 버전, 배포 버전 구분을 어떻게 해야할지..몰라서.. 물론  jvm 매개변수로 -ea 하는 방법이 있었
고, junint을 통해 테스트용 코드를 따로 생성하는 것도 알게 되었고.. 아.. maven이나 junit, jgit?, ant도 적응을 해야하는데..)

나는 자바의 객체지향 구현과 디자인에 반해 있으면서도 일부분은 아직 c/c++프로그래머 스타일인가 보다.. 억지로 컴파일러의
암시적 자동 초기화를 받아들이려고 하니까.. 혼란이 생긴듯 하다.(물론 int등을 Integer로 자동으로 바꿔주는 것도 포함.. 메모
리 할당및 초기화, 명시적인 해제, 메모리 접근, 그리고 참조..개발자의 편의를 위해서라지만.. oop의 캡슐화와 추상화의 취지
와도 맞다고 생각하지만.. 개발자들이 위의 과정을 모르고 지나치기 쉽게끔 너무 편의를 제공했다. 예전에 new로 생성하고..
free로 해제를 안해줬을때의 그 엄청난 찜찜함이란... 게다가 가비지 컬렉터가 서비스중 메모리 부족으로 풀 가비지 컬렉팅을
했을때의 위험성도 몇몇 글에서 봤으니.. )

데이터라면 
1.컴파일러에 타입 선언 (컴파일러 기본형 아닐때.. 말 그대로 c/c++ 에서 typedef.. 타입의 선언과 구현(정의)가 분리 가능)
2.메모리 할당하고 특정 이름으로 사용하겠다는 선언 + 메모리 블럭 값에 초기값을 넣겠다는 선언  int a = 10;
3.메모리 이름= 변수명(heap or stack or 공유 데이터라면 static 상 주소)을 통해 실제 값을 넣거나 읽는 등의 사용

메서드의 경운 
1.컴파일러에게 타입 선언(메서드이름,리턴형,접근제한,매개변수타입...필수는 아니지만 변수 이름주기) 
2.구현을 통해 메서드란 타입 정의(메서드의 스택 내부에서 사용하는 지역데이터의 경우는 저 위의 과정)
3.메모리 이름=메서드명(static상 공유 주소)을 통해 실제 사용 (순차적으로 처리될 컴파일된 목적코드는 어느 영역이었드라..
실행코드영역?)

클래스의 경운 (데이터와 메서드를 캡슐화 해놓았기에.. 위의 2개 과정들 중복 + 생성자및 각종 타입간의 상속 관계등 ) 
1.컴파일러에게 전체적인 구성 타입(데이터,메서드,상위타입) 선언  
2.구현 (명시적 생성자,기타 메서드 구현) + 클래스데이터에 대한 초기화 , 생성자의 구현에서 인스턴스 데이터에 대한 초기화   .. (1,2)를 합쳐서 클래스 정의
3.클래스의 역할에 따라서.. static 메서드로 사용  vs new를 통해 클래스의 개별 인스턴스를 생성해서 서비스 메서드로서 사용


************************************************************

10번 문제는.. 대박!
예전에 지훈형님과 string이 immutable 하다는 얘기를 했었는데..  내 생각이 너무 짧았다. concat 메서드에 집중을 했지..
이뮤터블을 깜박.. 단.순.무.식 
String str2 = str.concat("bbbbb"); 

이뮤터블의 개념은 알았지만, 틀려버렸다. = 내가 제대로 몰랐다는 의미! 
솔직히 지금까지 몇몇 프로젝트에서 문자열 처리 작업을 할때.. 그것이 분석및 분류 작업이라면.. 스트링 토크나이저를 통해서 
했고 붙이기 작업이라면.. + 연산자를 사용햇지.. str.concat을 거의 써본적이 없다. sysout에서 (a + "b") 또는 sysout(str.con
cat("aa"))  myMethod(str.subString("xx"))  (즉 스트링의 서비스 메서드가 리턴하는 새로운 스트링을 바로 전달) 요런식으로 
하는게 너무 습관화돼서.. 스트링 객체의 서비스 메서드인 concat, substring, index 어쩌구 기타 등등 메서드 들을 실제 저렇게
분리해서 사용해본 경험이 너무 적었다. 예전 로또 프로젝트에서 로또 번호 문자열 처리할때 subString 썼을때는 리턴값 받아서
사용했었고..


왜 자바에서 String 을 이뮤터블 패턴으로 결정했는지는.. 아직도 잘 모르겠다. (리소스 풀에 등록시켜둘라고 그러는건가?
.intern().. 왜 string에 대해 원본성? 요런게 확보되어야 하는지 모르겠다. 물론 고급 개발자들이 string을 이뮤터블로 결정한 
깊은 이유가 있을거라 생각한다. 아참.. 스티링간 + 연산자가 컴파일러 최적화를 통해 stringbuffer append()처리 되고 
반복문 내에서의 += 연산이.. 실제 메모리를 재 할당하고 복사하는 과정 때문에 오버헤드 발생하는 것을 상기할것! + 어떤
분의 논지였는데..  스트링 빌더,버퍼,synchronized 등등을 쓸때.. 과연 여기서 써야하나? 한번쯤 고민해보고 사용할것이란
메세지를 기억할것)

결론: 이뮤터블 객체... 실전에선 실수 안하려나? 간단한 개념이지만.. 이처럼 실수하기 쉬운 개념이기도 하다!

하여튼 선생님이 선별해주신 문제덕에 내가 제대로 모르던 것을 약간이나마 확인할 수 있어서 대만족!

************************************************************

ps. 틀린 문제에 대해 나름 리마인딩을 한다고 글을 작성하고.. 가급적 객관적인 시각으로 글을 읽어보니..
나라는 존재의 성향이 비쳐졌다. 틀린 문제에 대해 피곤했느니.. 아는거였느니.. 하는 뉘앙스가 군데군데 퍼져
있다. 알량한 자존심의 발로인가? 혹은 자기 보호 본능일까? 스스로 변명을 하고 자신을 지키기 위해서.. 

머리속의 개념들을 꺼내는 과정 자체는 나쁘지 않았다. 왜냐? 복습&정리를 통해 공부가 되었으니까.. 단지 동기가 
불순하여 표현이 시건방졌다.

모르는건 모른거고(정확히 알지 못하는것 = 모르는것), 실수했던건 실수한거다. 인정을 해야한다. 인정을 하고 겸손
해져야 배움이 있고 다음 단계로의 발전이 있다. 

자존심이 강할수록 실패했을때 좌절감이 커지게된다. 내가 폐인 생활을 하게된 계기도 너무 강한 자존심과 실패후
그 결과를 납득할 수 없었기 때문이었다. 게다가 내 경운 타인의 시선을 강하게 의식하는 성향이 있어서 스스로 무너
다.(사회인으로서 커리어를 쌓아갈 나이에.. 새롭게 법학 분야에서 어린 친구들과 경쟁등.. 초반엔 지적 호기심과 
조금씩 얻게 되는 성취감에 잊고 있었지만.. 실패를 경험하다 보니 내적 갈등이 발생했고 도피처가 필요했다. 결국 
그것이 누적되어 방구석 폐인이 되었던 것이다.)

내가 폐인 생활및 그간 살아오면서 알게된 깨달음중 하나는.. 모든 개구리는 자신만의 우물을 갖고 있다는것. 우물안
의 개구리인 주제에 자신의 우물을 "다른 개구리로부터" 인정받고 지키기 위한 본능이 존재한다는 것.  

결국 자신과의 싸움이지, 상대에 대한 싸움이 아니라는 것.
(내 안에선 아직도 알량한 자존심이 꿈틀대고 있는듯 하다. 본질이 아닌, 하등 중요치 않은 것들.. 어제에 비해 오늘의 
자신이 한치라도 발전해야 뿌듯한거지)

공개된 게시판에 글을 남김으로서 나 자신조차 객관적으로 평가해 버리다보면.. 망할 자존심 문제도 점점 좋아지고 
내 주관도 객관에 가까워 질수 있겠지.. 파이팅!


1.나는 왜 지금 swing을 공부하고 있나? 
 => db쿼리 툴을 학습수준이 아닌, 서비스 수준으로 만들고 싶어서..  
   1.1 db쿼리 자체도 굉장히 어려운 분야인데.. 겉핥기식 아닐까? 
    => 쿼리문 최적화, 테이블 설계등에 대해서.. 중요 포인트이고 학습이 필요하다고 생각함. 물론 스윙으로 툴app의 외관
        과 기능을 구현해 놓으면 추후.. 고차원적인 쿼리문 최적화, join 최적화 등의 작업을 고민하고 추가하는건 간단할듯함.
2.그렇다면 왜 db쿼리 툴을 만들고 있나? 취업용 포트폴리오인가? vs 별다른 의미는 부여하지 않았나?  
 => 별다른 의미는 없음. db 쿼리문 공부를 실제 툴 프로젝트를 진행함으로서 깊이 이해할수 있으리라 판단했음.
  2.1취업용 포트폴리오라면 어떤 회사를 목표로 하기에 db쿼리 툴을 선택했나? 
 => oop 구현 기법을 적극적으로 구사하고 공부할 예정임. 이 과정을 통해 디자인 패턴을 조금 더 이해가 가능하리라 판단함
     시장의 수요에 .. xx 디자인에 대한 이해가 요구사항 이었음
3.많은 시간을 투자해 공부할 만큼 가치가 있는 부분일까? 
 => 윈도우즈 프로그래밍을 공부할때 개념들 (컴포넌트간 관게,구조,이벤트 핸들링, 멀티스레드)을 잡아놓고 어떠한 기능들이
      있는지 훑어놔야 추후에 실제 app 구현시 이런 기능의 활용을 어떻게 접근해야 하겠다는 판단력이 생기고 , 그후 요 책을
      참고 용도로 활용할 예정. 전체를 정독할 예정 아님.
  3.1스윙에 투자를 한다 함은.. gui 프로그래머가 되고 싶은 것인가? 
   =>일단 독립 app개발이 가능한 수준으로 올라가고 싶음. gui부분 공부가 그래서 필요함. 물론 모바일쪽으로 간다면
      안드로이드, 세분화 해서 게임쪽으로 간다면 unity를 공부할 필요성이 있다고 생각함.


by givingsheart 2014. 1. 2. 09:29