알고리즘

댓글 알고리즘 - 인접목록방식

ssh9308 2021. 7. 21. 13:58
반응형

기본적인 댓글 알고리즘에 대해서 살펴보겠습니다 :)

 

첫 번째로 댓글을 구현하는데 가장 많이 사용하는 방법은 "인접 목록 방식"입니다.

댓글의 아이디를 참조하는 parent_id 칼럼을 추가하는 방식으로써 하나의 테이블만으로 댓글 기능을 구현합니다.

 

이해를 위하여 아래의 테이블을 예시로 들겠습니다.

CREATE TABLE dbo.COMMENT_TEST 
( 
	comment_id		bigint not null,	-- 댓글 아이디(pk)
	parent_id		bigint null,		-- 부모 아이디
	comment			nvarchar(500) not null, -- 댓글 내용
	comment_date		datetime not null,	-- 작성 일자
	author			varchar(20) not null	-- 작성한 사람
) 

ALTER TABLE dbo.COMMENT_TEST ADD CONSTRAINT PK__COMMENT_TEST__COMMENT_ID PRIMARY KEY (comment_id)

INSERT INTO dbo.COMMENT_TEST VALUES (1,NULL,N'데이터베이스 어려운가요?',getdate(),'ssh9308'); 
INSERT INTO dbo.COMMENT_TEST VALUES (2,1,N'열심히 공부하시면 어렵지 않을겁니다!',getdate(),'kyj9787') 
INSERT INTO dbo.COMMENT_TEST VALUES (3,2,N'친절한 답변 감사합니다!',getdate(),'ssh9308') 
INSERT INTO dbo.COMMENT_TEST VALUES (4,1,N'SQL 안티패턴 책을 한번 봐보세요',getdate(),'korea1993') 
INSERT INTO dbo.COMMENT_TEST VALUES (5,4,N'어려운 내용은 아닐까요?',getdate(),'mansae4433') 
INSERT INTO dbo.COMMENT_TEST VALUES (6,4,N'그책은 입문서로는 좀 어렵지 않을까요?',getdate(),'respond9977') 
INSERT INTO dbo.COMMENT_TEST VALUES (7,6,N'입문서로는 좀 어려울수 있겠군요 ㅜ',getdate(),'youngboys123')

댓글구조

 

첫 번째 글 "데이터베이스 어려운가요?"의 comment_id를 1이라고 두면, 해당 댓글에 대한 답글인 

"열심히 공부하시면 어렵지 않을 겁니다!"의 comment_id 가 2가 되고, comment_id = 1에 대한 답글이 되므로,

parent_id = 1 이 되게 됩니다.

 

그럼 이러한 인접 목록 방식을 실제 서비스에서 사용하기 위해 댓글의 답글을 불러오는

쿼리는 어떤 식으로 작성해야 할지 아래의 쿼리를 보면서 이해해보도록 하겠습니다.

 

댓글의 첫 번째 답글을 가져오기 위해서는 JOIN이나 SEBQUERY를 사용할 수 있습니다.

1. JOIN 을 이용한 방법

SELECT c2.* FROM dbo.COMMENT_TEST c1 WITH(NOLOCK) 
LEFT OUTER JOIN dbo.COMMENT_TEST c2 WITH(NOLOCK) ON c1.comment_id = c2.parent_id
WHERE c1.comment_id = 1

 

2. SUBQUERY를 이용한 방법

SELECT 
	*
FROM dbo.COMMENT_TEST WITH(NOLOCK)
WHERE comment_id IN (SELECT 
	                 comment_id 
	             FROM dbo.COMMENT_TEST WITH(NOLOCK)
	             WHERE parent_id = 1
	             )

 

첫번째 답글

 

 

그럼 답글에 대한 답글을 가져오려면 어떤 식으로 조회해야 할까요?

조인을 한번 더 걸어서 쿼리 해주는 방법이 있습니다.

SELECT c3.* FROM dbo.COMMENT_TEST c1 WITH(NOLOCK) 
LEFT OUTER JOIN dbo.COMMENT_TEST c2 WITH(NOLOCK) ON c1.comment_id = c2.parent_id
LEFT OUTER JOIN dbo.COMMENT_TEST c3 WITH(NOLOCK) ON c2.comment_id = c3.parent_id
WHERE c1.comment_id = 1

답글에 대한 답글
답글에 대한 답글

 

그럼 자연스럽게 해당 답글에 대한 답글은 한 번 더 조인을 통해서 가져올 수 있음을 유추해볼 수 있습니다.

SELECT c4.* FROM dbo.COMMENT_TEST c1 WITH(NOLOCK) 
LEFT OUTER JOIN dbo.COMMENT_TEST c2 WITH(NOLOCK) ON c1.comment_id = c2.parent_id
LEFT OUTER JOIN dbo.COMMENT_TEST c3 WITH(NOLOCK) ON c2.comment_id = c3.parent_id
LEFT OUTER JOIN dbo.COMMENT_TEST c4 WITH(NOLOCK) ON c3.comment_id = c4.parent_id
WHERE c1.comment_id = 1 and c4.comment_id IS NOT NULL

 

하지만, 대부분의 서비스 사이트에서는 수많은 댓글이 달리게 되고 해당 댓글에 대한 답글도 무수히 많이 존재합니다.

SQL 쿼리에서 조인 회수는 미리 고정되어야 하기 때문에 몇 번의 조인이 합당할지 알기도 어렵습니다.

또한, 너무 많은 조인 횟수 때문에 성능에 저하를 가져올 수도 있습니다.

 

위와 같은 문제점을 해결하고자 다음 포스팅에서는 댓글 알고리즘의 하나의 경로 열거(Path Enumeration) 방법에 대해

알아보겠습니다 :)

 

경로 열거 방식이 궁금하다면 - [Algorithm] 경로 열거 방식

 

 

 

반응형