'2013/11'에 해당되는 글 1건

  1. 2013.11.20 [ExtJS4 MVC 실전강좌] 멀티게시판 애플리케이션 구현(1) 1
자바스크립트/Ext JS2013. 11. 20. 15:23

이번 시간에는 게시판 애플리케이션의 UI를 구성하고 데이터를 채울 준비를 해본다. 간략히 게시판 애플리케이션에 대해 설명하면, 좌우로 나눠진 게시판 애플리케이션에서 좌측에 게시판 리스트를 그리드로 구성하고 해당 그리드에서 게시물을 클릭하면 우측 패널에 해당 글의 내용이 보여지는 구조다.

 

---------------------------------------

연재순서

1회 | 2013. 9 | ExtJS4 클래스 시스템의 이해

2회 | 2013. 10 | ExtJS4 MVC 아키텍처의 이해

3회 | 2013. 11 | 시스템 뼈대 구현하기

4회 | 2013. 12 | ExtJS4 실전코딩 : 멀티 게시판 애플리케이션 구현 (1)

5회 | 2014. 1 | ExtJS4 실전코딩 : 멀티 게시판 애플리케이션 구현 (2)


이전시간에 우리는 애플리케이션의 뼈대를 구성하고 UI를 가지고 있는 클래스라면 어떤 형태로도 보여지는 구조를 구현해 보았다. 이런 구조의 뼈대는 게시판과 같이 동일한 구조를 반복적으로 표현하는 애플리케이션뿐만 아니라 전혀 다른 여러가지 형태의 애플리케이션 클래스를 실행할 수 있는 좋은 구조다.

이제 게시판 애플리케이션의 UI를 구성해 보자. <표 1>은 게시판을 구성할 클래스들에 대한 설명이다.

 타입

 클래스명

 기능

비고 

 모델

 MyMvc.model.Board

 게시판 데이터 모델 클래스

 

 뷰

MyMvc.view.BoardMain 

 한 개의 게시판 대표 클래스

 

MyMvc.view.BoardList 

 게시판 리스트를 표현할 그리드 클래스

 

 MyMvc.view.BoardView

 한 개의 게시물의 내용을 보여줄 클래스

 

 컨트롤러

 MyMvc.controller.Board

 게시판 관리 컨트롤러 클래스

 

 스토어

MyMvc.store.Boards 

 게시판 데이터 집합

 

<표 1> 클래스 정의

 

UI 클래스를 구현하기 앞서 <리스트 1>과 같이 실행할 프로그램의 클래스명을 수정하도록 하자. 게시판 애플리케이션의 메인 클래스는 MyMvc.view.board.BoardMain이다. 최초 애플리케이션이 실행되면 첫번째 데이터가 선택되고 BoardMain 클래스가 실행되도록 한다는 내용이다.

 

<리스트 1> /json/programlist.json

{"entitys": [
    {
        "pgm_syscd": "F001",
        "pgm_class": "MyMvc.view.board.BoardMain",
        "pgm_icon": "grid",
        "pgm_nm": "ExtJS",
        "brd_number": "001"
    },
    {
        "pgm_syscd": "F001",
        "pgm_class": "MyMvc.view.board.BoardMain",
        "pgm_icon": "grid",
        "pgm_nm": "Sencha Touch",
        "brd_number": "002"
    },
    {
        "pgm_syscd": "F002",
        "pgm_class": "MyMvc.view.board.BoardMain",
        "pgm_icon": "grid",
        "pgm_nm": "구인_구직",
        "brd_number": "003"
    }
],
    "errMsg": "", "errTitle": "검색결과", "message": "", "success": true, "totalCount": "2"}

 

app/view 폴더 아래에 board 폴더를 생성하고 <리스트 2>와 같이 BoardMain.js 클래스를 구현하자. 이 클래스는 board 레이아웃을 사용해 좌측에 그리드와 우측에 패널을 가지고 있고, 게시판 아이디로 사용할 brd_number를 config 정보로 가지고 있다.

 

<리스트 2> BoardMain 클래스

Ext.define('MyMvc.view.board.BoardMain', {
    extend: 'Ext.container.Container',
    alias: 'widget.boardmain',
    layout : 'border',

    config: {
      brd_number : ''
    },
    initComponent: function () {
        var me = this;
        me.initConfig();

        Ext.apply(me, {
            items: [
                {
                    region: 'center',
                    xtype: 'boardlist',
                    brd_category_cd : me.getBrd_number()
                },
                {
                    xtype: 'boardview',
                    title: '게시물',
                    width : 500,
                    region: 'east',
                    collapsible: true,
                    collapsed : true,
                    split: true
                }
            ]
        });
        me.callParent(arguments);
    }
});

