게시판 그룹 리스트의 핵심은 데이터를 트리 구조로 표현하는 것이다.

즉, 리스트 기능을 표 형태가 아닌 트리 구조의 계층형으로 구현한다.

부서별 게시판들(공지사항, 토론방, QNA 등)로 구성하거나

하위 토론방을 주제별로 구분해서 사용할 수 있기 때문이다.

리스트를 트리로 구현하면서 신규, 읽기, 수정, 삭제를 하나의 페이지로 구현하고

신규, 읽기, 수정, 삭제가 발생할때 마다 트리를 매번 다시 생성하는 것은

비효율적이고 복잡해서

신규, 읽기, 수정, 삭제를 Ajax로 구현한다.


따라서 멀티 게시판 관리자 기능의 핵심은 트리 사용과 Ajax 활용이 된다.


개인적으로 사용해본 트리 라이브러리 중

dynatree가 무료(MIT) 중에서 가장 무난하다고 생각해서 사용한다.

자세한 사용법은 찾아보길 바라고 여기서는 관련된 내용만 다룬다.

http://wwwendt.de/tech/dynatree/doc/sample-select.html
http://jwgye.tistory.com/13

이외에 jstree나 bootstrap-treeview도 좋다고 생각한다.

    https://www.jstree.com/demo/
    https://github.com/jonmiles/bootstrap-treeview


다음 그림과 같이 트리 구조로 게시판 그룹이 있다고 하면

dynatree는 다음과 같이 JSON을 이용하여 트리 구조를 표현해서 넘겨만 주면 된다.

    {“key”: “1”, “title”: “공지사항”},
    {"key": "2", "title": "동아리", "isFolder": true,
        "children": [
            {"key": "3", "title": "기타"},
            {"key": "4", "title": "축구"}
            ]
        },
    {"key": "5", "title": "토론방"} 

Key는 그룹번호(bgno), title는 그룹 명(bgname)을 의미하고

2번 동아리는 자식(children)으로 기타(3)와 축구(4)를 가지는 트리 구조이다.

1과 5는 출력만 하면 된다.

이상과 같이 JSON 데이터를 생성하는 것이 트리 표현의 핵심인데

Java의 ObjectMapper를 이용하면 쉽게 처리할 수 있다.

ObjectMapper는 리스트(List)등의 구조체를 문자열로 변환하는 클래스인데

리스트의 항목이 클래스(VO)로 되어 있기 때문에

변환을 하면 JSON형태가 되게 된다.

클래스의 변수(메소드) 명이 JSON의 키로 생성되는 것이다.

변수의 값은 JSON의 키 값으로 생성된다.


따라서, 다음과 같이 TreeVO를 생성하면 쉽게 해결 된다.

dynatree에서 사용하는 key, title, isFolder, children로 클래스 멤버를 구성하고

데이터베이스에서 데이터를 가지고 올 때에도 이와 같이 가지고 오는 것이다.

