MikroORM v6.6 โ€“ ๋ฌด์—‡์ด ๋‹ฌ๋ผ์กŒ๋‚˜?

๐Ÿ“š
Backend
2025.12.01

๐Ÿ“š 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์—์„œ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ๋ถˆํŽธํ•œ ์ ์„ ํฌ๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค ์ƒ๊ฐํ•œ๋‹ค.

Previous
structuredClone() โ€“ Web Platform์ด ์ œ๊ณตํ•˜๋Š” ํ‘œ์ค€ ๋”ฅ ํด๋ก 
๐Ÿ“šWeb
2025.11.16
Next
์ฒซ ์ด์ง ํ›„ ํšŒ๊ณ 
๐Ÿค”Retrospect
2025.12.08