좌측 그리드 클래스를 작성하자. 클래스명은 BoardList이고 Grid 클래스를 상속받으며 boarlist이라는 위젯명을 사용한다. <리스트 3>에서 스토어는 Ext.create를 사용해 매번 생성하도록 했다. 컨트롤러에 스토어를 등록하고 store: 'Board'로 사용할 수도 있겠으나, 이렇게 할 경우 모든 게시판이 하나의 스토어를 공유해 사용하게 되므로 각 게시판별 게시물을 읽어오기 어려워진다.

 

<리스트 3> BoardList 클래스 코드

Ext.define('MyMvc.view.board.BoardList', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.boardlist',
    columnLines: true,
    initComponent: function () {
        var me = this;
        this.store = Ext.create('MyMvc.store.Boards');
        Ext.apply(this, {
            tbar: [
                {
                    xtype: 'button',
                    text: '글쓰기 ',
                    action: 'board.create'
                }
            ],
            columns: [
                {
                    text: '게시글번호 ',
                    width: 80,
                    dataIndex: 'brd_seq',
                    field: {
                        allowBlank: false
                    }
                },
                {
                    text: '제목 ',
                    flex: 1,
                    dataIndex: 'brd_title',
                    field: {
                        allowBlank: false
                    }
                },
                {
                    text: '입력자 ',
                    width: 70,
                    dataIndex: 'brd_input_user_nm',
                    field: {
                        allowBlank: false
                    }
                },
                {
                    text: 'Input Date ',
                    width: 150,
                    align: 'center',
                    dataIndex: 'brd_input_date',
                    field: {
                        allowBlank: false
                    }
                },
                {
                    text: 'Read Cnt ',
                    width: 70,
                    dataIndex: 'brd_read_cnt',
                    field: {
                        allowBlank: false
                    }
                }
            ],
            dockedItems: [
                {
                    xtype: 'pagingtoolbar',
                    store: this.store,
                    dock: 'bottom',
                    displayInfo: true
                }
            ]
        });

        me.callParent(arguments);
    }
});

 

우측 패널 클래스를 작성한다. 우측 패널 클래스는 내부에 게시물 내용을 확인하는 폼 패널과 함께 조작을 위한 버튼을 가지고 있다.

 

<리스트 4> BoardView 클래스 코드

Ext.define('MyMvc.view.board.BoardView', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.boardview',
    bodyPadding: 5,
    autoScroll: true,
    collapsed: true,

    initComponent: function () {
        var me = this;
        Ext.apply(this, {
            items: [
                {
                    xtype: 'form',
                    bodyPadding: 10,
                    itemId: 'board.form',
                    layout: 'anchor',
                    defaults: {
                        anchor: '100%'
                    },
                    buttons: [
                        {
                            xtype: 'statusbar',
                            defaultText: ' ',
                            flex: 1
                        },
                        {
                            action: 'board.save',
                            text: 'Save',
                            scope: me,
                            handler: function () {
                                this.onSave();
                            }
                        },
                        {
                            action: 'board.remove',
                            text: 'Del ',
                            listeners: {
                            }
                        } ,
                        {
                            action: 'board.close',
                            text: 'Close ',
                            listeners: {
                            }
                        }
                    ],

                    items: [
                        {    xtype: 'hiddenfield', name: 'brd_seq'    },
                        {    xtype: 'hiddenfield', name: 'brd_category_cd'    },
                        {
                            xtype: 'textfield',
                            name: 'brd_title',
                            allowBlank: false,
                            fieldLabel: '제 목',
                            emptyText: 'Title'
                        },
                        {
                            xtype: 'textareafield',
                            grow: true,
                            growMin: 150,
                            growMax: 300,
                            allowBlank: false,
                            name: 'brd_content',
                            fieldLabel: '내 용 '
                        },
                        {
                            xtype: 'textfield',
                            name: 'brd_input_user_nm',
                            allowBlank: false,
                            fieldLabel: '등 록 자'
                        },
                        {
                            xtype: 'displayfield',
                            fieldLabel: '입 력 일',
                            name: 'brd_input_date'
                        },
                        {
                            xtype: 'displayfield',
                            fieldLabel: '수 정 일',
                            name: 'brd_update_date'
                        }
                    ]
                }
            ]
        });
        this.callParent(arguments);
    }
});

 

좌측 그리드에서 사용할 Store 클래스를 작성하자. Store 클래스는 CRUD가 모두 가능하도록 플록시를 설정하자. actionMethod의 경우 서버쪽 코드에 따라 변경될 수 있으므로 필요 시 수정하도록 한다.

 

<리스트 5> Boards Store 클래스 코드

