오늘은 대댓글 게시판을 설계하는 방법에 대해서 정리 해보려고 하는데요.

참고로, UI나 코드를 중심으로 한 글은 아니지만, 

NoSQL인 Firebase의 Firestore를 사용하였을 때를 기준으로 테스트하고 작성해 보았기 때문에,

관계형 데이터베이스를 사용하는 경우는 조금 다를 수 있습니다.



1. 대댓글


보통 커뮤니티에서 아래와 같은 방식의 댓글을 많이 사용하는데요.

아래와 같은 구성을 하기위해서는 어떤부분들을 고민하고 해결해야 하는지 정리해 보겠습니다.


원글: 이것은 삼각함수를 이용하여 해결한 것입니다.


A댓글: 너무나 좋은 방법입니다.

-> C댓글: 저도 좋아 보이네요.

-> D댓글: 저도 A님과 같이 좋은 방법이라고 생각합니다.

B댓글: 저는 반대합니다.


먼저 DB에 대해서 고민해 보도록 하겠습니다.


댓글 Collection 에 넣을 필드를 표로 만들어 보면 아래와 같은데요.

꽤나 많은 요소들이 필요한 것 같지만, 

핵심요소는 reply_id, board_id, depth, bundle_id, bundle_order정도 로 그리 많지 않습니다.


 reply_id

 string


 글아래에 바로 댓글이 달리는 Q&A게시판 같은 경우는 

 id를 따로 두고, board_num을 100개든 500개든 잡아서,

 댓글을 달 수 있도록 해주어야 하겠지만,

 커뮤니티 게시판의 경우 각 글에 들어가서 보는 댓글만 필요하므로,

 id자체를 unique한 키로 사용할 수 있습니다. 


 board_id

 string

 댓글이 달린 게시판의 id

 depth

 number


  답글의 깊이 또는 위치를 정합니다.

  원댓글은 0, 대댓글은1로 표현하면 됩니다.


 bundle_id

 number


 댓글과 대댓글을 하나로 묶어줄 id입니다.

 글이 삭제 될 경우(실제로는 is_deleted로 숨기는 것), 

 댓글까지 삭제시켜야 하므로, 이때 필요한 id입니다. 

 parent_id라고도 할 수 있지만, 
 bundle들이 공유하는 id이므로 bundle_id로 지칭하였습니다.

 

  

 bundle_order

 number


  답글의 깊이 또는 위치를 정합니다.

  원댓글은 0, 대댓글은1로 표현하면 됩니다.


 user_id

 string

 user의 id  

 nickname

 string

 user의 nickname  

 ip

 string 

 글의 아이피 

 reply

 string

 댓글

 is_deleted

 boolean


 글 삭제는 실제로는 숨기기 임 

 true인 경우 삭제된 글입니다로 표현하기도 합니다.


 created_at

 timestamp 

 생성 시간

 updated_at

 timestamp 

 업데이트된 시간

 deleted_at

 timestamp 

 삭제된 시간


이제 위에 대한 필드를 기본으로 해서,

대댓글에 대해서 고민해 보도록 하겠습니다.


user_id, ip나 reply자체 혹은 created_at같은 것들은 특별히 고민할 부분은 아니어서,

이 글에서 다루지는 않겠습니다.


여기서는 Firebase로 대댓글을 다루는데 있어서 고민해 보아야 할 점들을 기록하였습니다.


A가 댓글을 남기고, B도 댓글을 남긴다음, C가 A에 대한 대댓글을 남긴다고 가정하겠습니다.

여기에 한번더 D가 A의 댓글에 또 대댓글을 남겨보겠습니다.

시간순서로는 A -> B -> C->D이지만,

실제로 유저가 보아야 하는 순서는 A->C->D->B입니다.


이 문제를 해결하기 위해서는,

두가지가 필요합니다.


첫째로, 같은 묶음(bundle)끼리는 같은 값을 공유하고 있어야 하므로,

bundle_id가 하나 필요하구요.

이 때, bundle_id는 ascending으로 증가하는 값이어야,

UI상에서 정렬해서 보여줄 때 편하겠습니다.

보통 MySQL같은 경우는 쉽지만, 

Firestore는 임의로 서버코드에서 오름차순으로 값을 주어야 하는데,

unique같은 옵션이 없으므로,

드물지만, 많은 유저가 동시에 요청을 할 경우 중복된 값이 발생하거나 할 수도 있습니다.

그래서 어쩔수 없이 timestamp값을 공유해서 bundle_id값으로 사용할 수 밖에 없겠습니다.


둘째로는, 같은 묶음인 bundle간에 순서를 정해줄 수 있도록 bundle_order가 필요합니다.

1,2,3,4를 직접 지정해 줄 수도 있겠지만,

중복이 발생할 확률이 적도록 millisecond단위로 시간을 저장하겠습니다.

bundle_order에 따라 ascending순서로 UI에서 정렬해서 보여주면 되겠네요.


핵심부분을 코드로 써보면 아래와 같은데요.

bundle_id가 이미 존재하는 경우는 대댓글로 보고,

depth값도 1로 줘서 ui상으로 들여쓰기를 해주구요.

아닌경우는 새롭게 id와 order를 지정해주면 됩니다.



저장한 것들은 아래와 같이,

bundle_id순으로 댓글을 정렬한 다음,

bundle_order순으로 정렬해서 get()해 주면 될 것 같네요.


구현해 본 결과 정상적으로 아래와 같이 동작하였습니다.



나중에(12:52) 입력한 대댓글이 2nd 댓글보다 더 위에 정상적으로 배치 되었습니다.


+ Recent posts