[JS~Nodejs/쿼리] Sequelize ORM : 관계형 데이터베이스의 여러 테이블을 조인하는 코드
상황 설명
Nodejs 로 KO웹페이지를 만드는 과정에서 여러 테이블을 조인하는 기능이 필요했다.
신고글을 상세 조회할 때, 그 신고글의 댓글에 해당하는 데이터들을 comments 리스트로 만들고 응답에 추가해주는 작업.
그리고 그 댓글에 대한 상세데이터도 함께 응답에 넣어서 글과 함께 댓글이 조회되도록 해야했다.
원래 생각했던 것은,
우선 특정 ID 의 신고글을 조회하고, 그 신고글에 해당하는 댓글들을 또 따로 조회(?) 해서 그 응답을 리스트로 만들고 그 리스트를 특정 글 상세 조회 응답값에 추가해주고,,, 뭐 이런 느낌으로 여러번 조회하도록 구성하려고 했다.
그런데, 챗지피티가 더 좋은 방법을 알려주었다 ㅋㅋㅋㅋㅋ
include 코드 : 한 줄로 정리
작성 코드 :
router.get('/:id', async (req, res) => {
try {
const report = await Report.findByPk(req.params.id, {
include: [{ model: Comment, include: [User] }]
});
if (!report) {
return res.status(404).json({ error: '신고글을 찾을 수 없습니다.' });
}
// 댓글이 없을 경우 메시지 추가
const comments = report.Comments || []; // 댓글이 없으면 빈 배열로 설정
const message = comments.length === 0 ? '댓글이 없습니다.' : null;
// 신고글과 댓글을 함께 응답
res.json({ report, comments, message });
} catch (error) {
res.status(500).json({ error: '신고글 상세 조회 중 오류가 발생했습니다.' });
}
});
위의 코드에서 핵심은 이 코드
const report = await Report.findByPk(req.params.id, {
include: [{ model: Comment, include: [User] }]
});
신고글과 그에 대한 댓글 및 댓글 작성자 정보를 한 번의 쿼리로 효율적으로 조회할 수 있도록 하는 코드이다.
코드 설명
** include
- Sequelize에서 관계가 설정된 다른 모델을 함께 조회할 때 사용
- 이 옵션을 사용하면, 기본 모델(예: Report)과 관련된 다른 모델(예: Comment)의 데이터를 함께 가져온다.
** { model: Comment }
- Comment 모델을 포함하여 Report 모델과의 관계를 설정
- 즉, 특정 신고글(Report)에 대한 모든 댓글(Comment)을 함께 조회하겠다는 의미
** include: [User]
- Comment 모델과 관련된 User 모델을 포함하여 댓글 작성자의 정보를 함께 가져오겠다는 의미
- 즉, 각 댓글이 어떤 사용자에 의해 작성되었는지를 알 수 있도록 User 모델의 데이터를 포함
전체적인 실행 흐름
1. 특정 ID의 신고글(Report)을 조회
2. 해당 신고글에 대한 모든 댓글(Comment)을 함께 조회
3. 각 댓글에 대한 작성자 정보(User)도 함께 조회
신고글 상세 조회 응답 결과 예시
{
"id": 1,
"title": "신고글 제목",
"content": "신고글 내용",
"Comments": [
{
"id": 1,
"content": "댓글 내용 1",
"User": {
"id": 1,
"username": "사용자1"
}
},
{
"id": 2,
"content": "댓글 내용 2",
"User": {
"id": 2,
"username": "사용자2"
}
}
]
}
Sequelize ORM이 내부적으로 생성하는 SQL 쿼리
위의 코드를 통해 실행되는 쿼리는 아래와 같다
SELECT
`Report`.`id`,
`Report`.`title`,
`Report`.`content`,
`Report`.`createdAt`,
`Report`.`updatedAt`,
`Comment`.`id` AS `Comment.id`,
`Comment`.`content` AS `Comment.content`,
`Comment`.`createdAt` AS `Comment.createdAt`,
`Comment`.`updatedAt` AS `Comment.updatedAt`,
`Comment`.`UserId` AS `Comment.UserId`,
`User`.`id` AS `User.id`,
`User`.`username` AS `User.username`
FROM
`Reports` AS `Report`
LEFT JOIN
`Comments` AS `Comment` ON `Report`.`id` = `Comment`.`ReportId`
LEFT JOIN
`Users` AS `User` ON `Comment`.`UserId` = `User`.`id`
WHERE
`Report`.`id` = :id;
쿼리 설명
1. SELECT:
- Report 테이블에서 필요한 필드(id, title, content, createdAt, updatedAt)를 선택
- Comment 테이블에서 댓글의 필드(id, content, createdAt, updatedAt, UserId)를 선택
- User 테이블에서 댓글 작성자의 정보(id, username)를 선택
2. FROM:
- Reports 테이블을 Report라는 별칭으로 사용하여 기본 테이블로 설정
3. LEFT JOIN:
- Comments 테이블을 Comment라는 별칭으로 사용하여 Report와 조인
👉 Report의 id와 Comment의 ReportId가 일치하는 경우에만 댓글을 가져온다.
- Users 테이블을 User라는 별칭으로 사용하여 Comment와 조인
👉 Comment의 UserId와 User의 id가 일치하는 경우에만 작성자 정보를 가져온다.
4. WHERE:
- Report의 id가 요청된 ID(:id)와 일치하는 경우에만 결과를 반환