자바스크립트/Ext JS2012. 12. 7. 13:23

이번에는 지금까지 코드를 정리 하는 시간을 좀 갖도록 하겠습니다. 실제 시스템을 ExtJS로 구축하도보면 

특히나 MVC모델로 구현할 경우 Controller가 비대해지는 현상이 발생합니다.


이는 MVC를 오해해서 생기는 현상이 아닌가 생각되는데요. MVC에서 V는 View를 의미하는데 이러한 이유로 

View안에는 기능적인 코드가 다 빠져있고 그 것들이 모두 Controller안에 들어가 있게 됩니다. 


Controller역할을 로직의 구현으로 이해하는 경우인것 입니다. 결과적으로 Controller안에 모든 관련 View의 기능이

 구현되어 있고 View는 껍데기만 존재하는 것이죠.


이렇게 비대해진 Controller는 유지보수 입장에서 굉장히 길고 파악하기 힘들게 되고 View자제의 재활용성이 

기능을 포함하지 않은 단순 껍데기만 재활용하게 되어 반쪽짜리 클래스로 전락하게 되는 것이죠.


제 생각이지만 이게 아니라 View은 일종의 클래스 (화면을 기준으로 화면제어 등의 기능이 포함된.)로 생각하고

UI와 그에 따른 제어기능도 포함되도록 해야합니다. 그래야만 재활용 측면에서도 해당 View Class를 가져다 쓸때

 기능도 함께 쓸 수 있게됩니다.


 기능이 모두 Controller에 구현될 경우 재활용은 Controller까지 신경써야하니 활용도가 떨어지게 되는 것입니다.


그래서 아래 코드는 View안에서는 자신과 관련된 기능에 대해 구현을 하고 Controller는 View에서 구현 된 

기능을 함수 단위로 호출 만 하도록 하게끔 리팩토링 작업을 한 것이니 참고하고 봐주시기 바랍니다.


아래 코드의 요점은 Controller에 구현된 로직을 각 뷰 클래스로 옮기고 Controller에서는 함수단위로 호출만

 하도록 변경한것입니다.


// app/controller/FrameController.js 를 수정한다.
// views, refs, onLaunch를 확인하자.
Ext.define('ria.controller.FrameController', {
    extend: 'Ext.app.Controller',
    //stores: ['system.Systems'],
    views: ['ria.view.frame.WestMenuPanel',
            'ria.view.frame.WestMenuDataViewPanel'], // 꼭 명시되어야함, 명시하지 않을 경우 require를 이용해야합.
    refs: [
            {ref: 'westMenu', selector: 'WestMenuPanel'}
        ],
    init: function() {
    	this.control({
    		// step1. 좌측 매뉴에 추가된 패널 즉 시스템 패널에 대한 이벤트 추가.
    		'WestMenuPanel > WestMenuDataViewPanel': {
    			afterrender: this.firstSelect,
    			expand: this.onItemClicked
            }
         });
    },
    /**
     *  step2. afterrender는 추가된 패널 별로 render된 이후에 호출한다.
     *	추가된 시스템 패널 중에 열려 있는지 확인하면 맨처음 하나만 열리게 된다.
     *	그 열려있는 시스템 패널에 하위 프로그램이 로딩되어 추가될 수 있도록 코딩해야한다.  
    **/
    firstSelect : function(panel){
    	panel.firstSelectDataView();
    },
    /**
     * Step3. 시스템 패널을 클릭 할 때 마다 expand이벤트가 호출 된다.
     * 이 때 클릭되어 expand된 패널 위에 하위 프로그램을 출력하면 된다.
     * @param a
     * @param b
     * @param c
     */
    onItemClicked : function(panel){
    	panel.onItemClicked();
    },
    onLaunch: function() {
        this.getWestMenu().setWestMenuDataViewPanel();
    }
});

// app/view/frame/WestMenuDataViewPanel.js 를 생성한다.
Ext.define('ria.view.frame.WestMenuDataViewPanel',{
    extend: 'Ext.panel.Panel',
    alias: 'widget.WestMenuDataViewPanel',
    animCollapse : true,
    collapsible : true,
    collapsed   : true,
    useArrows: true,
    rootVisible: false,
    multiSelect: false,
    initComponent: function() {
    	var me = this;
        Ext.apply(this, {
            items: [{
                xtype: 'dataview',
                trackOver: true,
                cls: 'feed-list',
                itemSelector: '.feed-list-item',
                overItemCls: 'feed-list-item-hover',
                tpl: '
{pgm_nm}

' }], header: { toolFirst: true }, /*** * Date : 2012.12.06 * Desc : dataview상에 출력된 리스트 중에 맨처음 프로그램이 * 선택되어지도록 한다. * @param store */ firstSelectDataView : function(){ if(me.collapsed) return; var store = this.onItemClicked(); if(store){ var task = new Ext.util.DelayedTask(function(){ me.down('dataview').getSelectionModel().select(store.getAt(0)); }); task.delay(1000); } }, /** * Step3. 시스템 패널을 클릭 할 때 마다 expand이벤트가 호출 된다. * 이 때 클릭되어 expand된 패널 위에 하위 프로그램을 출력하면 된다. * @param a * @param b * @param c */ onItemClicked : function(){ if(me.collapsed) return // 패널이 접히지 않은 놈을 찾는다. if(me.store) return; me.store = Ext.create('ria.store.system.Programs'); // 재활용 되는 것을 막는다. me.store.load({ params: { // 아래 코드는 시스템 패널이 가지고 있는 시스템 아이디를 프로그램 store에 전달하는 // 코드다 이렇게 해야 각기 시스템 패널별로 해당 시스템 이하의 프로그램을 가져올수 있다. pgm_syscd: this.pgm_syscd } }); // 최종 시스템 패널 안으 dataview에 프로그램 store를 바인딩 한다. me.down('dataview').bindStore(me.store); return me.store; } }); this.callParent(arguments); } }); // app/view/frame/WestMenuPanel.js를 추가합니다. Ext.define('ria.view.frame.WestMenuPanel',{ extend : 'Ext.panel.Panel', alias : 'widget.WestMenuPanel', layout:'accordion', // 이놈 하위에 추가될 dataview또한 accordion collapsible: true, split:true, title : '^^', activeItem: 0, initComponent: function() { var me = this; Ext.apply(this, { /*** * Date : 2012.12.07 * Desc : 최초 첫번째 프로그램 선택. */ setWestMenuDataViewPanel: function(){ var store = Ext.create('ria.store.system.Systems'); store.load(function(record, b, c){ // 아직 로드전이므로 로드한다.이때 json파일 호출 store.each(function(rec){ // store를 탐색하여 me.add({ // 메뉴가 추가될 패널에 아래와 같이 패널을 추가. xtype:'WestMenuDataViewPanel', title:rec.get('pgm_sysnm'), // 시스템명 pgm_syscd:rec.get('pgm_syscd'), // 시스템 코드 iconCls:rec.get('pgm_sysicon') // 아이콘이 있다면 표기 }); }); }); } }); this.callParent(arguments); } });

이제 프로그램을 다시 확인해보면 동일하게 작동하는 것을 알수 있습니다. 앞으로는 Controller에 기능을 구현하고 구현된 기능을 어디로 옮겨야할지 생각해 본 후 각 뷰클래스등에 구현하므로해서 코드의 밸런스를 맞춰가도록 하겠습니다.


Posted by 베니94