MikroORM v6.6 โ ๋ฌด์์ด ๋ฌ๋ผ์ก๋?
๐ Overview
MikroORM 6.6.0์ ๋์ ๋๋ ๋๊ท๋ชจ ๊ธฐ๋ฅ ์ถ๊ฐ๋ ์๋์ง๋ง, โ์ํฐํฐ์ ์บก์ํ์ ์ผ๊ด์ฑ์ ์ง์ผ์ฃผ๋ ๊ธฐ๋ฅโ์ด ์ ์ ์ง์๋์๋ค๋ ์ ์์ ์๋นํ ์๋ฏธ ์๋ ๋ฆด๋ฆฌ์ค๋ผ ์๊ฐํ๋ค.
์ด๋ฒ ํฌ์คํ ์์๋ ์ฐ๋ฆฌ ํ์ด ์ฑํํ ์ปจ๋ฒค์ ์ธ private ํ๋ + get/set accessor๋ฅผ ์ด์ฉํ ํ๋กํผํฐ ๊ด๋ฆฌ ๊ด์ ์ผ๋ก ์ด๋ฒ ๋ฆด๋ฆฌ์ฆ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด๋ คํ๋ค.
1. MikroORM 6.6.0 ์ฃผ์ ๋ณ๊ฒฝ์ ์์ฝ
๊ณต์ ๋ฆด๋ฆฌ์ค ๋ ธํธ https://github.com/mikro-orm/mikro-orm/releases/tag/v6.6.0
๋ฒ๊ทธ ํฝ์ค๊ฐ ์๋ ํผ์ณ ๋ชฉ๋ก๋ง ํ์ธํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
-
core: allow control over relation filters in entity definition
- ๊ธฐ์กด MikroORM์๋ ๊ธ๋ก๋ฒ/์ํฐํฐ ๋จ์ ํํฐ(SoftDeleteFilter ๋ฑ)๊ฐ ์์์ง๋ง, ํน์ relation์ ํํฐ๊ฐ ์ด๋ป๊ฒ ์ ์ฉ๋ ์ง ์ธ๋ฐํ ์ ์ดํ๊ธฐ ์ด๋ ค์ ๋ค.
- ํน์ relation์ ํํฐ๋ฅผ ์ ์ฉํ ์ง ๋ง์ง ๋ฑ์ ์ํฐํฐ ์ ์ ๋จ๊ณ์์ ์ง์ ์ง์ ํ ์ ์๋๋ก ๋ณ๊ฒฝ๋์๋ค.
-
core: allow defining filters on nullable relations as strict
- nullable relation์๋ ํํฐ ์ ์ฉ์ ๊ฐ์ ํ ์ ์๊ฒ ๋ณ๊ฒฝ๋์๋ค.
- ์ญ์ ๋ ์ํฐํฐ๊ฐ nullable์ด๋ผ ์กฐ์ธ๋์ด ๋ฒ๋ฆฌ๋ ๋ฌธ์ ๋ฑ์ ๊น๋ํ ํด๊ฒฐ ๊ฐ๋ฅํ๋ค.
-
core: allow disabling filters on relations
- relation ๋จ์๋ก ํํฐ ๋๊ธฐ๊ฐ ๊ฐ๋ฅํ๊ฒ ๋ณ๊ฒฝ๋์๋ค.
- ๊ธ๋ก๋ฒ ํํฐ๊ฐ ์ ์ฉ๋์ด์๋๋ผ๋ ํน์ relation์ ๋ํด์ ํํฐ๋ฅผ ๊บผ๋ฒ๋ฆด ์ ์๋ค.
-
core: support private properties with get/set accessors
- ์ด๋ฒ ๋ฆด๋ฆฌ์ฆ์ ํต์ฌ์ด๋ผ ์๊ฐํ๋ค. private ํ๋ + getter/setter ๋ฅผ ORM์ด ์ ์ ์ง์ํ๋ค.
#privateField์ฌ์ฉ ๊ฐ๋ฅํ๋ค. (์ ๊ทผ์ getter/setter๋ก ์ ํ)- ๋๋ฉ์ธ ๊ท์น์ ๊ฐ์ ํ๊ณ ์บก์ํ๋ฅผ ๋์ฑ๋ ๊ฐ๋ ฅํ๊ฒ ์ ์ฉํ ์ ์๋ค.
-
entity-generator: allow generating enums as type or JS dictionary
- enum์ TS ํ์ ๋๋ JS ๊ฐ์ฒด(dictionary) ๋ก ์ ํ ์์ฑ ๊ฐ๋ฅํ๊ฒ ๋ณ๊ฒฝ๋์๋ค.
-
entity-generator: support generating defineEntity() definitions
-
entity-generator: support native postgres enums
-
knex: reexport raw helper that supports QueryBuilder and Knex.QueryBuilder
-
postgres: skip left joined relations from pessimistic locks automatically
๊ทธ ์ค์์๋ ์ค๋ฌด์์ ํฐ ์ํฅ์ ์ฃผ๋ ๊ฑด ์ํฐํฐ๋ฅผ ์ ์์ผ๋ก private ํ๋ + accessor ๊ตฌ์กฐ๋ก ์ค๊ณํ ์ ์๊ฒ ๋ ๊ฒ์ด๋ผ ์๊ฐํ๋ค.
2. ๊ธฐ์กด MikroORM์ ๋ฌธ์ ์
@Entity()
export class User {
@PrimaryKey()
id!: number;
@Property()
email!: string;
@Property()
nickname!: string;
}๋๋ถ๋ถ์ ์์ ๊ฐ์ด ํ๋กํผํฐ๋ค์ public์ผ๋ก ๋๊ธฐ์ setEmail() ๊ฐ์ ๋ฉ์๋๋ฅผ ๋ชจ๋ธ์ ์ถ๊ฐํ๋๋ผ๋ user.email์ ์ง์ ์ ๊ทผํ์ฌ ๋ณ๊ฒฝํ ์ ์๋๋ก ์ฝ๋ ๋ ๋ฒจ์์ ์ ์ดํ ์ ์์๋ค.
user.email = 'invalid@...'; // ๊ทธ๋๋ก ํ์ฉ๋จํ ์ปจ๋ฒค์ ๊ณผ ์ฝ๋ ๋ฆฌ๋ทฐ๋ก ์์ ๊ฐ์ ์ง์ ํ ๋น์ ์ต๋ํ ๋ง๊ณ ์์์ง๋ง, ๋๋ฉ์ธ ๊ท์น์ ๊ฐ์ ํ๊ธฐ ์ด๋ ต๋ค๋ ์ ์ด ๋ถํธํจ์ผ๋ก ์กด์ฌํ๋ค.
3. ๋ณ๊ฒฝ๋ MikroORM
์ด๋ฒ ๋ฆด๋ฆฌ์ฆ ์ดํ ์ด์ ์๋์ ๊ฐ์ ๊ตฌ์กฐ๊ฐ ๊ณต์ ํจํด์ผ๋ก ๊ฐ๋ฅํด์ก๋ค.
@Entity()
export class User {
@PrimaryKey()
#id!: number;
#email!: string;
@Property({ accessor: true })
get email() {
return this.#email;
}
set email(value: string) {
this.#email = value;
}
}| ๊ด์ | ๊ธฐ์กด ๋ฐฉ์ | v6.6 ๋ฐฉ์ |
|---|---|---|
| ์ํฐํฐ ํ๋ ์ ๊ทผ | ๋๊ตฌ๋ public ํ๋๋ฅผ ์ง์ ๋ณ๊ฒฝ ๊ฐ๋ฅ | getter/setter ๋ก์ง์ ๊ฐ์ ํ์ฌ ๋ฌด๋ถ๋ณํ ๋ณ๊ฒฝ ๋ฐฉ์ง |
| ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ | ๊ท์น์ ์งํค์ง ์์ ๊ฐ ์ ๋ ฅ ๊ฐ๋ฅ โ ์ทจ์ฝ | setter์์ ๋๋ฉ์ธ ๊ท์น์ ๊ฐ์ ์ ์ฉ ๊ฐ๋ฅ |
| private field ํ์ฉ | ๋น๊ณต์์ /์ฐํ์ ๊ตฌํ ํ์ | private ํ๋๋ฅผ ORM์ด ์ง์ ๊ณต์ ์ง์ |
| ์ ์ง๋ณด์์ฑ | ๊ท์น์ด ์ํฐํฐ ๊ณณ๊ณณ์ ํฉ์ด์ง | ์ํฐํฐ๊ฐ ์บก์ํ๋ ๋๋ฉ์ธ ๋ชจ๋ธ์ฒ๋ผ ๋์ํ์ฌ ์ ์ง๋ณด์์ฑโ |
4. JS private vs @Property({ accessor: true })
MikroORM v6.6์์ private properties with get/set accessors๋ฅผ ์ง์ํ๋ฉด์ ํท๊ฐ๋ฆฌ๊ธฐ ์ฌ์ด ํฌ์ธํธ๊ฐ ํ๋ ์๊ธด๋ค. JS์ #privateField๋ง ์ฐ๋ ๊ฒ๊ณผ MikroORM์ @Property({ accessor: true })๋ฅผ ์ฐ๋ ๊ฒ์ ๋ญ๊ฐ ๋ค๋ฅผ๊น?
๋์ ๊ฒน์น๋ ๋ถ๋ถ๋ ์์ง๋ง, ์ญํ / ๊ด์ฌ์ฌ๊ฐ ์์ ํ ๋ค๋ฅด๋ค. ์๋์์ ์์๋ก ๋น๊ตํด๋ณด์.
4-1. JS private
class User {
#email: string;
constructor(email: string) {
this.#email = email;
}
getEmail() {
return this.#email;
}
changeEmail(next: string) {
if (!next.includes('@')) {
throw new Error('Invalid email');
}
this.#email = next;
}
}
const u = new User('a@b.com');
// ์ธ๋ถ์์ ์ง์ ์ ๊ทผ ๋ถ๊ฐ
// u.#email (Syntax Error)
u.changeEmail('new@domain.com'); // ๋๋ฉ์ธ ๊ท์น์ ๊ฐ์ ์ฌ๊ธฐ์ JS์ private ํ๋๋ ์ค์ง JS ๋ ๋ฒจ ์บก์ํ๋ง ์ ๊ณตํ๋ค.
- ํด๋์ค ์ธ๋ถ์์ #email์ ์ ๊ทผํ ์ ์๊ณ
- ํด๋์ค ๋ด๋ถ์์๋ ๋ง์๋๋ก ์ฝ๊ณ ์ธ ์ ์๋ค
- โORM์ด ์ด ํ๋๋ฅผ DB์ ์ด๋ป๊ฒ ์์ํํ ์งโ๋ ๋ชจ๋ฅธ๋ค (๊ด์ฌ ์์)
์ฆ, JS private์ ์ธ์ด ์ฐจ์์ ์ ๋ณด ์๋์ ๊ฐ๊น๋ค.
4-2. @Property({ accessor: true })
MikroORM ์ ์ฅ์์ ์ค์ํ ๊ฑด ๋ค์๊ณผ ๊ฐ๋ค.
- ์ด๋ค ํ๋กํผํฐ๊ฐ DB ํ๋์ ๋งคํ๋์ด์ผํ ๊น?
- ๊ฐ์ ์ฝ๊ณ ์ธ ๋ ์ด๋ค ๊ฒฝ๋ก๋ฅผ ํตํด ์ ๊ทผํด์ผ ํด์ํ ๊น?
import { Entity, PrimaryKey, Property } from '@mikro-orm/core';
@Entity()
export class User {
@PrimaryKey()
id!: number;
#email!: string;
@Property({ accessor: true })
get email() {
return this.#email;
}
set email(value: string) {
if (!value.includes('@')) {
throw new Error('Invalid email');
}
this.#email = value;
}
}์ฆ, ์ด ํ๋กํผํฐ๋ getter/setter๋ฅผ ํตํด ์ ์ด๋๋ ํ๋กํผํฐ๋ผ๊ณ ORM์๊ฒ ์ ์ธํ๋ ๊ฒ์ด๋ค.
๐ค Understanding
MikroORM v6.6์ ์คํ์ด ํฌ๊ฒ ๋ฐ๋ ๋ฆด๋ฆฌ์ค๋ ์๋์ง๋ง, ์ํฐํฐ ๋ชจ๋ธ๋ง์ ์์ฑ๋๋ฅผ ํฌ๊ฒ ๋์ด์ฌ๋ฆฌ๋ ๊ธฐ๋ฅ์ ์ ์์ผ๋ก ์ง์ํ๋ค.
MSA + DDD ์คํ์ผ๋ก ๊ฐ๋ฐํ๋ ์ฐ๋ฆฌ ํ์๊ฒ๋ ๋๋ฉ์ธ ๊ท์น์ setter์์ ๊ฐ์ ํ ์ ์๊ฒ ๋์ด ๋ถํธํ ์ ์ ํฌ๊ฒ ๊ฐ์ ํ ์ ์๋ค ์๊ฐํ๋ค.