Subset์ Entity JSON ํ์ผ์ subsets ๊ฐ์ฒด์์ ์ ์ํฉ๋๋ค.
๊ธฐ๋ณธ Subset ์ ์
Entity ๊ตฌ์กฐ
{
"id": "User",
"table": "users",
"props": [
{ "name": "id", "type": "integer" },
{ "name": "username", "type": "string" },
{ "name": "email", "type": "string" },
{ "name": "role", "type": "enum", "id": "UserRole" }
],
"subsets": {
"A": ["id", "username", "email", "role"],
"SS": ["id", "username"]
}
}
Subset ์ ์ ๊ท์น
{
"subsets": {
"A": [
"id",
"created_at",
"username",
"email",
"role"
]
}
}
๊ด๊ณ ํ๋ ์ ํ
OneToOne ๊ด๊ณ
{
"props": [
{ "name": "id", "type": "integer" },
{ "name": "username", "type": "string" },
{
"type": "relation",
"name": "employee",
"with": "Employee",
"relationType": "OneToOne"
}
],
"subsets": {
"P": [
"id",
"username",
"employee.id",
"employee.employee_number",
"employee.salary"
]
}
}
OneToOne ๊ด๊ณ๋ ์๋์ผ๋ก LEFT JOIN๋ฉ๋๋ค.
employee.id๋ฅผ ์ ํํ๋ฉด employees ํ
์ด๋ธ์ด ์กฐ์ธ๋ฉ๋๋ค.
์ค์ฒฉ ๊ด๊ณ (2๋จ๊ณ ์ด์)
{
"subsets": {
"P": [
"id",
"username",
"employee.salary",
"employee.department.name",
"employee.department.company.name"
]
}
}
SQL ๊ฒฐ๊ณผ:
SELECT
users.id,
users.username,
employees.salary AS employee__salary,
departments.name AS employee__department__name,
companies.name AS employee__department__company__name
FROM users
LEFT JOIN employees ON users.id = employees.user_id
LEFT JOIN departments ON employees.department_id = departments.id
LEFT JOIN companies ON departments.company_id = companies.id
Hydrate ๊ฒฐ๊ณผ:
{
id: 1,
username: "john",
employee: {
salary: "70000",
department: {
name: "Engineering",
company: {
name: "Tech Corp"
}
}
}
}
Subset ๋ค์ด๋ฐ ์ ๋ต
์ผ๋ฐ์ ์ธ ๊ท์น
{
"subsets": {
"A": [...], // All - ๋ชจ๋ ํ๋ (๊ด๋ฆฌ์ ์์ธ)
"L": [...], // List - ๋ชฉ๋ก์ฉ (ํ
์ด๋ธ ํ)
"P": [...], // Profile - ํ๋กํ (๊ด๊ณ ํฌํจ)
"SS": [...], // Summary - ์์ฝ (๋๋กญ๋ค์ด, ํ๊ทธ)
"C": [...] // Card - ์นด๋ UI
}
}
๋๋ฉ์ธ๋ณ Subset
{
"subsets": {
"AdminList": ["id", "username", "email", "role", "created_at"],
"UserCard": ["id", "username", "role"],
"ProfileView": ["id", "username", "bio", "employee.department.name"]
}
}
๋ช
๋ช
ํ:
- ์งง๊ณ ๋ช
ํํ ์ด๋ฆ ์ฌ์ฉ (A, L, P ๋ฑ)
- ํ ๋ด์์ ์ผ๊ด๋ ๊ท์น ์ ์ง
- ๋๋ฉ์ธ๋ณ๋ก ์๋ฏธ ์๋ ์ด๋ฆ ์ฌ์ฉ ๊ฐ๋ฅ
Subset ์ค๊ณ ์์น
1. ์ต์ ํ๋ ์์น
// โ ๋์จ: ๋ถํ์ํ ํ๋ ํฌํจ
{
"L": [
"id", "created_at", "updated_at", "deleted_at",
"username", "email", "password", "bio",
"last_login_at", "is_verified"
]
}
// โ
์ข์: ๋ชฉ๋ก์ ํ์ํ ํ๋๋ง
{
"L": [
"id",
"username",
"role",
"created_at"
]
}
2. ์ฉ๋๋ณ ๋ถ๋ฆฌ
{
"subsets": {
// ๋ชฉ๋ก ์กฐํ์ฉ
"L": ["id", "username", "role", "created_at"],
// ์์ธ ์กฐํ์ฉ (๊ด๊ณ ํฌํจ)
"P": [
"id", "username", "email", "bio",
"employee.salary",
"employee.department.name"
],
// ๋๋กญ๋ค์ด์ฉ
"SS": ["id", "username"]
}
}
3. ์ฑ๋ฅ ๊ณ ๋ ค
// โ
์ข์: ํ์ํ ๊ด๊ณ๋ง JOIN
{
"P": [
"id",
"username",
"employee.department.name"
]
}
// โ ๋์จ: ๋ถํ์ํ JOIN
{
"P": [
"id",
"username",
"employee.id",
"employee.company.id",
"employee.projects.id"
]
}
์ฑ๋ฅ ํ:
- JOIN์ ์ต์ํ์ผ๋ก (ํ์ํ ๊ด๊ณ๋ง)
- ๋ชฉ๋ก ์กฐํ๋ L Subset ์ฌ์ฉ (๊ด๊ณ ์ ์ธ)
- ์์ธ ์กฐํ๋ง P Subset ์ฌ์ฉ (๊ด๊ณ ํฌํจ)
์ค์ ์์
User Entity
{
"id": "User",
"table": "users",
"props": [
{ "name": "id", "type": "integer" },
{ "name": "created_at", "type": "date" },
{ "name": "username", "type": "string" },
{ "name": "email", "type": "string" },
{ "name": "role", "type": "enum", "id": "UserRole" },
{ "name": "bio", "type": "string", "nullable": true },
{
"type": "relation",
"name": "employee",
"with": "Employee",
"relationType": "OneToOne",
"nullable": true
}
],
"subsets": {
"A": [
"id", "created_at", "username", "email",
"role", "bio"
],
"L": [
"id", "username", "role", "created_at"
],
"P": [
"id", "username", "email", "bio",
"employee.salary",
"employee.department.name"
],
"SS": [
"id", "username"
]
}
}
Code Generation
Subset์ ์ ์ํ๋ฉด ์๋์ผ๋ก ํ์
์ด ์์ฑ๋ฉ๋๋ค:
# Subset ๋ณ๊ฒฝ ํ ์ฝ๋ ์ฌ์์ฑ
pnpm sonamu generate
Subset์ ๋ณ๊ฒฝํ๋ฉด ๋ฐ๋์ Code Generation์ ์คํํด์ผ ํฉ๋๋ค.
๊ทธ๋์ผ TypeScript ํ์
์ด ์
๋ฐ์ดํธ๋ฉ๋๋ค.
์์ฑ๋๋ ํ์
:
// sonamu.generated.ts
export type UserSubsetKey = "A" | "L" | "P" | "SS";
export type UserSubsetMapping = {
A: {
id: number;
created_at: Date;
username: string;
email: string;
role: UserRole;
bio: string | null;
};
L: {
id: number;
username: string;
role: UserRole;
created_at: Date;
};
P: {
id: number;
username: string;
email: string;
bio: string | null;
employee: {
salary: string;
department: {
name: string;
};
} | null;
};
SS: {
id: number;
username: string;
};
};
๋ค์ ๋จ๊ณ