mysql의 강점은 관계형 db라는 점입니다. 앞의 글에서 테이블의 생성에 대하여 알아봤다면 이번 시간에는 관계형 테이블을 만드는 방법을 알아보고 쿼리를 통하여 db에 저장하고 삭제하고 수정하고 조회하는 CRUD(Create, Read, Update, Delete)를 하는 방법에 대해 알아보겠습니다.
테이블 관계
Sequelize에서는 데이터베이스 테이블 간의 관계를 정의할 때 associate 메서드를 사용합니다.
Sequelize에서 관계를 정의하는 방법은 크게 세 가지 유형이 있습니다.
- 일대일 관계 (One-to-One Relationships)
- 일대다 관계 (One-to-Many Relationships)
- 다대다 관계 (Many-to-Many Relationships)
다음은 각각의 관계 유형에 대한 associate 메서드의 사용 방법입니다.
일대일 관계 (One-to-One Relationships)
Sequelize를 사용하여 Node.js에서 일대일 관계를 맺는 방법은 hasOne와 belongsTo 메서드를 사용하는 것입니다.
다음은 예시 모델인 User와 Profile이 있을 때, 각 User는 하나의 Profile과 연관되어 있는 일대일 관계를 가진다고 가정해 봅시다.
models/user.js
const Sequelize = require("sequelize");
module.exports = class User extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
name: {
type: Sequelize.STRING(255),
unique: true,
},
},
{
sequelize,
modelName: "user",
tableName: "User",
timestamps: true,
charset: "utf8mb4",
collate: "utf8mb4_general_ci",
}
);
}
static associate(db) {
db.User.hasOne(db.Company, {
as: "Who",
sourceKey: "name",
foreignKey: "worker",
});
}
};
models/comment.js
const Sequelize = require("sequelize");
module.exports = class Company extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
companyName: {
type: Sequelize.STRING(255),
unique: true,
},
},
{
sequelize,
modelName: "company",
tableName: "Company",
timestamps: true,
charset: "utf8mb4",
collate: "utf8mb4_general_ci",
}
);
}
static associate(db) {
db.Company.belongTo(db.User, {
targetKey: "name",
foreignKey: "worker",
});
}
};
위의 코드에서 User 모델과 Company모델 각각에 hasOne와 belongsTo 메서드가 사용되었습니다.
hasOne 메서드는 관계를 맺을 대상 모델에서 사용됩니다. User 모델에서 Company 모델을 참조하기 위해 User 모델에 hasOne 메서드를 추가합니다.
belongsTo 메서드는 관계를 맺을 다른 모델에서 사용됩니다. Company 모델에서 User 모델을 참조하기 위해 Company 모델에 belongsTo 메서드를 추가합니다.
위의 코드에서 User 모델은 하나의 Profile을 가질 수 있으므로 hasOne 메서드를 사용합니다. Profile 모델은 하나의 User와 연관되므로 belongsTo 메서드를 사용합니다.
Sequelize에서는 데이터베이스 간의 관계를 설정할 때 as를 사용하여 각 모델 간의 관계에 대한 별칭(alias)을 지정할 수 있습니다.
이제 이와 같은 관계를 가진 User와 Company모델을 사용하여 데이터베이스 작업을 수행할 수 있습니다.
관계를 맺는 방법
const user = await User.findOne({
where: { name: "Rainbowbear" },
});
const company = await Company.findOne({
where: { name: "Rainbowbear" },
});
user.addWho(company);
위에서 as를 Who로 설정을 해두었기 때문에 addWho라는 메서드를 사용하여 user와 company를 관계를 맺어줍니다.
User
id | name (sourceKey) |
1 | Rainbowbear |
Company
id | worker (foreignKey) | companyName |
1 | Rainbowbear | RainbowCompany |
일대다 관계 (One-to-Many Relationships)
Sequelize를 사용하여 Node.js에서 일대다 관계를 맺는 방법은 hasMany와 belongsTo 메서드를 사용하는 것입니다.
다음은 예시 모델인 User와 Task가 있을 때, User는 많은 Task를 가질 수 있고, 각 Task는 하나의 User와 연관되어 있는 일대다 관계를 가진다고 가정해 봅시다.
models/user.js
static associate(db) {
db.User.hasMany(db.Task, {
as: "Responsibility",
sourceKey: "name",
foreignKey: "whoDo",
});
}
models/task.js
static associate(db) {
db.Task.belongsTo(db.User, {
targetKey: "name",
foreignKey: "whoDo",
});
}
위의 코드는 일대일 관계의 코드와 다르게 테이블에 대한 정보를 제외하고 관계를 설정하기 위한 associate부분만 가져왔습니다.
User 모델과 Task 모델 각에 hasMany와 belongsTo 메서드가 사용되었습니다.
hasMany 메서드는 관계를 맺을 대상 모델에서 사용됩니다. User 모델에서 Task 모델을 참조하기 위해 User 모델에 hasMany 메서드를 추가합니다.
belongsTo 메서드는 관계를 맺을 다른 모델에서 사용됩니다. Task 모델에서 User 모델을 참조하기 위해 Task 모델에 belongsTo 메서드를 추가합니다.
위의 코드에서 User 모델은 많은 Task를 가질 수 있으므로 hasMany 메서드를 사용합니다. Task 모델은 하나의 User와 연관되므로 belongsTo 메서드를 사용합니다.
이제 이와 같은 관계를 가진 User와 Task 모델을 사용하여 데이터베이스 작업을 수행할 수 있습니다.
관계를 맺는 방법
const user = await User.findOne({
where: { name: "Rainbowbear" },
});
const task1 = await Task.findOne({
where: { name: "서류 정리" },
});
const task2 = await Task.findOne({
where: { name: "메일 보내기" },
});
user.addResponsibility(task1);
user.addResponsibility(task2);
위에서 as를 Responsibility로 설정을 해두었기 때문에 addResponsibility라는 메서드를 사용하여 user와 task를 관계를 맺어줍니다.
models/user.js
id | name (sourceKey) |
1 | RainbowBear |
models/task.js
id | whoDo (foreignKey) | task |
1 | RainbowBear | 서류 정리 |
2 | RainbowBear | 메일 보내기 |
다대다 관계 (Many-to-Many Relationships)
Sequelize를 사용하여 Node.js에서 다대다 관계를 맺는 방법은 belongsToMany 메서드를 사용하는 것입니다.
예를 들어, User와 Group이라는 두 개의 모델이 있고 각각의 사용자는 여러 그룹에 속할 수 있으며 각 그룹도 다수의 사용자를 포함할 수 있다고 가정해 봅시다. 이러한 경우 다대다 관계를 설정할 수 있습니다.
models/user.js
static associate(db) {
db.User.belongsToMany(db.Skill, {
as: "Stack",
sourceKey: "name",
foreignKey: "whoHas",
through:"SkillStack",
onDelete:"cascade"
});
}
models/skill.js
static associate(db) {
db.Skill.belongsToMany(db.User, {
targetKey: "name",
foreignKey: "skillName",
through:"SkillStack",
onDelete:"cascade",
});
}
위의 코드는 일대일 관계의 코드와 다르게 테이블에 대한 정보를 제외하고 관계를 설정하기 위한 associate부분만 가져왔습니다.
위의 코드에서, belongsToMany 메서드는 User 모델과 Skill 모델 모두에 사용됩니다. through 옵션은 관계를 맺을 중간 모델을 지정합니다. 이 경우 SkillStack이라는 중간 모델을 사용합니다.
User 모델과 Skill 모델이 다대다 관계를 가지므로, User 모델은 Skill 모델을 참조하고, Skill 모델은 User 모델을 참조합니다.
위의 코드를 사용하여 데이터베이스 작업을 수행할 수 있습니다.
관계를 맺는 방법
const user1 = await User.findOne({
where: { name: "Rainbowbear" },
});
const user2 = await User.findOne({
where: { name: "bear" },
});
const skill1 = await Skill.findOne({
where: { name: "Java" },
});
const skill2 = await Task.findOne({
where: { name: "React" },
});
user1.addStack(skill1);
user1.addStack(skill2);
user2.addStack(skill1);
user2.addStack(skill2);
위에서 as를 Responsibility로 설정을 해두었기 때문에 addResponsibility라는 메서드를 사용하여 user와 task를 관계를 맺어줍니다.
models/user.js
id | name (sourceKey) |
1 | RainbowBear |
2 | bear |
through
id | whoHas | skillName |
1 | RainbowBear | Java |
2 | RainbowBear | React |
3 | bear | Java |
4 | bear | React |
models/skill.js
id | task |
1 | 서류 정리 |
2 | 메일 보내기 |
'Node.js' 카테고리의 다른 글
[NodeJS] JWT란? (JWT 생성, Access Token, Refresh Token) (2) | 2023.07.21 |
---|---|
[NodeJS] Socket.IO 이해하기 (0) | 2023.03.14 |
[NodeJS] mysql sequelize 이해하기 - (기본 설정과 테이블 생성) (0) | 2023.03.09 |
[NodeJS] multer 이해하기 (0) | 2023.03.06 |
[NodeJS] express session과 cookie 이해하기 (0) | 2023.03.05 |