| 최초 작성일 : 2021-09-25 | 수정일 : 2021-10-05 | 조회수 : 468 | 
이 게시글은 아래와 같은 구조를 구현하기 위한 방법을 알려드립니다
글을 기준으로 알려드리지만
결국 댓글, 카테고리 도 같은 구조로 구현 가능합니다.
이름만 변경하시면 됩니다
글 => 답글 => 답답글 => 답답답글....
댓글 => 대댓글 => 대대댓글 => 대대대댓글....
카테고리 => 2단계 카테고리 => 3단계 카테고리....원글 : http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
구글 번역글 : http://hmjkor.tistory.com/472
번역글 : https://wooriworld2006.tistory.com/417
저는 원글과 구글 번역글을 참고해서 이 게시글을 작성했습니다
글 생성시 먼저 자신의 lft, rgt 정보가 필요합니다.
다만 lft = rgt - 1
SELECT MAX(rgt) AS max_rgt
FROM post;rgt = max_rgt + 1 입니다rgt, lft를 가지고 게시글을 생성합니다
먼저 부모 글을 조회합니다.
SELECT *
FROM post AS parent
WHERE post_id = {parent_id}rgt = parent.rgt + 2 입니다
생성하기전에 게시글이 들어갈 자리를 비워야합니다
부모글의 오른쪽 글들을 한칸씩 옮길 필요가 있습니다Transaction을 이용합니다
UPDATE post
SET lft=lft+2 
WHERE ltf > {parent.rgt}UPDATE post
SET rgt=rgt+2 
WHERE rgt >= {parent.rgt}rgt, lft를 가지고 게시글을 생성합니다
글 제목, 내용 수정시 크게 주의할 사항은 필요하지 않다.
글 수정시 자식 존재시 수정 불가능 기능이 필요하시면
자식 글 조회 후 처리하시면 됩니다.
글 삭제시 자식글 전체 삭제 또는 자식 존재시 삭제 불가능 기능이 필요하시면
자식 글 조회 후 처리하시면 됩니다.
삭제 글, 오른쪽 글들의 lft, rgt의 변경을 원하신다면 아래를 참고해주세요
(삭제된 post의 오른쪽 글을 왼쪽으로 한칸 옮기는 기능)
UPDATE post
SET rgt = rgt - 
 (CASE 
 WHEN (rgt > {post.rgt}) THEN 2 
 WHEN (lft > {post.lft} AND rgt < {post.rgt}) THEN 1 
 ELSE 0 END)UPDATE post
SET lft = lft - 
 (CASE 
 WHEN (lft > {post.rgt}) THEN 2
 WHEN (lft > {post.lft - 1} AND rgt < {post.rgt - 1})
 THEN 1 
 ELSE 0 END)MySQL과 Javascript를 기준으로 작성합니다
게시글 정렬시 원글끼리의 정렬방법과 자식끼리의 정렬방법이 다릅니다.
보통 일반적인 게시판은 아래와 같이 정렬됩니다.
| depth | 제목 | 작성일 | 
|---|---|---|
| 1단계 | 제목 | 01/07 | 
| 1단계 | 제목 | 01/06 | 
| 1단계 | 애국가 | 01/02 | 
| 2단계 | [답글]동해물과 | 01/03 | 
| 2단계 | [답글]백두산이 | 01/04 | 
| 2단계 | [답글]마르고 | 01/05 | 
| 1단계 | 제목 | 01/01 | 
위 예시를 살펴보면
1. 1단계(원글)는 최신글이 앞으로 정렬
2. 2단계(자식)는 최신글이 뒤로 정렬
정렬방법이 서로 다른걸 확인 할 수 있습니다.
SELECT *
FROM post
ORDER BY lft DESC;위와 같은 쿼리는 원글 정렬은 만족하지만 자식 정렬은 만족하지 못합니다
먼저 두가지 값이 필요합니다.max_depth : 최대 깊이max_count_per_depth : 단계당 최대 글 개수
두 값 모두 필수이며, 최대 크기 제한이 필요합니다
글 생성시 max_depth와 max_count_per_depth 를 체크해주세요
또한 게시글 전체 조회 기능을 막으시고page_num(현재 페이지 넘버)와 page_length(한 페이지 당 길이)를 필수값으로 사용해주세요
자식이 영원히 늘어날 수 없으며, 한번에 전체를 조회 할 수 없게 합니다.
위 4가지 값을 통해, 목록 조회시 필요한 offset과 limit을 구합니다 (MySQL기준)
만약 n개의 글이 필요하다면, 조회 방법은 다음과 같습니다.
function getExtraLength(page_num, page_length, max_depth, max_count_per_depth) {
  let start_index = max_depth * max_count_per_depth;
  let offset = (page_num - 1) * page_length;
  let limit = parseInt(limit) + extra_length;
  
  if (offset > extra_length) {
    start_index = extra_length;
    offset = (offset - front_minus) || 0;
    limit += extra_length;
  }
  
  return {
    offset,
    limit,
    start_index,
  }
};여분이 포함된 게시글을 조회합니다
SELECT *
FROM post
ORDER BY lft DESC
LIMIT {limit}
OFFSET {offset};결과값을 results라고 부르겠습니다.
results를 부모-자식 관계에 맞게 lft와 rgt를 통해 정렬합니다
반복문과 조건문을 사용해주세요
end_index = (start_index + page_length) - 1results에서 start_index 부터 end_index 까지 게시글을 구합니다.
그 후 여분을 제거한 results 를 반환합니다