첫번째 복합 frame으로 이루어진(feed sample을 응용한) 샘플을 만들어서 실행까지는 어떻게든 해 볼 수 있지만 extjs를 이용한 모든 코딩이 이렇게 하드코딩으로만 이루어진다면 복잡한 디버깅과 끝없이 반복되는 bracket([,{,},]) 들 때문에 더이상 쳐다보고 싶지도 않게 된다.

아무래도 코드를 정리하고 모듈로 쪼개는 것이 좋겠다. 모듈로 쪼개기 위해서는 아무래도 기능적으로나 형태적으로 반복되는 부분을 잘 구분하고 전체적인 형태를 함수 호출 형태로 구성하는 것이 가장 쉬운 방법이다. 그러나 지나친 함수화는 자칫 파편화를 일으켜 오히려 전체적인 흐름을 방해할 수도 있으므로 간단한 수준의 함수화를 진행하도록 하자.

ExtJs는 화면에서 실행되는 client side script임을 여러차례 강조했는데 화면이 이미 script 언어이므로 이를 다시 모듈화하여 함수로 묶는 부분은 그렇게 큰 효용성이 없다. 물론 단순 반복적인 작업은 당연히 함수로 구현하는 것이 좋으며 소스의 크기가 작으면 로딩 속도와 실행속도에서 약간의 이득이 있겠지만 개발자의 입장에서는 아주 미세한 로딩 속도보다는 개발과 디버깅의 편의성이 훨씬 중요하다.
그래서, Server side script에서 화면 부분을 모듈로 정리하기로 했다.

우선 앞에서 설명한 예제를 php 언어로 재작성하였다.

index.php
<?php
// session 처리와 login 처리 
...
// db를 위한 부분
     include 'lib/mysql.php';
     include 'lib/check_user.php';
//
?>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=7"> <title>F-square</title> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
<meta http-equiv="expires" content="0" /> 
<meta http-equiv="Cache-control" content="no-cache" /> 
<meta http-equiv="Cache-control" content="max-age=0" /> 
<meta http-equiv="pragma" content="no-cache" />
<!-- 적용된 테마 외에 추가적인 style정의를 모아 놓은 sheet -->
<link rel="stylesheet" type="text/css" href="./design/css/menu_blue.css" media="screen" />

<!-- extjs 핵심 library -->
<script type="text/javascript" src="./js/include-ext.js"></script> 

<script type="text/javascript" src="./js/options-toolbar.js"></script>

<script type="text/javascript" src="./js/lib.js"></script>
<?
      include 'js/tree-menu.php';
      $conn_db = mysql_connect();
?>

<style type="text/css">
// style, icon class등 추가
</style>

Ext.onReady(function() {
    Ext.QuickTips.init();
    var viewport = Ext.create('Ext.Viewport', {
    id: 'border-example',
    layout: 'border',
    items: [
        // create instance immediately
        Ext.create('Ext.Component', {
            region: 'north',      // 화면의 북쪽(윗쪽)에 위치
            height: 58, // give north and south regions a height 
            autoEl: {
                tag: 'div'
            }
        }), {

            // lazily created panel (xtype:'panel' is default)
            region: 'south',  // 화면의 남쪽(아랫쪽)에 위치하는 panel
            contentEl: 'south', // div id='south'라고 하는 content를 overriding함
            split: true,  // 크기조정이 가능한 split
            height: 70,
            minSize: 100,
            maxSize: 200,
            collapsible: true,
            collapsed: true,
            title: 'Ticker',
            margins: '0 0 0 0'
        },

        {
            region: 'west',            // 화면의 서쪽(왼쪽)에 위치
            stateId: 'navigation-panel',
            id: 'west-panel', // see Ext.getCmp() below
            title: 'Menu',
            split: true,  // 크기조정이 가능한 split
            width: 200,
            minWidth: 175,
            maxWidth: 400,
            collapsible: true,  // 닫힘 기능이 가능
            animCollapse: true,  // 닫힐때 애니메이션 적용
            margins: '0 0 0 5',
            layout: 'accordion',  // accordion layout으로 탭들이 존재
            items: [
<?
      drawTreeMenu('favorit', $conn_db);
?>
                     ,
<?
      drawTreeMenu('main_menu', $conn_db);
?>
                    , 
<?
      drawTreeMenu('config', $conn_db);
?>

            ]
        },

        Ext.create('Ext.tab.Panel', {   // 화면의 가운데 tab panel생성 (mainpanel이라고 명명)
            region: 'center', // a center region is ALWAYS required for border layout
            deferredRender: false,
            bodyStyle: 'background-size:contain; background-image:url(http://www.nyewall.com/images/2013/07/background-flowers-sky-wallpaper-blue-nice-wallpapers.jpg);',
            id: 'MainPanel',
            activeTab: 0 // first tab initially active
        })]
    });

    // get a reference to the HTML element with id "hideit" and add a click listener to it
    Ext.get("hide-it").on('click', function(){
        var w = Ext.getCmp('west-panel');
        w.collapsed ? w.expand() : w.collapse();
    });
});
</script>

