350 likes | 705 Views
Cairngorm( 캔곰 ) : Flex UI 프레임워크. 옥상훈 차장 한국어도비시스템즈. Contents. 프레임워크의 역할 캔곰 프레임워크의 구조 캔곰프레임워크의 처리 과정의 이해 캔곰프레임워크의 작동 캔곰프레임워크 구성요소의 이해 캔곰프레임워크 작업 절차. 프레임워크의 역할 : 애플리케이션 아키텍쳐의 확장. 프레임워크가 없는 경우. 프레임워크가 있는 경우. - 벽돌이 추가되어도 같은 패턴으로 쌓인다 . - 벽돌을 추가하는 패턴을 익혀야 한다.
E N D
Cairngorm(캔곰): Flex UI 프레임워크 옥상훈 차장 한국어도비시스템즈
Contents • 프레임워크의 역할 • 캔곰 프레임워크의 구조 • 캔곰프레임워크의 처리 과정의 이해 • 캔곰프레임워크의 작동 • 캔곰프레임워크 구성요소의 이해 • 캔곰프레임워크 작업 절차
프레임워크의 역할 : 애플리케이션 아키텍쳐의 확장 프레임워크가 없는 경우 프레임워크가 있는 경우 - 벽돌이 추가되어도 같은 패턴으로 쌓인다. - 벽돌을 추가하는 패턴을 익혀야 한다. • 벽돌을 추가하는 패턴을 익히지 않아도 된다. • - 벽돌이 추가될수록 패턴들이 제각기 나타남.
프레임워크의 역할 : 애플리케이션의 역할 세분화 (분담) • 캔곰 프레임워크는 화면을 처리하는 과정을 6가지로 분류 • view 패키지 : 화면 로직 처리 • vo 패키지 : 화면에서 가져갈 데이터 구조 정의 • control 패키지 : 사용자의 조작에 따른 이벤트와 이를 연결시켜주는 컨트롤 정의 • business 패키지 : 비즈니스 메서드를 호출하는 Delegate정의 • commands 패키지 : 이벤트가 발생하면 실행 하게 될 커맨드 정의 • model 패키지 : 데이터를 담아 처리할 클래스 정의
캔곰 프레임워크의 구조 Command 1 Command 2 Front Controller Business Delegate Service Locator . . . . . Command N Model Locator Value Object View
캔곰프레임워크의 처리 과정의 이해 • 캔곰은 이벤트-처리위임-데이터 모델의 처리구조 • 캔곰은 이벤트가 발생했을 때 데이터를 위임해서 가져오도록 함 • 로또 당첨시 변호사에게 당첨금을 찾아오도록 위임하는 것과 유사 • 처리 과정 • 1) view에서 캔곰 이벤트발생 : 로또 당첨 이벤트 • 2) FrontController에는 이벤트에 해당하는 커맨드가 매핑되어 있음 : 변호사에게 당첨금을 찾아오도록 얘기해둠 • 3) 지정된 command 실행 : 당첨금 수령을 위임함 • 4) delegate의 메서드 실행 : 변호사가 위임장을 받아 당첨금을 찾아옴 • 5) ServiceLocator에서 business 메서드 실행 : 은행의 위치는 ServiceLocator • 6) 결과데이터는 model에 저장 : 당첨금을 금고에 저장 • 7) view에서는 model의 데이터에 바인딩
HTTPService ServiceLocator WebService RemoteObejct 캔곰프레임워크 작동 Result핸들러에 결과 이벤트로 전달 8 RPC호출 결과 값 저장 9 Command BusinessDelegate ModelLocator RPC서비스 호출 위임 3 변경된 데이터 알림 유저이벤트와 함께 데이터 전달 RPC서비스 호출 RPC호출 결과 4 10 2 7 유저로부터 이벤트발생 1 FrontController View RPC서비스 호출 결과 오브젝트 생성 6 5 RPC호출 결과를 오브젝트에 수용 ValueObject
캔곰프레임워크 작동 • 초기화 1단계 • ModelLocator 인스턴스를 새로 생성 : View -> ModelLocator • 초기화 2단계 • ModelLocator에서 사용하는 vo클래스 생성자 호출 : ModelLocator -> VO • 초기화 3단계 • FrontController 생성자 호출 : Cairngorm -> FrontController • 초기화 4단계 • 캔곰 Command와 이벤트명 등록 : FrontController -> Cairngorm
캔곰프레임워크 작동 • 실행 6단계 • 캔곰 Delegator로 responder 전달 : Command -> Delegate • 실행 7단계 • 캔곰 responder 인스턴스 전달 : Command -> Delegate • 실행 8단계 • 캔곰 이벤트 객체로 사용자 입력값이 들어있는 event 전달 : Command -> Event • 실행 9단계 • 캔곰 Delegator의 비즈니스 메서드 수행 : Delegate -> Delegate • 실행 9-1단계 • ModelLocator getInstance()호출 : View -> ModelLocator • 실행 10단계 • 캔곰 ModelLocator에 결과값 세팅 : Command -> ModelLocator • 실행 1단계 • 캔곰 이벤트 생성자 호출 : View -> Event • 실행 2단계 • 캔곰 이벤트이름 부모 생성자로 전달 : Event -> CairngormEvent • 실행 3단계 • 캔곰 이벤트 브로드캐스트 : View -> CairngormEvent • 실행 4단계 • ModelLocator 인스턴스를 싱글톤으로 가져오기 • 실행 5단계 • 캔곰 Command execute 호출 : Cairngorm -> Command
View : 사용자들이 보는 화면 • 역할 • 화면을 구성하는 요소 • 이벤트를 통해 사용자의 요청을 FrontController로 전달 • 사용법 • 사용자의 화면 로직에 따라 각각의 View를 생성 • 각 View마다 저마다의 이벤트를 정의 • 작동 • 사용자가 화면을 조작하면 이벤트가 발생 • 이벤트 발생시 데이터는 ValueObject나 기타 클래스를 통해서 이벤트와 함께 전파됨
FrontController : 이벤트에 반응하여 커맨드를 실행 • 역할 • 비즈니스 로직을 수행할 Command 정보 포함 • 발생한 이벤트에 대해 실행할 커맨드(Command)에 대한 매핑을 가지고 있음 • 사용법 • FrontController를 확장하여 addCommand함수를 구현 • addCommand함수에는 이벤트명과 Command 정보를 담아둠 • 작동 • 사용자 이벤트가 발생하면 EventBroadcaster를 통해서 그 이벤트에 매핑된 Command가 실행되도록 함
Command : 비즈니스 로직을 담은 컴포넌트 • 역할 • 커맨드는 비즈니스 로직을 담고 있으며 비즈니스 로직을 위임해서 실행하도록 함 • Command에서 델리게이트(Delegate)를 호출해서 비즈니스 메서드를 수행함 • 사용법 • Command, Responder인터페이스를 구현한 클래스로서 execute, onResult, onFault함수를 구현해서 만든다. • 작동 • execute함수는 EventBroadcaster를 통해서 같이 넘어온 유저의 데이터를 받아 Business Delegate에게 비즈니스로직에 해당하는 함수를 위임하여 실행하도록 한다. • onResult 및 onFault는 비즈니스로직 수행이 성공 및 실패했을 때의 결과값을 ModelLocator에 세팅해줌
Business Delegate : RPC 함수 호출 • 역할 • Command로부터 데이터를 받아 ServiceLocator에 정의된 RPC함수를 호출 • RPC함수는 HTTPService, WebService, RemoteObject등이 됨 • 사용법 • Business Delegate에는 command에서 위임한 함수를 정의 • 작동 • responder를 통해서 실행결과는 다시 Command에서 처리되도록 함 • 서비스(Service)를 호출하여 커맨드로 결과를 전송한다.
Service Locator : RPC 객체를 담음 • 역할 • RPC객체를 담음 • 사용법 • RPC객체 즉 HTTPService, WebService, RemoteObject등 실제로 데이터를 처리해주는 서비스 객체 들을 정의함 • 이 RPC객체의 id명은 Business Delegate에서 찾는 이름이 됨 • 작동 • RPC서비스를 호출하고 결과를 델리게이트로 전송
Value Object : 데이터 모델 • 역할 • 데이터 모델을 담도록 만들어진 객체 • 사용법 • Value Object는 자바의 Value Object와 같은 클래스로 정의 • 캔곰 프레임워크의 ValueObject 클래스를 구현 • Object.registerClass를 통해서 자바의 Value Object클래스와 플렉스 액션스크립트 클래스를 매핑시켜 줌 • 작동 • 자바에서 Value Object로 넘어오는 객체 값을 액션스크립트의 객체 값으로 받아 줌
ModelLocator : 모든 데이터를 저장 • 역할 • 플렉스 클라이언트가 사용할 모든 데이터를 담음 • RIA애플리케이션은 하나의 페이지에 모든 화면이 들어있기 때문에 각 화면들이 사용할 데이터를 중앙집중적으로 관리하는 것이 코딩에 유리 • 화면에 있는 컴포넌트와 데이터바인딩을 통해서 갖고 있는 데이터가 바뀌면 바로 보여줄 수 있다. • 사용법 • 화면에서 사용하는 모든 데이터 레퍼런스는 ModelLocator에 들어감 • ModelLocator는 싱글톤으로 구현됨 • 작동 • 커맨드는 델리게이트(Delegate)로부터의 리스판스(response)를 처리한 다음 모델로케이터에 들어있는 데이터를 업데이트한다. • 뷰는 모델로케이터에 바인딩 되어 있기 때문에 자동으로 화면이 업데이트됨
캔곰프레임워크 작업 절차 1단계 : 캔곰 프로젝트 생성 • 캔곰 프로젝트 생성 • Cairngorm.swc파일을 Library path에 추가
캔곰프레임워크 작업 절차 2단계 : 캔곰 폴더 생성 • 패키지 구조에 따라 6개의 폴더 생성 • business, commands, control, model, view, vo라는 이름으로 6개의 폴더를 생성
캔곰프레임워크 작업 절차 3단계 : view 부분 작업 • view 디렉토리에는 사용자가 볼 화면을 담은 컴포넌트 저장 • 화면을 만들었으면 현재 경로(com.adobe.cairngorm.lotto.view)에 대한 네임스페이스를 view라는 이름으로 정의 • 화면이 완성되면 view 컴포넌트를 메인애플리케이션에 인클루드함 <mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:view="com.adobe.cairngorm.lotto.view.*" …중략… /> <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" backgroundColor="#c6db94" fontSize="12" xmlns:view="com.adobe.cairngorm.lotto.view.*"> <view:LottoView/> </mx:Application>
캔곰프레임워크 작업 절차 4단계 : ValueObject 부분 작업 • vo 디렉토리에 화면에서 사용할 데이터 모델(ValueObject) 구성 • com/adobe/cairngorm/lotto/vo 디렉토리 밑에 LottoVO.as라는 이름으로 액션스크립트 클래스를 만들어 줌 • RemoteObject를 사용할 경우 [RemoteClass]라는 메타태그를 사용해서 매핑대상이 되는 자바클래스의 풀 경로 정의 package com.adobe.cairngorm.lotto.vo { import com.adobe.cairngorm.vo.ValueObject; [RemoteClass(alias="com.adobe.cairngorm.lotto.vo.LottoVO")] public class LottoVO implements ValueObject { public var ans1:Number; public var ans2:Number; public var ans3:Number; } }
캔곰프레임워크 작업 절차 5단계 : ValueObject 자바 클래스 • C:\fds2\jrun4\servers\default\flex\WEB-INF\classes\com\adobe\cairngorm\lotto 디렉토리에 vo와 business 디렉토리를 생성 • vo 디렉토리에 LottoVO.java란 이름으로 앞에서 작성한 ValueObject 액션스크립트 클래스를 자바빈즈로 구현 • 자바빈즈 객체값을 네트워크로 전송하기 위해서 클래스 선언에 implements Serializable이라고 표시함 package com.adobe.cairngorm.lotto.vo; public class LottoVO implements java.io.Serializable { public int ans1; public int ans2; public int ans3; public LottoVO() { } }
캔곰프레임워크 작업 절차 6단계 : Business 자바클래스 • C:\fds2\jrun4\servers\default\flex\WEB-INF\classes\com\adobe\cairngorm\lotto 디렉토리에 business 디렉토리를 생성 • 예) LottoDelegate.java라는 이름으로 작성하여 저장한다. 이 클래스는 플렉스에서 RemoteObject로써 LottoVO객체를 파라미터로 사용하여 lottoResult라는 메서드를 호출하면 그 결과를 ArrayList형태로 리턴한다. package com.adobe.cairngorm.lotto.business; import java.util.*; import com.adobe.cairngorm.lotto.vo.LottoVO; public class LottoDelegate { public List lottoResult(LottoVO lotto) { ArrayList al = new ArrayList(); …. 중략 … al.add(lotto); return al; } }
캔곰프레임워크 작업 절차 7단계 : RemoteObject 작업 • 앞에서 작성한 LottoDelegate 자바 클래스를 RemoteObject로 정의 • remoting-config.xml 파일에 lottoService라는 이름으로 RemoteObject의 destination을 정의 • Services.mxml 정의 • LottoDelegate.java를 RemoteObject로 등록하는 파일이다. … 중략 … <destination id="lottoService"> <properties> <source>com.adobe.cairngorm.lotto.business.LottoDelegate</source> </properties> </destination> … 중략 … <?xml version="1.0" encoding="utf-8"?> <cairngorm:ServiceLocator xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:cairngorm="com.adobe.cairngorm.business.*"> <mx:RemoteObject id="lottoService“ destination="lottoService“ showBusyCursor="true" result="event.token.resultHandler( event );“ fault="event.token.faultHandler( event );"> </mx:RemoteObject> </cairngorm:ServiceLocator>
캔곰프레임워크 작업 절차 8단계 : Delegate 클래스 정의 • 사용자로부터 이벤트가 발생하면 거기에 반응하여 RemoteObject의 메서드를 호출해주는 대리인의 역할을 함 • Delegate는 클래스가 초기화 될 때 RemoteObject 서비스를 ServiceLocator에서 찾고 RemoteObject의 비즈니스메서드를 호출한다. package com.adobe.cairngorm.lotto.business { import com.adobe.cairngorm.business.Responder; import com.adobe.cairngorm.business.ServiceLocator; import com.adobe.cairngorm.lotto.vo.LottoVO; // ValueObject 명시 import mx.rpc.AsyncToken; // RemoteObject 결과 처리 import mx.rpc.events.ResultEvent; public class LottoDelegate { private var responder : Responder; private var service : Object; public function LottoDelegate(responder : Responder){ this.service = ServiceLocator.getInstance().getService( "lottoService" ); this.responder = responder; } public function lotto( lottoVO : LottoVO ): void {// RemoteObject 자바빈즈의 메서드 호출 var token : AsyncToken = service.lottoResult( lottoVO ); token.resultHandler = responder.onResult; token.faultHandler = responder.onFault; } } }
캔곰프레임워크 작업 절차 9단계 : event 클래스 정의 • com/adobe/cairngorm/viote/control 디렉토리에 view에서 발생할 이벤트를 정의 • LottoEvent.as의 정의로서 앞에서 정의한 ValueObject를 인수로 받도록 한다. 이 ValueObject는 인수로써 비즈니스 메서드에게까지 전달이 된다. package com.adobe.cairngorm.lotto.control { import com.adobe.cairngorm.control.CairngormEvent; import com.adobe.cairngorm.lotto.vo.LottoVO; public class LottoEvent extends CairngormEvent { public var lottoVO:LottoVO; public function LottoEvent(lottoVO:LottoVO) { trace('[실행 1단계] 캔곰 이벤트 생성자 호출 : View -> Event'); super(LottoControl.EVENT_VOTE); trace('[실행 2단계] 캔곰 이벤트이름 부모 생성자로 전달 '); this.lottoVO = lottoVO; } } }
캔곰프레임워크 작업 절차 10단계 : FrontController 클래스 정의 • com/adobe/cairngorm/viote/control 디렉토리에 view에서 이벤트가 발생하면 실행될 명령(command)를 정의 • LottoControl클래스는 FrontController를 확장하여 정의한 것으로 초기화되면 addCommand함수를 호출하여 이벤트명과 커맨드를 같이 매핑하여 등록 • 추가적인 업무에 대해서 이벤트명과 비즈니스 메서드를 계속 추가해나감 package com.adobe.cairngorm.lotto.control { import com.adobe.cairngorm.control.FrontController; import com.adobe.cairngorm.lotto.commands.LottoCommand; public class LottoControl extends FrontController { public function LottoControl(){ addCommand(LottoControl.EVENT_VOTE, LottoCommand ); } public static const EVENT_VOTE:String = "lotto"; } }
캔곰프레임워크 작업 절차 11단계 : Command 클래스 정의 • com/adobe/cairngorm/viote/commands 디렉토리에는 이벤트가 발생했을 때 실행되어 할 명령어(commands )클래스를 정의 • commands클래스는 이벤트당 1개씩 1:1로 작성 • commands 클래스에는 execute, onResult, onFault의 3개의 메서드를 구현해주어야 함 • execute메서드는 사용자가 발생시킨 이벤트를 인수로 받아서 대리인(Delegate)의 메서드를 호출하면서 이벤트 값도 같이 전달 • onResult 와 onFault는 이벤트가 발생하고 나서 결과를 처리해주는 메서드에 해당하는 것으로 결과값을 ModelLocator의 변수에 세팅 • ModelLocator는 처음에 실행되었을 때의 인스턴스를 계속 유지하도록 ModelLocator.getInstance()라는 함수를 통해 인스턴스를 만들기 때문에 추가되는 데이터를 게속 유지할 수 있다.
캔곰프레임워크 작업 절차 11단계 : Command 클래스 정의 package com.adobe.cairngorm.lotto.commands { import mx.rpc.events.ResultEvent; import com.adobe.cairngorm.business.Responder; import com.adobe.cairngorm.commands.Command; import com.adobe.cairngorm.control.CairngormEvent; import com.adobe.cairngorm.lotto.business.LottoDelegate; import com.adobe.cairngorm.lotto.control.LottoEvent; import com.adobe.cairngorm.lotto.model.ModelLocator; import com.adobe.cairngorm.lotto.vo.LottoVO; import mx.collections.ArrayCollection; public class LottoCommand implements Command, Responder { private var model : ModelLocator = ModelLocator.getInstance(); public function execute( event : CairngormEvent ) : void { trace('[실행 5단계] 캔곰 Command execute 호출 : Cairngorm -> Command'); model.lottoResult.isPending = true; trace('[실행 6단계] 캔곰 Delegator로 responder 전달 : Command -> Delegate'); var delegate : LottoDelegate = new LottoDelegate( this ); trace('[실행 8단계] 캔곰 이벤트 객체로 사용자 입력값이 들어있는 event 전달 : Command -> Event'); var lottoEvent : LottoEvent = LottoEvent( event ); delegate.lotto( lottoEvent.lottoVO ); } public function onResult( event : * = null ) : void { trace('[실행 10단계] 캔곰 ModelLocator에 결과값 세팅 : Command -> ModelLocator'); model.lottoResult.lottoAC = event.result; model.lottoResult.isPending = false; model.workflowState = ModelLocator.VOTE_RESULT_STATE; } public function onFault( event : * = null ) : void { model.lottoResult.statusMessage = "에러 발생!!"; model.lottoResult.isPending = false; } } }
캔곰프레임워크 작업 절차 12단계 : model 클래스 정의 • com/adobe/cairngorm/viote/model 디렉토리에서는 ModelLocator클래스를 정의해두고 여기에는 모든 데이터의 정의가 들어가도록 함 • 여기서는 LottoResult라는 클래스를 이용하여 데이터를 담아오며 LottoResult클래스는 ModelLocator클래스에서 초기화한다.
캔곰프레임워크 작업 절차 12단계 : model 클래스 정의 package com.adobe.cairngorm.lotto.model { import com.adobe.cairngorm.model.ModelLocator; [Bindable] public class ModelLocator implements com.adobe.cairngorm.model.ModelLocator { private static var modelLocator:com.adobe.cairngorm.lotto.model.ModelLocator; public static function getInstance():com.adobe.cairngorm.lotto.model.ModelLocator { if(modelLocator==null) { trace("[초기화 1단계] ModelLocator 인스턴스를 새로 생성 : View -> ModelLocator"); modelLocator = new com.adobe.cairngorm.lotto.model.ModelLocator(); } else { trace("[실행 4단계] ModelLocator 인스턴스를 싱글톤으로 가져오기"); } return modelLocator; } public function ModelLocator() { if ( com.adobe.cairngorm.lotto.model.ModelLocator.modelLocator != null ) throw new Error( "Only one ModelLocator instance should be instantiated" ); } public var lottoResult:LottoResult = new LottoResult(); public var workflowState : Number; public static const VOTE_RESULT_STATE:Number = 1; public static const VOTE_INSERT_STATE:Number = 2; } }
캔곰프레임워크 작업 절차 12단계 : model 클래스 정의 package com.adobe.cairngorm.lotto.model { import com.adobe.cairngorm.lotto.vo.LottoVO; import mx.collections.ArrayCollection; public class LottoResult { [Bindable] public var lottoVO:LottoVO; [Bindable] public var lottoAC:ArrayCollection = new ArrayCollection(); [Bindable] public var statusMessage:String; [Bindable] public var isPending:Boolean; public function LottoResult() { trace('[초기화 2단계] ModelLocator에서 사용하는 vo클래스 생성자 호출 : '); } } }
캔곰프레임워크 작업 절차 13단계 : 화면과 이벤트 연결 • 화면에서 사용자가 조작을 하면 이벤트가 발생되도록 함 • Event ->Command -> Delegate -> ModelLocator를 통해 데이터가 화면에 보이도록 함 • 사용자가 버튼을 누르면 데이터를 ValueObject 담고 이는 LottoEvent클래스에 담아 이벤트를 발생시킨다. • 프론트컨트롤러에서는 View로부터 이벤트가 발생하면 거기에 해당하는 커맨드를 찾아서 실행함. • 프론트컨트롤러는 메인애플리케이션(LottoMain.mxml)에서 반드시 인스턴스화 해야함 var event : LottoEvent = new LottoEvent( lottoVO ); CairngormEventDispatcher.getInstance().dispatchEvent( event );
캔곰프레임워크 작업 절차 14단계 : 캔곰 인스턴스 초기화 • 메인애플리케이션에서는 ModelLocator를 인스턴스화하고 프론트컨트롤러, 서비스로케이터 등을 같이 인스턴스화 한다. • view에게 ModelLocator의 데이터를 바인딩 시켜주어 바뀐 데이터가 업데이트 되도록 한다. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:business="com.adobe.cairngorm.lotto.business.*" xmlns:control="com.adobe.cairngorm.lotto.control.*" xmlns:view="com.adobe.cairngorm.lotto.view.*"> <mx:Script> <![CDATA[ import com.adobe.cairngorm.lotto.model.ModelLocator; // [초기화 1단계] : ModelLocator를 싱글톤으로 생성함 [Bindable] public var model:ModelLocator = ModelLocator.getInstance(); ]]> </mx:Script> <business:Services id="lottoServices"/> <control:LottoControl id="controller"/> <view:LottoView lottoResult="{model.lottoResult}"/> </mx:Application>
캔곰프레임워크 작업 정리 • 메인: LottoMain.mxml : 웹루트에 위치하는 메인 애플리케이션 파일 • view : LottoView.mxml : 화면 로직을 정의 • vo : LottoValueObject.as : 화면에서 가져갈 데이터 구조 정의 • control : LottoEvent.as, LottoControl.as : 사용자의 조작에 따른 이벤트와 이를 연결시켜주는 컨트롤 정의 • business : Services.mxml, LottoDelegate.as : RemoteObject의 위치와 이를 사용해서 비즈니스 메서드를 호출하는 Delegate정의 • commands : LottoCommand.as : 이벤트가 발생하면 실행 하게될 커맨드 정의 • model : ModelLocator.as, LottoResult.as : 데이터를 담아 처리할 클래스 정의