- JAVA 스터디 중 스터디장이 댓글 게시판 숙제로 구글 중 내가 적용한 알고리즘(까먹을까봐-_-)


계층형 게시판을 위한 테이블의 구성 및 알고리즘은 워낙 다양하기 때문에 특별히 정해진 솔류션은 존재하지 않습니다.
여기서는 많은 책자에서 소개되어 있는 간단한 계층형 게시판의 구조와 알고리즘에 대해서 알아봅니다.

 

설명을 위해 테이블에는 다음과 같은 컬럼들만 있다고 가정합니다. 실제로는 더 많겠죠.

No : 글번호(Primary Key)
Title : 글제목
Grp : 같은 주제를 갖는 게시물의 고유번호. 부모글과 부모글로부터 파생된 모든 자식글은 같은 번호를 갖습니다.
Seg : 같은 그룹내 게시물의 순서
Lvl : 같은 그룹내 계층

 

게시판에 첫번째 글이 올라오면, 테이블에는 다음과 같은 정보가 저장됩니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 1, '안녕하세요'     ,   1,   1,   0

====================================

새 글에서 No는 시퀀스로부터 받아온 값, Grp는 No와 동일한 값, Seq는 1, Lvl은 0입니다.

 

두번째 글과 세번째 글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0

====================================

 

첫번째 글에 답글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 4, '  반가워요     ',   1,   2,   1 

====================================

답글의 경우, Grp는 부모글의 Grp 값, Seq는 부모글의 Seq+1, Lvl은 부모글의 Lvl+1이 됩니다.

 

첫번째 글의 답글에 답글이 올라옵니다. 즉, 네번째 글의 답글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 4, '  반가워요     ',   1,   2,   1 
 5, '    감사합니다 ',   1,   3,   2

====================================

 

첫번째 글의 두번째 답글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 6, '  환영합니다   ',   1,   2,   1 
 4, '  반가워요     ',   1,   2,   1 
 5, '    감사합니다 ',   1,   3,   2

====================================

 

여기서, 두번째 답글이 첫번째 답글보다 먼저 표시되려면, 동일한 그룹 번호에 있으면서 부모의 Seq 번호보다 큰 게시물의 Seq 번호를 모두 1만큼 증가시킵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 6, '  환영합니다   ',   1,   2,   1
 4, '  반가워요     ',   1,   3,   1
 5, '    감사합니다 ',   1,   4,   2

====================================

 

여섯번째 게시물에 답글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 6, '  환영합니다   ',   1,   2,   1
 7, '    감사합니다 ',   1,   3,   2
 4, '  반가워요     ',   1,   3,   1
 5, '    감사합니다 ',   1,   4,   2

====================================

 

마찬가지로 동일한 그룹 번호에 있으면서 부모의 Seq 번호보다 큰 게시물의 Seq 번호를 모두 1만큼 증가시킵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 6, '  환영합니다   ',   1,   2,   1
 7, '    감사합니다 ',   1,   3,   2
 4, '  반가워요     ',   1,   4,   1
 5, '    감사합니다 ',   1,   5,   2

====================================

 

검색 할 때는 Grp를 내림차순으로 Seq를 오름차 순으로 정렬하면 됩니다. 인덱스는 기본키와 Grp+Seq의 복합 인덱스를 설정하면 됩니다.

 

실제 오라클에서 테이블을 구성하고 검색해봅니다.

 

drop table qnaboard;

 

create table qnaboard
(no number,
 title varchar2(100),
 contents varchar2(4000),
 writer varchar2(20),
 wdate date,
 grp number,
 seq number,
 lvl number);

 

drop sequence qnaboard_no_seq;

 

create sequence qnaboard_no_seq
start with 1
increment by 1;

 

create index qnaboard_no_idx on qnaboard(no) reverse;

 

alter table qnaboard
add constraint qnaboard_no_pk primary key (no);

 

create index qnaboard_grp_seq on qnaboard(grp desc, seq asc);

alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

 

첫번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '안녕하세요', null, '길동', sysdate, qnaboard_no_seq.currval, 1, 0);

 

두번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '날씨가 맑습니다', null, '철수', sysdate, qnaboard_no_seq.currval, 1, 0);

 

세번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '모임이 있습니다', null, '영희', sysdate, qnaboard_no_seq.currval, 1, 0);

 

네번째 게시물 입력 - 첫번째 게시물의 답글

답글이 올라오는 경우에는 답글에 부여 할 seq를 먼저 확보해줍니다.
update qnaboard
set seq=seq+1
where grp=1 and seq>1;

 

insert into qnaboard
values(qnaboard_no_seq.nextval, '반가워요', null, '만수', sysdate, 1, 2, 1);

 

다섯번째 게시물 입력 - 네번째 게시물의 답글
update qnaboard
set seq=seq+1
where grp=1 and seq>2;

 

insert into qnaboard
values(qnaboard_no_seq.nextval, '감사합니다', null, '길동', sysdate, 1, 3, 2);

 

여섯번째 게시물 입력 - 첫번째 게시물의 두번째 답글
update qnaboard
set seq=seq+1
where grp=1 and seq>1;

 

insert into qnaboard
values(qnaboard_no_seq.nextval, '환영합니다', null, '찬호', sysdate, 1, 2, 1);
 
일곱번째 게시물 입력 - 여섯번째 게시물의 답글
update qnaboard
set seq=seq+1
where grp=1 and seq>2;

 

insert into qnaboard
values(qnaboard_no_seq.nextval, '감사합니다', null, '길동', sysdate, 1, 3, 2);

 

게시판을 검색하는 경우, grp로 내림차순, seq로 오름차순으로 정렬하면 됩니다.
select case when lvl=0 then no
            when lvl>0 then null end no
, rpad('+', lvl, '-')||title title
, writer
, wdate
from qnaboard
order by grp desc, seq;


   NO TITLE                WRITER     WDATE
----- -------------------- ---------- -------------------
    3 모임이 있습니다      영희       2007-09-15 19:54:00
    2 날씨가 맑습니다      철수       2007-09-15 19:53:55
    1 안녕하세요           길동       2007-09-15 19:53:50
      +환영합니다          찬호       2007-09-15 19:54:21
      +-감사합니다         길동       2007-09-15 19:54:26
      +반가워요            만수       2007-09-15 19:54:08
      +-감사합니다         길동       2007-09-15 19:54:15

+ Recent posts