public class TreeVO {
    private String key, title, parent;
    private boolean isFolder;
    private List children;
   
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    ~~ 생략 ~~

TreeVO.java

List로 지정된 children이 트리 변환의 핵심인데

ObjectMapper에 의해

List는 하위 JSON 집합으로 변환된다.


데이터 베이스에서 danatree의 JSON 키 생성구조(TreeVO)로 데이터 리스트를 조회하고

이 리스트를 계층 구조로 정리하고(children에 넣어주고)

ObjectMapper를 이용해서 JSON으로 변환하는 것이

게시판 그룹 리스트의 핵심 사항이다.


이 개념을 가지고 하나씩 구현해 본다.

먼저, 메인 페이지이자 게시판 그룹 리스트를 구현한다.

하나의 게시판 그룹이 추가될 때 마다

게시판 그룹 리스트 페이지를 새로 실행하고

게시판 그룹 트리를 다시 생성하는 것은 비효율적이고 직관성이 떨어져

이상의 그림과 같이

왼쪽에 리스트(트리), 오른쪽에는 입력/수정 화면이 하나로 묶어서 구현한다.

왼쪽의 트리에서 게시판을 선택하면

오른쪽에 해당 정보가 나오고 수정/삭제 할 수 있는 방식이다.

게시판에서는 각각의 화면이 다른 페이지로 있었지만

여기서는 모든 페이지가 하나에 구현된다.

따라서 Ajax가 많이 사용된다.


먼저, 게시판 그룹 리스트를 가지고 오는(selectBoardGroupList) 컨트롤을 작성한다.

@RequestMapping(value = "/boardGroupList")
public String boardList(ModelMap modelMap){
    List<?> listview   = boardSvc.selectBoardGroupList();

    TreeMaker tm = new TreeMaker();
    String treeStr = tm.makeTreeByHierarchy(listview);
   
    modelMap.addAttribute("treeStr", treeStr);
   
    return "board9/BoardGroupList";

BoardGroupCtr.java

public List<?> selectBoardGroupList(){
    return sqlSession.selectList("selectBoardGroupList");
}

BoardGroupSvc.java

<select id="selectBoardGroupList" resultType="gu.common.TreeVO" >
    SELECT BGNO 'KEY', BGNAME TITLE, BGPARENT PARENT
      FROM TBL_BOARDGROUP
     WHERE BGDELETEFLAG='N'
     ORDER BY BGNO 
</select> 

board9.xml

selectBoardGroupList를 이용해 가지고 온 데이터는

dynatree에 필요한 데이터 구조(KEY, TITLE)로 맞춘 TreeVO에 담겨 있다.

게시판 그룹의 부모(BGPARENT) 정보를 이용하여 계층 구조를 생성하게 된다.


Listview의 개수만큼(size) 하나씩(item=TreeVO) 반복하며

새로운 리스트(rootlist)에 하나씩 추가한다.

이때, 하나의 데이터(TreeVO)의 부모 정보(bgparent)가 NULL이 아니면

부모가 있다는 의미로

부모 데이터를 찾아서 (for ~~~ mtDO.getParent().equals(ptDO.getKey()))

children(List)에 내가 너의 자식이라고 추가(add)해 주는 방식으로 계층을 형성한다.

부모가 없는 경우는 최상위 노드(Root)를 의미하며

새로운 리스트(rootlist)에 추가하고 다음으로 넘어간다.

public class TreeMaker {
    public String makeTreeByHierarchy(List<?> listview){
        List<TreeVO> rootlist= new ArrayList<TreeVO>();
       
        for (Integer i=0; i<listview.size(); i++) {           
            TreeVO mtDO = (TreeVO)listview.get(i);           
           
            if (mtDO.getParent()==null) {
                rootlist.add(mtDO);
                continue;
            }   
             for (Integer j=0; j<listview.size(); j++) {
                 TreeVO ptDO = (TreeVO) listview.get(j);
                 if (mtDO.getParent().equals(ptDO.getKey())) {
                     if (ptDO.getChildren()==null) ptDO.setChildren(new ArrayList<Object>() );
                     List<TreeVO> a = ptDO.getChildren();
                     a.add(mtDO);
                     ptDO.setIsFolder(true);
                     break;
                 }
             }     
         }

        ObjectMapper mapper = new ObjectMapper();
        String str="";
        try {
            str = mapper.writeValueAsString(rootlist);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str;
    }

TreeMaker.java

계층 구조로 데이터가 정리되면

ObjectMapper로 JSON형태의 문자열로 변환하면 된다.

일반 리스트 데이터를 위와 같은 방식으로 변환하는 것은

자주 사용하는 것이라 common폴더에 생성하였다.

설명이 어려워서 이해되지 않는 경우

boardGroupList 컨트롤에서 사용하는 것처럼

makeTreeByHierarchy를 호출하는 것만 기억해도 된다.


이렇게 생성한 정보는 modelMap을 이용하여 JSP로 보낸다.

JSP 파일에서는 넘겨 받은 treeStr의 값을

다음과 같이 dynatree의 문법에 맞춰 넣어주면 트리가 생성된다.

#tree는 트리를 만들 대상 DIV의 ID이다.

$(function(){
    $("#tree").dynatree({
        children: <c:out value="${treeStr}" escapeXml="false"/>,
        onActivate: TreenodeActivate
    });
            fn_groupNew();
});
~~ 생략 ~~
<div id="tree"></div> 

BoardGroupList.jsp

Dynatree를 사용하기 위해서는

다음과 같이 CSS와 JS 파일을 포함해야 한다.

<link rel="stylesheet" href="js/dynatree/ui.dynatree.css" id="skinSheet"/>
<script src="js/jquery-2.2.3.min.js"></script>
<script src="js/jquery-ui.js"></script>
<script src="js/dynatree/jquery.dynatree.js"></script> 

BoardGroupList.jsp

Dynatree는 JQuery와 JQueryUI를 기반으로 제작되었기 때문에

위와 같이 JQuery도 지정해야 한다.


웹 페이지를 실행해 보면 이상의 그림과 같이 트리가 생성된 것을 볼 수 있다.

(데이터가 없어서 못 볼 수도 있다.)

onActivate는 트리의 노드가 선택되면 발생하는 이벤트로 

TreenodeActivate를 아직 구현하지 않아서 노드를 클릭하면 오류가 발생한다.











'Java > 게시판 9: 멀티 & 관리' 카테고리의 다른 글

1. 멀티게시판 관리자(그룹) 준비  (2) 2016.08.14
3. 게시판 그룹 읽기 / 삭제  (0) 2016.08.14
4. 게시판 그룹 쓰기와 수정  (0) 2016.08.14
5. 게시판 적용  (0) 2016.08.14

+ Recent posts