오늘은 대댓글 게시판을 설계하는 방법에 대해서 정리 해보려고 하는데요.
참고로, 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 댓글보다 더 위에 정상적으로 배치 되었습니다.
'설계' 카테고리의 다른 글
게시판 페이지 번호를 매기는 페이징방법에 대해서 알아보자 (0) | 2019.02.28 |
---|