ℹ️ 작업환경
db: mysql 8.x
ORM: sequelize 6.x
댓글의 댓글의 댓글....을 쓸 수 있는 댓글창을 만드려고 하는데, 댓글창의 뎁스가 어디까지인지 알수 없기 때문에 sequelize에 include를 사용할 수가 없었다. 그래서 sequelize의 옵션을 찾아봤는데...
일단 결론은..실패.
Including everything이라는 부분에서 비슷한 부분이 나오는거 같아서 한번 활용해 보았다.
// Fetch all models associated with User and their nested associations (recursively)
User.findAll({ include: { all: true, nested: true }});
사이트에 위와 같은 예제가 있어서 한번 Comment
모델로 테스트 해봤는데 2가지 문제가 있었음.
✅ 문제1. 일단 첫번째로 원하는 모델만을 포함할수가 없었고 모든 연관 모델들이 다 엮였음.
✅ 문제2. recursive하게 계속 nested된다고 했는데, Comment를 자기 참조하는 과정에서는 1번밖에는 참조가 안됨. 알리아스를 사용해서 Comment를 LowComment로 조회도 해봤는데, recursive하게 되지 않음. 자기참조가 아닌 모델들은 계속 참조가 되었지만, 자기 자신을 참조하는 경우는 1뎁스아래밖에는 참조 안됐음.
뭐 된다고 해도 문제1
의 경우로 인해서 사용할수는 없음. 그래서 직접 raw쿼리로 짜기로함.
참고로
sequelize-hierachy
라는 패키지가 있다. 재귀적으로 모델을 조회하는 것을 지원해준다고해서 sequelize 공식 사이트에서도 소개되고 있다. 하지만 sequelize 5.x에서 호환이 되고 6.x의 sequelize에서는Bluebird
이 제거됨에 따라 관련 에러가 나타나기 때문에 한번 시도만 해보고 맒.
MySQL의 CTE를 통해서 재귀로 자식코멘트를 찾아서 조회한 후 백엔드에서 원하는 json모형으로 변형을 해 주었음.
아래와 같이 recursive cte (MySQL에서는 8.x부터 지원) 활용한다.
with recursive comments_cte as (
select 원하는 컬럼들...
from comments c
inner join posts p on p.id = c.postId and p.postKey='${postKey}'
where c.upperId is null and c.isDeleted = false
union all
select 위에 원하는 컬럼들과 같은 순서 같은 갯수 같은 데이터형태로...
from comments c
inner join comments_cte cte on cte.id = c.upperId
where c.isDeleted = false
)
select 최종적으로 필요한 컬럼들
from comments_cte c
inner join users u on u.id = c.userId
order by lvl, id desc