배경
시스템이 구축된 후 마케터와 광고주측은 특정 주제로 게시글을 만들고, 게시글에 댓글을 주고받으며 업무를 하게 되었다. 
댓글이 많이 달리게 되면서 가독성이 떨어지게 되었고, 대댓글에 대한 요구사항이 있어서 개발하게 되었다.



대댓글 기능

1. 프로젝트 개요

  • 목표: 게시판에서 대댓글(댓글의 댓글) 기능을 구현하여 계층적인 댓글 구조를 지원.
  • 특징:
    • parentIdx 컬럼을 이용해 부모 댓글과 대댓글 간의 관계를 명시.
    • 재귀 쿼리를 활용해 대댓글 구조를 조회.
    • 댓글과 대댓글이 적절히 정렬되도록 데이터 저장 및 조회 처리.

2. 데이터베이스 구조

  • 테이블명: treply
  • 주요 컬럼:
    • idx (int): 댓글 고유 식별자.
    • parentIdx (int): 부모 댓글의 idx. 최상위 댓글은 NULL 또는 
    • boardIdx 게시글의 고유 식별자 
    • content (nvarchar): 댓글 내용.
    • regid (varchar): 작성자 ID.
    • 기타 정보: regdate(작성일), updateDate(수정일), filename(첨부파일명) 등.

3.접근법과 고민

  • 문제 상황:
    기존 댓글 시스템에서는 단순히 댓글만 표시할 수 있었고, 대댓글(댓글의 댓글) 기능을 구현하려면 각 댓글의 계층적 관계를 명확히 나타낼 방법이 필요했다.

    • 대댓글이 여러 단계로 깊어질 경우, 이를 어떻게 효율적으로 저장하고 조회할지에 대한 명확한 설계가 없었음.
    • 데이터베이스의 기존 구조는 이러한 계층적 데이터를 처리하기에 적합하지 않았음.
  • 아이디어 도출 과정:
    "부모-자식 관계로 연쇄적으로 연결된 트리 구조"를 떠올려 parentIdx라는 컬럼을 추가하여 부모 댓글을 참조하도록 설계

    • 이 구조를 사용하면 댓글과 대댓글 간의 관계를 단순하면서도 직관적으로 표현할 수 있을 것으로 판단.
    • 트리 구조의 계층적 특성을 SQL 재귀 쿼리로 활용하여 데이터를 조회.
  • 적용 결과:

    • parentIdx를 활용한 데이터 구조를 통해 댓글과 대댓글의 관계를 직관적으로 관리.
    • CTE(Common Table Expression)를 사용해 SQL에서 재귀적으로 데이터를 조회, 추가적인 서버 로직 없이 대규모 데이터를 효과적으로 처리.



4. 재귀 쿼리 구조

  • 쿼리 개요:
    • CTE(Common Table Expression)를 활용해 계층 구조를 재귀적으로 조회.
    • parentIdx가 NULL 또는 0인 최상위 댓글을 앵커로 설정.
    • 대댓글은 부모 댓글의 idx를 기준으로 연결.



WITH TREE_QUERY AS (
    -- 앵커 멤버: 최상위 댓글 조회
    SELECT
        idx, parentIdx, content, regid, logintype, regdate, updateDate, filename, filesize, updateflag, emailflag, isOpBoard,
        CONVERT(VARCHAR(255), idx) AS sort,
        CONVERT(int, idx) AS FirstValue
    FROM [treply]
    WHERE (parentIdx IS NULL OR parentIdx = 0) AND boardidx = @boardidx

    UNION ALL

    -- 재귀 멤버: 대댓글 연결
    SELECT
        B.idx, B.parentIdx, B.content, B.regid, B.logintype, B.regdate, B.updateDate, B.filename, B.filesize, B.updateflag, B.emailflag, B.isOpBoard,
        CONVERT(VARCHAR(255), C.sort + '-' + CONVERT(VARCHAR(255), B.idx)) AS sort,
        CONVERT(int, CASE
                        WHEN CHARINDEX('-', C.sort) > 1 THEN LEFT(C.sort, CHARINDEX('-', C.sort) - 1)
                        ELSE C.sort
                    END) AS FirstValue
    FROM [treply] B
    INNER JOIN [TREE_QUERY] C ON C.idx = B.parentIdx
    WHERE B.boardidx = @boardidx
)
-- 최종 출력
SELECT *
FROM TREE_QUERY
WHERE 1 = 1 {0}
ORDER BY FirstValue ASC, sort ASC;




5. 기술적 선택 및 이유

  1. parentIdx 사용:
    • 계층 구조를 간단히 표현하고, 부모-자식 관계를 명확히 정의.
  2. 재귀 CTE 사용:
    • 계층적 데이터 처리를 SQL 레벨에서 효과적으로 수행.
    • 별도의 서버 로직 없이 SQL로 처리 가능.
  3. 정렬 구현:
    • sort 컬럼: 댓글의 계층 구조를 나타내기 위해 문자열 형태로 계층 경로 생성("1-2-5" 등).
    • FirstValue: 최상위 댓글 기준 정렬을 위한 보조 컬럼.

6. 주요 결과

  • 댓글과 대댓글이 계층적으로 정렬되어 출력.
  • UI에서 계층 구조를 쉽게 표시 가능.
  • 대규모 데이터를 효율적으로 처리 가능.

7. 구현 의의

  • 효율성: 서버 로직 없이 SQL에서 모든 계층 구조를 처리.
  • 확장성: 대댓글 기능뿐만 아니라 다양한 계층적 데이터 처리에 적용 가능.
  • 정렬 보장: 정렬 방식(FirstValue, sort)으로 데이터 표시 일관성 유지.

8. 개선 및 확장 가능성

  • 성능 최적화: 대규모 데이터에서 실행 속도를 개선하기 위해 인덱스 최적화.
  • 추가 기능: 요구사항이 있다면 댓글에 대한 좋아요/싫어요 기능 등 추가를 검토해볼 수도 있음.