서버, 네트워크

대댓글과 답글 구성에 방법에 대한 생각

마리오64 2023. 6. 8. 23:59

최근에 제품을 리뉴얼 하면서 대댓글과 답글 쪽을 손볼일이 생겼다.

기존 그누보드 5 에서는 경로열거 방식을 사용하여 한자리씩 A~Z 까지 26개의 제한된 대댓글만 가능하다

 

요즘 사이트들을 보면 대댓글 대신 맨션을 쓰기도 하지만 대댓글로 한다고 해도 대댓글 26개제한은 너무적다.

 

대댓글 알고리즘들

대댓글, 답글은 크게 업데이트 방식과 업데이트 안하는 방식, 반업데이트 형으로 나뉜다

SQL 안티 패턴이라는 책을 보면 DB 를 이용해 계층형으로 데이터를 저장하는 5가지 방법이 소개되어있다.

항목별 쉽다 어렵다가 있는데 플젝진행하면서 성능을 측정하면서 각각이 뭔지 좀더 와닿았다

자식조회 : 페이징 없이 부모로부터 자식들을 전부 호출하는것

트리조회: 트리조회 페이징을 하거나 중간부터 조회할 때 트리조회가 필요하다

삽입 : 끝이나 중간에 대댓, 답글로 삽입

삭제 : 동일

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

 

인접목록:

부모글 id 를 자식글에 저장하여 하나의 부모id 를 참조하는 자식들을 조인하거나 각 단계별로 찾아야한다.

단점: 해보니까 페이징이문제다 저 표에보면 트리조회가 어렵다고 하는데 페이지를 나누게 되면

성능을 희생시키지 않고서는 자식을 조회하기 불가능에 가깝다

각 댓글마다 자신의 id 를 참고하고있는 자식들을 다 쿼리해야하는데 댓글이 100개면 100번 쿼리해야한다

n+1 문제이기도 하다.

설령 자식들이 있는것만 한다고해도 미리저장해야하고 최악의 경우 n 개의 댓글에 전부 대댓이 있다면 n 번 쿼리를 해야하는것이다.

n+1 문제를 해결하려면 페이징이 거의 불가능하다 (where not in 으로 조회한것들의 id 를 보내는것도 생각했지만 너무많아지고 사용자가 중간에 1p 에서 6p 로 건너뛴다 던가하면 무용지물...)

결론: 비추

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

재귀적 쿼리

mysql 의 경우 8.0 부터 지원한다.

DBMS 에서 내부적으로 뷰 같은 임시 테이블을 생성해서 재귀적 정렬을 해준다

페이징 시에도 문법적으로나 사용법은 단순한데...  한페이지에 보여주는게 많으면서 사용자수가 많으면 DB 부하가 심했다

결론: 페이지뷰가 적으면 그럭저럭이다

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

경로열거

DBMS 에서 아스키 코드가 정렬되는 점을 이용한다

각 단계별로 몇자리를 할지 정해서 경로를 적는다

각 단계별 자리수만 맞는다면 order by로 만 정렬이 가능하다.

 

3자리씩 끊어서 저장한다고 했을때

000 ~ ZZZ 36진수를 이용하여 각단계에 최대 46,656 까지 저장가능하다

 

장점: 정렬이 간단하다, 부모글, 자식글 찾기도 단순

단점은 대댓글/답글의 깊이가 깊어질 때 문자열이 길어지므로 인덱스를 생각하면 단계제한이 필요하다.

mysql 8.0 , maria DB 10.4 는 767 바이트의 인덱스를 지원하므로  utf8mb4 에서 47단계까지 저장가는하다.

 

중첩집합.

중첩집합은 처음부터 이진트리를 구조로 저장하여 조회가 아주빠르다

 

장점: 이진트리라서 읽기가 아주빠르다.

단점: 표에 나온건처럼 삽입시에 삽입되는 순서를 기점으로 하위 댓글 트리의 트리를 

다시 계산해서 번호를 업데이트를 해야한다.

결론:  읽기위주인 경우 매우빠르다 댓글다는건 글작성 후 길어야 3~4일이고 조회가 더 많은 사이트면 적합할것이다.

대게의 댓글들은 삭제해도 삭제되었다는 표시만하기때문에 삭제가 어렵다는건 단점이 아닐것이다.

 

클로저 테이블

클로저 테이블은 생소했는데 두개의 테이블에 하나는 댓글을 다른하나는 순서쌍을 저장한다

원리를 보면 댓글부모 자식관계를 행렬로 저장한다 때문에 n^2 으로 저장행이 증가한다.

그래프를 바로읽기때문에 읽기 빠르다

결론: 비추, 댓글이 많이 달리는 사이트의 경우 테이블에 데이터가 너무 늘어난다.