Skip to content

Conversation

@sunwon12
Copy link
Owner

@sunwon12 sunwon12 commented Oct 16, 2025

무한 대댓글 시스템 설계 - 최종 정리


설계 핵심 목표

  • 댓글/대댓글 무한 트리 구조 지원
  • 읽기·쓰기 모두 빠른 성능
  • DFS 순서 기반 페이지네이션 지원
  • 실무 서비스 수준의 단순성 + 유지보수성 확보

트리 구조 저장 방식 후보군 비교

모델 구조 조회 복잡도 삽입 복잡도 장점 단점
Adjacency List 부모 ID만 저장 O(depth) (재귀 필요) O(1) 구현 가장 단순, 변경 쉬움 트리 전체 조회 비효율적, N+1 문제
Materialized Path /1/2/3 형태의 경로 문자열 O(1) (LIKE로 조회) O(1) 구현 쉬움, 정렬/조회 빠름 부모 이동 시 하위 전체 path 수정 필요
Nested Set Model lft, rgt 값으로 범위 표현 O(1) (범위 쿼리) O(n) 서브트리 조회 최강 삽입/삭제 시 대량 UPDATE 발생
depth + position 인덱스 걸기 ORDER BY depth, position O(1) O(1) 구현 쉬움, 정렬/조회 빠름 서브 댓글(하위 트리)의 순서를 보장할 수 없음
(DFS 순서 불가능, 같은 depth 내 정렬만 가능)

❌ 채택하지 않은 이유 요약

  • Adjacency List → 조회 성능 최악 (재귀, N+1 쿼리)
  • Materialized Path → 부모 이동 시 하위 path 전부 수정 필요
  • Nested Set → 댓글 추가 시 대량 UPDATE (쓰기 O(n))

✅ 최종 채택: Sort Key 기반 Materialized Path (단일 테이블)

Materialized Path의 장점을 가져오되,

정렬 안정성과 DFS 순서를 보장하는 sort_key 를 추가해 개선.


동작 방식

1. sort_key = DFS 순서를 표현하는 문자열

  • 각 댓글의 위치를 경로 기반 문자열로 표현
  • 부모의 sort_key 뒤에 /0001, /0002 식으로 자식 순서를 이어붙임

예시:

0001                  ← 댓글1
0001/0001             ← 댓글1의 자식
0001/0001/0002        ← 댓글1의 자식의 두 번째 자식

ORDER BY sort_key 만으로 DFS 순서 정렬 및 페이지네이션 가능


2. position + depth 조합으로 관리 단순화

  • position: 같은 부모 아래에서의 순서 (4자리 패딩)
  • depth: 댓글 계층 깊이 (최대 50단계 제한)
  • sort_key = 부모.sort_key + '/' + position

예시:

id parent_id depth position sort_key
1 NULL 0 1 0001
2 1 1 1 0001/0001
3 2 2 1 0001/0001/0001
4 2 2 2 0001/0001/0002

3. DFS 순서 페이지네이션

  • 첫 페이지

    GET /api/comments?postId=1&size=10

  • 다음 페이지

    GET /api/comments?postId=1&lastKey=0001/0003&size=10

  • 쿼리:

    SELECT * FROM comments
    WHERE post_id = :postId
    AND sort_key > :lastKey
    ORDER BY sort_key
    LIMIT :size;
    

단일 인덱스 정렬로 정렬·페이징 모두 해결


sort_key 설계 이슈 및 해결

자리수 오버플로우

  • String.format("%08d", id) 사용 시 9자리 이상 깨짐

    "%016d" (16자리 패딩) 으로 해결

깊은 depth로 인한 문자열 폭발

  • depth 10,000 × 16자리 = 160,000자 → VARCHAR 한계 초과

    depth 최대 50 제한 + position 4자리 고정

최종 길이: 4 * 50 + 49 = 249자

→ 충분히 안전하고, 인덱스 사용 가능


최종 데이터 구조 예시

id post_id content parent_id depth position sort_key
1 100 댓글1 NULL 0 1 0001
2 100 댓글2 1 1 1 0001/0001
3 100 댓글3 2 2 1 0001/0001/0001
4 100 댓글4 2 2 2 0001/0001/0002
5 100 댓글5 3 3 1 0001/0001/0001/0001

🧾 요약 정리

항목 설명
트리 구조 저장 방식 Sort Key 기반 Materialized Path
조회 복잡도 O(1) (ORDER BY sort_key)
삽입 복잡도 O(1) (부모 sort_key 기반 문자열 계산)
삭제 복잡도 O(1) (LIKE 쿼리로 하위 전체 삭제 가능)
장점 구조 단순, 정렬 쉬움, 페이지네이션 용이
단점 부모 변경 시 하위 sort_key 수정 필요
적합한 경우 댓글/대댓글처럼 삽입 잦지만 이동 거의 없는 구조

결론

  • 읽기 성능: DFS 정렬과 페이징을 ORDER BY sort_key 로 해결
  • 쓰기 성능: 부모의 sort_key만 읽으면 바로 계산 가능 (O(1))
  • 단순성과 유지보수성 모두 확보

@sunwon12 sunwon12 self-assigned this Oct 16, 2025
@sunwon12 sunwon12 merged commit 428d75f into main Oct 16, 2025
@sunwon12 sunwon12 changed the title Materialized Path 무한 댓글 조회 [1] Materialized Path 무한 댓글 조회 Oct 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants