hotamul의 개발 이야기

대댓글 기능 데이터 모델링 #1 (Adjacency List) 본문

Dev./DB

대댓글 기능 데이터 모델링 #1 (Adjacency List)

hotamul 2024. 1. 3. 00:11

Tree data structure illustration

사용자들이 댓글을 달고 서로에게 대답하면서 토론 스레드를 만들 수 있는 서비스를 개발할 때 각 댓글들이 어떤 댓글의 답변인지 알 수 있도록 아래와 같이 parent_id를 이용해서 간단하게 Comments 테이블을 구성할 수 있다.

CREATE TABLE Comments (
  comment_id SERIAL PRIMARY KEY,
  parent_id BIGINT UNSIGNED,
  comment TEXT NOT NULL,
  FOREIGN KEY (parent_id) REFERENCES Comments(comment_id)
);

Adjacency List Entity-Relationship Diagram

그런데 딱 봐도 위와 같은 테이블 구성은 하나의 SQL 쿼리로 모든 댓글 연결들을 조회하는 것이 어려워 보인다.

바로 자식 댓글까지는 쉽게 얻을 수 있지만, 댓글 스레드는 무한히 생성될 수 있기 때문에 한 스레드의 모든 댓글을 조회하려면 아래와 같이 여러 번의 SQL 쿼리를 실행해야 한다.

SELECT c1.*, c2.*, c3.*, c4.*
  FROM Comments c1 -- 1st level
  LEFT OUTER JOIN Comments c2
    ON c2.parent_id = c1.comment_id -- 2nd level
  LEFT OUTER JOIN Comments c3
    ON c3.parent_id = c2.comment_id -- 3rd level
  LEFT OUTER JOIN Comments c4
    ON c4.parent_id = c3.comment_id; -- 4th level

위 쿼리는 점점 더 깊은 수준의 comment를 column에 추가하고 있는데 이는 매우 비효율적이고 어색해 보인다. 그리고 COUNT()와 같은 aggregate 연산 또한 어려워 보인다.

 

여러 번의 SQL 쿼리를 실행하거나 연속적인 LEFT OUTER JOIN을 이용하는 것 대신에, 모든 댓글을 한 번에 조회해서 메모리 로드하고 트리 형태로 다시 조립/정렬하는 방법도 있다. 하지만 댓글이 수백 수천 개씩 생성된다면 메모리에 모든 댓글을 조회해서 조립/정렬하는 것은 쉽지 않을 것이다.

 

그러면 위 방법이 무조건적으로 틀린 것이냐? 그것은 아니다.

Adjacency Lists 설계는 종종 사용되고 어떠한 경우에는 적절한 방법일 수 있다. Adjacency Lists 설계의 장점은 주어진 노드의 부모, 자식 노드를 직접 검색할 수 있다는 것이다. 그리고 쉽게 레코드를 삽입할 수 있다.

 

일부 RDBMS에서는 Adjacency Lists 형식으로 저장된 정보를 쉽게 다루기 위해 WITH 키워드를 이용한 Common Table Expression(공통 테이블 표현식)를 지원한다.

WITH CommentTree
       (comment_id, post_id, parent_id, author, comment, depth)
  AS (
     SELECT *, 0 AS depth FROM Comments
      WHERE parent_id IS NULL
      UNION ALL
     SELECT c.*, ct.depth+1 AS depth FROM CommentTree ct
       JOIN Comments c ON (ct.comment_id = c.parent_id)
  )
SELECT * FROM CommentTree WHERE post_id = 1234;

Microsoft SQL Server 2005, Oracle 11g, IBM DB2, PostgreSQL 8.4에서는 위처럼 CTE을 사용하여 재귀적인 쿼리를 작성할 수 있다. MySQL, SQLite,... 는 아직 이러한 문법을 지원하지 않지만 Adjacency Lists를 사용하는 것이 RDBMS 브랜드에 따라 그렇게까지 제한적으로 보이지는 않는다.

 

그럼에도 댓글 스레드를 다루는 더 효율적인 방법이 뭐가 있을까?

 

'Dev. > DB' 카테고리의 다른 글

대댓글 기능 데이터 모델링 #2 (Path Enumeration)  (0) 2024.01.03
[CS - DB] Isolation level of Transactions  (0) 2022.12.15
Comments