<body bgcolor="#F0F0FF" /* onload=reqeustFullScreen();*/>
<table width=100% border=0 cellpadding=0 cellspacing=0 >
<tr><td align=left width=145 class="logo">AMS</td><td align=left class="logo"></td></tr>
<tr><td align=left width=145 class="logo_under">&nbsp; Management System</td><td class="logo_under">- AMS Consulting</td></tr>
</table>

<!-- use class="x-hide-display" to prevent a brief flicker of the content -->
<div id="west" class="x-hide-display">
<p>west panel</p>
</div>
<div id="center2" class="x-hide-display">
<a id="hide-it" href="#"> </div>
<div id="center1" class="x-hide-display">
</div>
</div>
<div id="south" class="x-hide-display">
<p>정상상태</p>
</div>
<br/>

이제 index.php가 조금 간단하게 줄어들었다. 추가로 수정해야 하는 부분은 drawTreeMenu를 구성부분이다. php의 장점 중 하나가 함수 내에 html 텍스트를 임의로 삽입할 수 있고 문법 체크가 덜 엄격하다는 부분으로 비슷한 기능으로 비교대상이 되곤 하는 jsp로 구성하는 경우와는 약간 차이가 난다(jsp로도 구성은 가능하나 일부 변경작업이 필요하다).

js/tree-menu.php
<?php
function drawTreeMenu( $title, $dbconn )
{
     // 보안을 위해 추가적인 session check와
     // theme, cookie 등을 체크

     if ( $title == 'main_menu') {
        $str_id = 'Fund-manager';
        $icon   = 'info';
        $cond_clause = 'user_level <= menu_level ';
    }
    else if ( $title == 'favorit' ) {
        $str_id = 'favorit';
        $icon   = 'nav';
        $cond_clause = 'favorit = true';
    }
?>
       {
        title: '즐겨찾기',
        xtyle: 'treepanel',
        id: '<=$str_id>',
        iconCls: '<=$icon>',
        margins: '2 2 0 2',
        autoScroll: true,
        ...
        root:{ text: "Root Node",
              children: [
<?
                 // 메뉴를 조회하기 위한 query문
                 $sql = "SELECT menu_title, menu_num, leaf ";
                 $sql.= "FROM menu_table ";
                 $sql.= "WHERE use_yn = 'Y'  ";
                 $sql.= $cond_clause;
                 ...
                 menu를 화면에 출력하는 부분
?> 
              ]
          },
          listeners: {
                itemclick: function(s,d) {
                 ...
          }
       }
<?
}
?>

php로 extjs의 복잡함을 줄이기는 역부족이다. 그러나, Style sheet를 잘 정의하고 반복적인 컴포넌트 호출 (chart, grid 등)부분을 function으로 분리하기만 해도 디버그와 화면 개발이 훨씬 쉬워진다.

By yaplab

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다