Ext.define('MyMvc.store.Boards', {
    extend: 'Ext.data.Store',
    autoLoad: false,
    model: 'MyMvc.model.Board',
    proxy: {
        type: 'ajax',
        actionMethods: {
            read: 'GET',
            create: 'POST',
            update: 'PUT',
            destroy: 'DELETE'
        },
        api: {
            read: '/board.do?boards',
            create: '/board.do?create',
            update: '/board.do?update',
            destroy: '/board.do?remove'
        },
        reader: {
            type: 'json',
            root: 'entitys',
            totalProperty: 'totalCount',
            messageProperty: 'message'
        },
        listeners: {
            exception: function (proxy, response, operation) {

            }
        }
    }
});

 

<리스트 5>의 Store 클래스에서 사용하는 모델 클래스를 작성하자. 이 클래스 또한 자체적으로 CRUD가 모두 가능하도록 <리스트 5>의 플록시 설정을 그대로 사용하도록 하자. 일반적으로 스토어에 설정된 플록시 정보는 게시물의 리스트를 저장하는 용도로 사용하고, 모델에 설정된 플록시 정보는 폼 정보와 연관지어 입력, 수정, 삭제 등을 수행하는 데 사용한다.

 

<리스트 6> Board 모델 클래스 코드

Ext.define('MyMvc.model.Board', {
    extend: 'Ext.data.Model',
    idProperty: 'brd_seq',
    fields: [
        {name: 'brd_seq', type: 'int'},
        'brd_title',
        'brd_content',
        'brd_category_cd',
        'brd_input_user_nm',
        'brd_input_date',
        {name: 'brd_read_cnt', type: 'int'},
        'brd_update_date'
    ],
    proxy: {
        type: 'ajax',
        actionMethods: {
            read: 'GET',
            create: 'POST',
            update: 'PUT',
            destroy: 'DELETE'
        },
        api: {
            read: '/board.do?boards',
            create: '/board.do?create',
            update: '/board.do?update',
            destroy: '/board.do?remove'
        },
        reader: {
            type: 'json',
            root: 'entitys'
        }
    }
});

게시판 클래스들이 모두 동적으로 로딩될 수 있도록 컨트롤러 클래스를 만들고 앞서 작성한 모든 클래스를 등록하자. 이를 구체적으로 구현하는 방법에 대해서는 다음 시간에 설명하기로 한다.

 

<리스트 7> Board 컨트롤러 클래스 코드

Ext.define('MyMvc.controller.Board', {
    extend : 'Ext.app.Controller',

    views : [ 'board.BoardMain', 'board.BoardList', 'board.BoardView' ],
    models: ['Board'],
    stores : ['Boards'],

    init : function(app) {
        this.control({
        });
    }
});

 

이제 Board 컨트롤러 클래스를 application.js 클래스에 등록해 전체 애플리케이션이 Board컨트롤러 클래스를 인식하도록 변경해준다.

 

<리스트 8> application.js 내부 컨트롤러 추가

Ext.define('MyMvc.Application', {
	name : 'MyMvc',

	extend : 'Ext.app.Application',

	views : [
	// TODO: add views here
	],

	controllers : [ 'Frame' , 'Board'],

	stores : [
	// TODO: add stores here
	]
});

 

애플리케이션을 재실행하면 <그림 1>과 같이 게시판 리스트와 게시물 보기 화면을 확인할 수 있다.

<그림 1> 게시판 애플리케이션 UI 구성

 

좌측 메뉴에서 선택된 게시판은 BoardMain 클래스에 의해 우측 중앙 영역에 보여지게 된다. 표면적으로는 각 메뉴에서 선택된 게시판은 동일하나 각각의 게시판 구분은 /json/programlist.json의 brd_number에 의해 달라지게 된다.

이는 <리스트 9>와 같이 BoardMain 클래스를 수정하면, 좌측 게시판 리스트를 클릭할 때 마다 게시판 아이디가 다르다는 것을 확인할 수 있다. 이 게시판 아이디에 의해 데이터베이스의 게시물을 가져오거나 입력할 수 있다.

 

<리스트 9> BoardMain 클래스 수정

Ext.define('MyMvc.view.board.BoardMain', {
    extend: 'Ext.container.Container',
    alias: 'widget.boardmain',
    layout : 'border',

    config: {
      brd_number : ''
    },
    initComponent: function () {
        var me = this;
        me.initConfig();

        .. 중략 ..
        me.callParent(arguments);
        me.on('render', function(){
           console.log("현재 게시판의 게시판 아이디는 " + me.getBrd_number());
        });
    }
})

 

<그림 2> 게시판 아이디 확인 결과

 

정리하며

이번 시간에는 게시판 애플리케이션의 UI를 구현해 봤다. 동일한 게시판 프로그램을 개발하고 해당 프로그램이 각기 다른 데이터를 표현하도록 하는 것이 핵심이다. 다음 시간에는 게시판의 CRUD 기능을 구현해보겠다. 지면 관계상 생략된 내용은 필자의 블로그를 통해 확인하자.

Posted by 베니94