๋ฐฐ์น ์์ ๊ฐ์
๋๋ ๋ฑ๋ก
ํ ๋ฒ์ ์ฌ๋ฌ ๋ ์ฝ๋๋ฐ๋ณต๋ฌธ์ผ๋ก ๋ฑ๋ก
์ผ๊ด ์ ์ฅ
๋จ์ผ ์ฟผ๋ฆฌ๋ก ์ ์ฅ์ฑ๋ฅ ์ต์ ํ
๊ด๊ณ ์ ์ง
UBRef๋ก ๊ด๊ณ ๋ณด์กด์ธ๋ ํค ์๋ ์ฒ๋ฆฌ
ํธ๋์ญ์
์์์ฑ ๋ณด์ฅAll or Nothing
๊ธฐ๋ณธ ๋ฐฐ์น ๋ฑ๋ก
์ฌ๋ฌ User ์์ฑ
๋ณต์ฌ
await db.transaction(async (trx) => {
// 1. ์ฌ๋ฌ User ๋ฑ๋ก
const users = [
{ email: "[email protected]", username: "user1" },
{ email: "[email protected]", username: "user2" },
{ email: "[email protected]", username: "user3" },
];
for (const user of users) {
trx.ubRegister("users", {
email: user.email,
username: user.username,
password: "password",
role: "normal",
});
}
// 2. ์ผ๊ด ์ ์ฅ
const userIds = await trx.ubUpsert("users");
console.log(userIds);
// [1, 2, 3]
});
ubUpsert๋ ๋ฑ๋ก๋ ๋ชจ๋ ๋ ์ฝ๋๋ฅผ ๋จ์ผ INSERT ์ฟผ๋ฆฌ๋ก ์ฒ๋ฆฌํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค.๊ด๊ณ๊ฐ ์๋ ๋ฐฐ์น ๋ฑ๋ก
์ฌ๋ฌ Employee ์์ฑ (๊ฐ์ Department)
๋ณต์ฌ
await db.transaction(async (trx) => {
// 1. Department ๋ฑ๋ก
const deptRef = trx.ubRegister("departments", {
name: "Engineering",
});
// 2. ์ฌ๋ฌ Employee ๋ฑ๋ก
const employees = [
{ name: "John", number: "E001", salary: "70000" },
{ name: "Jane", number: "E002", salary: "75000" },
{ name: "Bob", number: "E003", salary: "80000" },
];
for (const emp of employees) {
const userRef = trx.ubRegister("users", {
email: `${emp.name.toLowerCase()}@test.com`,
username: emp.name,
password: "pass",
role: "normal",
});
trx.ubRegister("employees", {
user_id: userRef,
department_id: deptRef, // โ ๊ฐ์ Department
employee_number: emp.number,
salary: emp.salary,
});
}
// 3. ์์๋๋ก ์ผ๊ด ์ ์ฅ
const [deptId] = await trx.ubUpsert("departments");
const userIds = await trx.ubUpsert("users"); // [1, 2, 3]
const empIds = await trx.ubUpsert("employees"); // [1, 2, 3]
console.log({
deptId,
userCount: userIds.length,
empCount: empIds.length,
});
});
Array.map์ ํ์ฉํ ๋ฐฐ์น
Array.map์ผ๋ก UBRef ๋ฐฐ์ด ์์ฑ
๋ณต์ฌ
await db.transaction(async (trx) => {
// 1. ์ฌ๋ฌ User ๋ฑ๋ก (UBRef ๋ฐฐ์ด ์์ฑ)
const userRefs = ["alice", "bob", "charlie"].map((name) =>
trx.ubRegister("users", {
email: `${name}@test.com`,
username: name,
password: "password",
role: "normal",
})
);
// 2. ๊ฐ User์ ๋ํด Profile ๋ฑ๋ก
userRefs.forEach((userRef, index) => {
trx.ubRegister("profiles", {
user_id: userRef,
bio: `Hello, I'm user ${index + 1}`,
});
});
// 3. ์ ์ฅ
const userIds = await trx.ubUpsert("users");
await trx.ubUpsert("profiles");
console.log({ userCount: userIds.length });
});
์กฐ์ง ๊ตฌ์กฐ ๋๋ ์์ฑ
Company + Departments + Employees
๋ณต์ฌ
await db.transaction(async (trx) => {
// 1. Company
const companyRef = trx.ubRegister("companies", {
name: "Tech Startup",
});
// 2. ์ฌ๋ฌ Department ๋ฑ๋ก
const departments = ["Engineering", "Sales", "Marketing"];
const deptRefs = departments.map((name) =>
trx.ubRegister("departments", {
name,
company_id: companyRef,
})
);
// 3. ๊ฐ Department์ Employee ๋ฐฐ์น
const employeeData = [
{ dept: 0, name: "John", number: "E001" },
{ dept: 0, name: "Jane", number: "E002" },
{ dept: 1, name: "Alice", number: "E003" },
{ dept: 1, name: "Bob", number: "E004" },
{ dept: 2, name: "Charlie", number: "E005" },
];
for (const emp of employeeData) {
const userRef = trx.ubRegister("users", {
email: `${emp.name.toLowerCase()}@startup.com`,
username: emp.name,
password: "pass",
role: "normal",
});
trx.ubRegister("employees", {
user_id: userRef,
department_id: deptRefs[emp.dept], // Department ์ ํ
employee_number: emp.number,
});
}
// 4. ์์๋๋ก ์ ์ฅ
const [companyId] = await trx.ubUpsert("companies");
const deptIds = await trx.ubUpsert("departments");
const userIds = await trx.ubUpsert("users");
const empIds = await trx.ubUpsert("employees");
console.log({
companyId,
deptCount: deptIds.length,
userCount: userIds.length,
empCount: empIds.length,
});
});
ManyToMany ๋ฐฐ์น
์ฌ๋ฌ Project์ ์ฌ๋ฌ Employee ๋ฐฐ์
๋ณต์ฌ
await db.transaction(async (trx) => {
// 1. Projects ๋ฑ๋ก
const projects = ["Project A", "Project B", "Project C"];
const projectRefs = projects.map((name) =>
trx.ubRegister("projects", {
name,
status: "planning",
})
);
// 2. Employees ๋ฑ๋ก
const employees = ["John", "Jane", "Bob"];
const userRefs = employees.map((name) =>
trx.ubRegister("users", {
email: `${name.toLowerCase()}@test.com`,
username: name,
password: "pass",
role: "normal",
})
);
const empRefs = userRefs.map((userRef, i) =>
trx.ubRegister("employees", {
user_id: userRef,
employee_number: `E${100 + i}`,
})
);
// 3. ManyToMany ๊ด๊ณ (๋ชจ๋ ์กฐํฉ)
for (const projectRef of projectRefs) {
for (const empRef of empRefs) {
trx.ubRegister("projects__employees", {
project_id: projectRef,
employee_id: empRef,
});
}
}
// 4. ์ ์ฅ
const projectIds = await trx.ubUpsert("projects");
const userIds = await trx.ubUpsert("users");
const empIds = await trx.ubUpsert("employees");
await trx.ubUpsert("projects__employees");
console.log({
projectCount: projectIds.length,
empCount: empIds.length,
relationCount: projectIds.length * empIds.length,
});
// { projectCount: 3, empCount: 3, relationCount: 9 }
});
๋ฐ์ดํฐ ํ์ผ์์ ๋ฐฐ์น ์์ฑ
CSV/JSON ๋ฐ์ดํฐ๋ก ๋๋ ๋ฑ๋ก
๋ณต์ฌ
// ๋ฐ์ดํฐ ํ์ผ (employees.json)
const employeeData = [
{
email: "[email protected]",
username: "john",
department: "Engineering",
employeeNumber: "E001",
salary: "70000",
},
{
email: "[email protected]",
username: "jane",
department: "Engineering",
employeeNumber: "E002",
salary: "75000",
},
// ... ๋ ๋ง์ ๋ฐ์ดํฐ
];
async function importEmployees(data: typeof employeeData) {
return await db.transaction(async (trx) => {
// 1. ๊ณ ์ ํ Department ์ถ์ถ
const uniqueDepts = [...new Set(data.map((d) => d.department))];
// 2. Department ๋ฑ๋ก
const deptRefMap = new Map<string, any>();
for (const deptName of uniqueDepts) {
const deptRef = trx.ubRegister("departments", {
name: deptName,
});
deptRefMap.set(deptName, deptRef);
}
// 3. Employee ๋ฑ๋ก
for (const emp of data) {
const userRef = trx.ubRegister("users", {
email: emp.email,
username: emp.username,
password: "default_password",
role: "normal",
});
const deptRef = deptRefMap.get(emp.department);
trx.ubRegister("employees", {
user_id: userRef,
department_id: deptRef,
employee_number: emp.employeeNumber,
salary: emp.salary,
});
}
// 4. ์ ์ฅ
await trx.ubUpsert("departments");
await trx.ubUpsert("users");
await trx.ubUpsert("employees");
return { importedCount: data.length };
});
}
// ์ฌ์ฉ
await importEmployees(employeeData);
์ฑ๋ฅ ์ต์ ํ
๋จ์ผ ํธ๋์ญ์
๋ณต์ฌ
// โ
์ข์: ํ ๋ฒ์ ํธ๋์ญ์
await db.transaction(async (trx) => {
for (let i = 0; i < 1000; i++) {
trx.ubRegister("users", { ... });
}
await trx.ubUpsert("users");
});
// โ ๋์จ: ์ฌ๋ฌ ํธ๋์ญ์
for (let i = 0; i < 1000; i++) {
await db.transaction(async (trx) => {
trx.ubRegister("users", { ... });
await trx.ubUpsert("users");
});
}
์ฒญํฌ ๋จ์ ์ฒ๋ฆฌ
๋๋ ๋ฐ์ดํฐ๋ ์ฒญํฌ๋ก ๋๋์ด ์ฒ๋ฆฌ:๋ณต์ฌ
async function importLargeDataset(data: any[], chunkSize = 100) {
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.slice(i, i + chunkSize);
await db.transaction(async (trx) => {
for (const item of chunk) {
trx.ubRegister("users", item);
}
await trx.ubUpsert("users");
});
console.log(`Processed ${i + chunk.length} / ${data.length}`);
}
}
// 10,000๊ฐ ๋ฐ์ดํฐ๋ฅผ 100๊ฐ์ฉ ๋๋์ด ์ฒ๋ฆฌ
await importLargeDataset(largeDataset, 100);
์ค์ ์์
์๋ ๋ฐ์ดํฐ ์์ฑ
๋ณต์ฌ
async function seedDatabase() {
await db.transaction(async (trx) => {
// 1. Companies
const companies = ["Tech Corp", "Startup Inc", "BigCo"];
const companyRefs = companies.map((name) =>
trx.ubRegister("companies", { name })
);
// 2. Departments (๊ฐ Company๋น 3๊ฐ)
const deptNames = ["Engineering", "Sales", "Marketing"];
const deptRefs: any[] = [];
for (const companyRef of companyRefs) {
for (const deptName of deptNames) {
const ref = trx.ubRegister("departments", {
name: deptName,
company_id: companyRef,
});
deptRefs.push(ref);
}
}
// 3. Users + Employees (๊ฐ Department๋น 5๋ช
)
for (let i = 0; i < deptRefs.length; i++) {
for (let j = 0; j < 5; j++) {
const index = i * 5 + j;
const userRef = trx.ubRegister("users", {
email: `user${index}@test.com`,
username: `user${index}`,
password: "password",
role: "normal",
});
trx.ubRegister("employees", {
user_id: userRef,
department_id: deptRefs[i],
employee_number: `E${1000 + index}`,
});
}
}
// 4. ์ ์ฅ
await trx.ubUpsert("companies");
await trx.ubUpsert("departments");
await trx.ubUpsert("users");
await trx.ubUpsert("employees");
console.log("Seed data created!");
console.log({
companies: companies.length,
departments: deptRefs.length,
employees: deptRefs.length * 5,
});
});
}
ํ ์ฌํธ์ฑ
๋ณต์ฌ
async function reorganizeTeams(
projectId: number,
newMemberIds: number[]
) {
await db.transaction(async (trx) => {
// 1. ๊ธฐ์กด ๋ฉค๋ฒ ์ ๊ฑฐ
await trx
.table("projects__employees")
.where("project_id", projectId)
.delete();
// 2. ์ ๋ฉค๋ฒ ์ถ๊ฐ
for (const empId of newMemberIds) {
trx.ubRegister("projects__employees", {
project_id: projectId,
employee_id: empId,
});
}
await trx.ubUpsert("projects__employees");
return { newMemberCount: newMemberIds.length };
});
}
// ์ฌ์ฉ
await reorganizeTeams(1, [5, 10, 15, 20]);
์๋ฌ ์ฒ๋ฆฌ
๋ถ๋ถ ์คํจ ์ฒ๋ฆฌ
๋ณต์ฌ
async function importEmployeesWithValidation(data: any[]) {
const results = {
success: [] as number[],
failed: [] as { index: number; error: string }[],
};
for (let i = 0; i < data.length; i++) {
try {
await db.transaction(async (trx) => {
const userRef = trx.ubRegister("users", {
email: data[i].email,
username: data[i].username,
password: "pass",
role: "normal",
});
trx.ubRegister("employees", {
user_id: userRef,
employee_number: data[i].employeeNumber,
});
await trx.ubUpsert("users");
const [empId] = await trx.ubUpsert("employees");
results.success.push(empId);
});
} catch (error) {
results.failed.push({
index: i,
error: error.message,
});
}
}
return results;
}