IT/JS~Node.js

[JS~Nodejs/쿼리] Sequelize ORM : 관계형 데이터베이스의 여러 테이블을 조인하는 코드

토끼개발자 조르디 2024. 10. 14. 18:31

상황 설명

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)와 일치하는 경우에만 결과를 반환