깊이 있는 댓글 시스템
인터넷 서비스를 이용하면서 누구나 한번쯤 댓글 시스템을 이용해 본 적이 있을 것이다. 사용법이 너무나 간단하여 쉽게 제작할 수 있을 것 같지만, 실제로 만들어보면 그렇게 만만한 시스템이 아니란 것을 알게 된다.
여기서 생각해 볼 댓글 시스템은 제목 그대로 깊이 있는 댓글 시스템
이다. 단순히 시간 순서대로 정렬되어 한줄 한줄 표현되는 댓글이 아닌, 댓글에 대한 댓글(자식 댓글)을 계속해서 추가할 수 있는 깊이의 개념이 있는 댓글 시스템에 대하여 이야기 하고자 한다. 이해를 돕기 위하여 최대한 심플한 내용으로 설명을 하겠지만, 이를 응용하여 상용 시스템에서도 충분히 사용할 수 있으리라 생각한다.
댓글 시스템을 만들기 위해서는 댓글 데이터를 다루는 데이터베이스 부분과 이를 처리하는 서버 스크립트 부분 그리고 저장된 데이터를 화면에 표시하고 댓글을 입력했을 때 적절한 위치에 표시되게 하는 프론트엔드 부분이 어우러져야 하는데, 이번 글에서는 데이터베이스의 측면에서만 생각해 보기로 한다.
프론트엔드 부분을 간단하게 처리하기 위하여 댓글을 입력할 때 마다 화면을 갱신하는 방법으로 처리할 수도 있겠지만, JavaScript 를 이용하여 필요한 부분의 DOM 을 갱신하는 방법을 주로 사용하기 때문에 이 부분은 기회가 있으면 설명하기로 한다. 요즘엔 React 나 Vue 를 이용하여 Reactive 하게 표현하므로 관련 지식이 필요할 경우도 있다.
데이터베이스 테이블 설계
깊이 있는 댓글 시스템의 기본적인 테이블 구조는 다음과 같다.
- id: 댓글의 고유 Id
- comment: 댓글의 내용
- group_comment_id: 댓글과 그에대한 자식 댓글들을 묶기 위한 최상위 댓글 Id.
- parent_comment_id: 자식 댓글의 부모 댓글 Id. 최상위 댓글은 부모 댓글이 없으므로 NULL 값을 갖게된다.
- depth_no: 댓글의 깊이를 표현하는 값. 정수 값으로 기호에따라 0부터 시작할 지 1부터 시작할 지 정하면 되겠다. 여기에서는 0부터 시작하는 것으로 한다. 예를들어 최상위 댓글은 0, 최상위 댓글의 자식 댓글은 1, 그 댓글의 자식 댓글은 2, … 가 되는 식이다.
- order_no: 댓글의 정렬 순서를 정하는 값. 정수 값으로 기호에따라 0부터 시작할 지 1부터 시작할 지 정하면 되겠다. 여기에서는 1부터 시작하는 것으로 한다. 예를들어 최상위 댓글은 0, 최상위 댓글의 첫번째 자식 댓글은 1, 최상위 댓글의 두번째 자식 댓글은 3, 최상위 댓글의 첫번째 자식 댓글의 자식 댓글은 2, … 가 되는 식이다. 글로 표현하면 복잡하지만 계속해서 설명하므로 이해하는데 문제는 없을 것이다.
댓글 입력
우선 첫번째 댓글을 달아보자.
데이터 베이스 상에서 직접 댓글을 입력하는 방식으로 진행한다. 일반 유저가 댓글을 하나씩 입력하는 상황을 상상하면서 따라 읽으면 이해하기 쉽지 않을까 한다.
첫번째 댓글
어느 글에 첫번째 댓글이 달렸다. 자식 댓글이 없는 첫번째 최상위 댓글이다.
두번째 댓글
자식 댓글이 없는 두번째 최상위 댓글이다. 두번째 최상위 댓글의 group_comment_id
가 2로 된 것에 주목하기 바란다. 최상위 댓글은 해당 댓글의 Id 가 group_comment_id
값이 된다. 이 값을 이용하여 댓글의 댓글을 함께 묶어 표현하게 된다.
세번째 댓글
이제부터 상황이 달라지기 시작한다.
다음 사람이 1st
댓글을 보고 거기에 대한 의견을 달았다. 즉, 세번째 댓글은 1st
댓글의 댓글이다.
네번째 댓글
다음 사람이 1st
댓글에 대한 두번째 댓글이 달렸다.
다선번째 댓글
1st
의 자식 댓글 1st - 1st
에 대하여 자식 댓글 1st - 1st - 1st
이 달렸다.
댓글 데이터는 시간 순서대로 쌓이기 때문에 이렇게 저장이 되는데, 이 데이터는 보는 이로 하여금 관련된 자식 댓글을 쉽게 인식할 수 있도록 연관성을 보여주기 위해 다음과 같이 표현되어야 한다.
실제로 표시되어야 할 댓글 순서
한결 쉽게 이해할 수 있는 댓글의 순서로 표현 되었다.
이렇게 표현하는 쿼리는 다음과 같다.
연관성을 쉽게 인식 할 수 있도록 묶어서 보여주는 SQL Query
SELECT * FROM comments ORDER BY group_comment_id, order_no
위와 같이 댓글 데이터가 구성이 되어 있다면 이렇게 간단한 쿼리문으로 깊이가 있는 댓글을 구현할 수 있다. 적절하게 index 를 구성해 주면 아무리 많은 양의 댓글이 있다 하더라도 문제없이 표시될 것이라 생각된다.
체크 포인트
여기까지 읽으면서 느꼈겠지만 깊이가 있는 댓글을 표현하는 쿼리 자체는 비교적 간단하다. 그 대신, 입력된 댓글을 데이터베이스에 저장할 때 group_comment_id
와 order_no
를 알맞게 지정해 줘야 한다는 것을 알 수 있다. 사실 댓글 기능을 제작하는데 있어서 group_comment_id 와 order_no 를 찾아내는것이 프로그래밍의 대부분을 차지한다. 그리고 이 쿼리에서 parent_comment_id
와 depth_no
가 사용되지 않는 것 처럼 보이지만 이 값들은 댓글을 화면에 표시할 때 중요한 역할을 하게 되므로 마찬가지로 알맞게 지정해 줘야 한다.
결국, 댓글을 데이터베이스에 저장할때, 어느 부분에 저장되어야할 지를 확인해서 group_comment_id, parent_comment_id, depth_no 그리고 order_no 값을 적절하게 지정하는 것이 깊이있는 댓글의 기본이라 할 수 있겠다.
이들 값을 지정하는 방법은 다음글에서 설명하도록 한다.
Responses
Leave a response to @richard