MySQL의 JOIN 적용을 위한 준비
게시글 작성 사이트를 예시로 들어보자.
데이터베이스에는 유저 테이블과 게시글 테이블이 구분되어 있을 것이고, 게시글 테이블을 통해 해당 게시글의 작성자가 누구인지, 좀 더 깊게 들어가서 작성자의 이메일은 무엇인지 알기 위해서는 두 테이블 간 JOIN 작업이 필요할 것이다. sequelize를 통해 두 테이블을 JOIN 해서 정보를 획득하는 방법에 대해 알아보자
두 테이블의 관계 설정
// 유저 모델과 포스트 모델 간 1대 다 관계 설정
// models/user.js
static associate(models) {
this.hasMany(models.Post, {
sourceKey: 'id',
foreignKey: 'userId',
});
}
// models/post.js
static associate(models) {
this.belongsTo(models.User, {
targetKey: 'id',
foreignKey: 'userId',
});
}
우선 sequelize의 migrate를 통해 생성된 models 파일을 살펴본다.
만약 migrate를 통해 User 모델과 Post 모델이 생성되었다고 가정했을 때 각각의 코드에는 associate
라는 staticmethod가 있을 것이다. 해당 란에 위와 같이 각 모델 파일을 수정해 준다.
위 예시의 경우 유저와 게시글 테이블 간의 관계를 1대 Many로 설정하고 있다. 유저의 입장에서 게시글은 여러 개 작성할 수 있지만 게시글의 입장에서는 본인의 작성자는 단 한명이기 때문이다.
그래서 models/user.js 모델에 hasMany
메서드를 적용하여 User의 id와 Post의 userId 필드를 엮어준다.
그리고 models/post.js 모델의 경우 1대 다 중 '다'에 해당하므로 해당 케이스는 belongsTo
메서드를 통해 위와 같이 코드를 작성해준다.
저렇게하면 이제 sequelize의 CRUD 메서드 사용 시 include
메서드를 활용하여 JOIN 쿼리를 간접적으로 날릴 수 있게 된다.
예시를 살펴보자
// sequelize
const getPosts = async (req, res) => {
const getPosts = await Post.findAll({
attributes: {
exclude: ['userId'],
},
include: [
{
model: User,
attributes: ['id', 'username', 'role'],
},
],
order: [['createdAt', 'DESC']],
});
};
포스트 정보를 GET 하는 함수에서 findAll을 통해 Post테이블 데이터를 모두 불러오며, 이 과정에서 userId 필드를 제외한다. 그 이유는 이후 include 메서드를 통해 User 모델을 불러와 해당 모델에 담긴 필드를 불러오면서 유저 id를 가져올 것이기 때문이다. (굳이 userId에 대한 정보가 중복되어 reponse될 필요가 없기 때문이다.) 마지막으로 게시글 조회 시 게시일 기준으로 내림차순 정렬이 되도록 설정하였다.
{
"posts": [
{
"id": 3,
"title": "cat이 작성한 테스트 타이틀입니다.",
"content": "3번째 테스트 내용 입니다.",
"createdAt": "2023-06-21T05:15:47.000Z",
"updatedAt": "2023-06-21T05:15:47.000Z",
"User": {
"id": 3,
"username": "cat",
"role": "user"
},
},
]
}
결과적으로 위 예시처럼 post에 대한 정보 안에 User 정보를 함께 가져올 수 있게 된다.
'백엔드 개발자(node.js)가 되는 과정' 카테고리의 다른 글
nodejs 비밀번호 해싱 처리하기 (0) | 2023.06.26 |
---|---|
프로세스와 스레드에 대한 간단 정리 (0) | 2023.06.22 |
Sequelize로 모델 생성 및 테이블 연동하기 (0) | 2023.06.21 |
Sequalize로 MYSQL 데이터베이스 마이그레이션하기 (0) | 2023.06.20 |
[WIL] 22. 06. 12 ~ 06. 16 (0) | 2023.06.19 |