Skip to main content Link Search Menu Expand Document (external link)

๐Ÿ–ย ๋œฏ์–ด๋ณด๊ธฐ 1์ผ์ฐจ - ์‹œ์ž‘์€ build.gradle ๋ถ€ํ„ฐ?(feat. Entity vs Domain)


Table of contents
  1. ๐Ÿ–ย ๋œฏ์–ด๋ณด๊ธฐ 1์ผ์ฐจ - ์‹œ์ž‘์€ build.gradle ๋ถ€ํ„ฐ?(feat. Entity vs Domain)
    1. ์‹œ์ž‘
    2. ๊ฒฐ๋ก 
    3. ์˜ค๋Š˜ ์•Œ ๊ฒŒ ๋œ ๊ฒƒ
    4. ๋‹ค์Œ์— ํ•  ๊ฒƒ
    5. ๊ฒฐ๋ก 

์‹œ์ž‘

์ผ๋‹จ ํŠธ์œ„ํ„ฐ์— ์˜คํ”ˆ ์†Œ์Šค ๋œฏ์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! ์„ค๋กœ์ธ๋ถ€ํ„ฐ ํ•  ๊ฑฐ์—์š”! ๋ผ๊ณ  ์งˆ๋Ÿฌ์„œ ์˜ค๋Š˜ ์„ค๋กœ์ธ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋‹ค์šด ๋ฐ›์•˜๋‹ค. ๋ฉ์ฒญํ•˜๊ฒŒ ์„œ๋ฒ„ ํŒŒ์ผ ์ธํ…”๋ฆฌ์— ํ•œ ๊บผ๋ฒˆ์— ์˜ฌ๋ ค์„œ ์ „์ฒด ๋‹ค ๋‹ค์šด ๋ฐ›๋Š”๋ฐ๋งŒ 20๋ถ„ ๊ฑธ๋ ธ๋‹ค.

๋‚ด ๋…ธํŠธ๋ถ์ด ๋ฌธ์ œ์ธ๊ฐ€?

์—ฌํŠผ ๋ชจ๋ฅด๋Š” ์ฝ”๋“œ๋ฅผ ๋ณผ ๋•Œ build.gradle ๋ถ€ํ„ฐ ๋ณด๋Š”๊ฒŒ ์Šต๊ด€์ด๋ผ ์—ฌ๊ธฐ๋ถ€ํ„ฐ ์‹œ์ž‘ํ–ˆ๋‹ค.

์‹œ์ž‘๋ถ€ํ„ฐ Distributed under CC BY-NC-SA ๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ๋ˆˆ์— ๋„์—ˆ๋Š”๋ฐ ๋‹น์—ฐํžˆ ๋ชฐ๋ž๊ธฐ ๋•Œ๋ฌธ์— ๊ฒ€์ƒ‰์„ ํ•ด๋ดค๋”๋‹ˆ ๋ผ์ด์„ผ์Šค ๊ด€๋ จ๋œ ๋ฌธ๊ตฌ์˜€๋‹ค. ์˜ค ๋ญ”๊ฐ€ ์˜คํ”ˆ ์†Œ์Šค๋Š” ์ด๋ ‡๊ฒŒ ๊ผผ๊ผผํ•ด์•ผ ํ•˜๋Š” ๊ฑด๊ฐ€ ์‹ถ์—ˆ๋‹ค.

  • This license lets others remix, tweak, and build upon your work non-commercially, as long as they credit you and license their new creations under the identical terms.
  • ์ด ๋ผ์ด์„ผ์Šค๋Š” ์ƒ์—… ๋ชฉ์ ์ด ์•„๋‹ˆ๋ฉด ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ˆ˜์ •ํ•ด๋„ ์ƒ๊ด€ ์—†๋‹ค~ ๋ผ๋Š” ๊ฑฐ ๊ฐ™๋‹ค. ๋™์ผ ์กฐ๊ฑด์ด๋ฉด ์ƒˆ๋กœ์šด ์ฐฝ์ž‘๋ฌผ์—๋„ ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋กœ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑด๊ฐ€? ์—ฌํŠผ ์ถœ์ฒ˜ ์—์„œ ๋” ์ž์„ธํ•œ ๊ฑด ๋ณด์„ธ์š”.

image



๊ทธ๋‹ค์Œ ๋ณด๊ฒŒ ๋œ ๊ฒƒ์€ jvm 17๊ณผ kotlin version 1.6.10 ์ด๋ผ๋Š” ๊ฑด๋ฐ 1.6?

๊ฐ‘์ž๊ธฐ ๋‚˜๋Š” ๋ช‡ ๋ฒ„์ „ ์“ฐ์ง€ ํ•˜๊ณ  ๊ถ๊ธˆํ•ด์ ธ์„œ ๋‚ด ์ฝ”๋“œ ๋ณด๋‹ค๊ฐ€ ์ ฏ๋ธŒ๋ ˆ์ธ ์ฝ”ํ‹€๋ฆฐ ๋ธ”๋กœ๊ทธ๋ฅผ ๊ฐ”๋Š”๋ฐ 1.6.0 ๋ฆด๋ฆฌ์ฆˆ๊ฐ€ 2021๋…„ 12์›” ์ค‘์ˆœ์ด๋‹ค. ์•„์ง 3๊ฐœ์›” ๋ฐ–์— ์•ˆ์ง€๋‚œ ๊ฑฐ ๊ฐ™์€๋ฐ ์—„์ฒญ ์ตœ์‹  ๋ฒ„์ „ ์“ฐ๋„ค? ์‹ถ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ข€ ๋” ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ์•„ ์ด๊ฑฐ ์ธํ…”๋ฆฌ์ œ์ด ๊ธฐ๋ณธ์œผ๋กœ ๋งŒ๋“ค๋ฉด ์ฝ”ํ‹€๋ฆฐ ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ๋˜๊ณ  java 17 ์„ค์ •ํ•ด์„œ ์ด๋ ‡๊ฒŒ ๋‚˜์™”๋‚˜ ์‹ถ์—ˆ๋‹ค.(์™œ๋ƒ๋ฉด ๋‚ด๊ฐ€ ์ตœ๊ทผ์— ๋งŒ๋“ ๊ฒŒ

๊ทผ๋ฐ ๊ฒ€์ƒ‰ํ•ด๋ณด๋ฉด์„œ ์ ฏ๋ธŒ๋ ˆ์ธ ๋ธ”๋กœ๊ทธ ์ฒ˜์Œ ๋“ค์–ด๊ฐ€๋ดค๋Š”๋ฐ ์ด๊ฒƒ๋„ ๊ฐ์žก๊ณ  ์ •๋ฆฌํ•˜๋ฉด์„œ ๊ณต๋ถ€ํ•˜๋Š” ๊ธ€ ์“ฐ๋ฉด ์—„์ฒญ๋‚œ ๊ณต๋ถ€๊ฐ€ ๋  ๊ฑฐ ๊ฐ™๋‹ค. ์ฝ”ํ‹€๋ฆฐ ์ •๋ณด๋Š” ๋‹ค ์—ฌ๊ธฐ ์žˆ์—ˆ๊ตฌ๋‚˜!!

1.6.10 ์—์„œ ๋‹ค๋ฅธ ๊ฑด ์ž˜ ๋ชจ๋ฅด๊ฒ ๊ณ  Kover๋ผ๋Š”๊ฒŒ ์ƒ๊ฒผ๋‹ค๊ณ  ํ•œ๋‹ค. ์ฝ”๋“œ ์ปค๋ฒ„๋ฆฌ์ง€๋ฅผ ์ธก์ •ํ•˜๋Š” gradle plugin์ด๋ผ๋Š”๋ฐ ๊ธฐ์กด์— jacoco๊ฐ€ gradle toolchain, ๋ฉ€ํ‹ฐ ํ”Œ๋žซํผ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์™„์ „ํžˆ ํ†ตํ•ฉ๋˜์ง€ ์•Š์€ ์ด์Šˆ๋ฅผ ํ”ฝ์Šคํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค. ์•„์ง ๊ฐœ๋ฐœ ์ดˆ๊ธฐ ๋‹จ๊ณ„๊ตฌ๋‚˜.

Kotlin + Coverage = Kover ์ธ๊ฑด๊ฐ€!


์ด๊ฑฐ 2๊ฐœ๋„ ์ฒ˜์Œ ๋ณธ๋‹ค.

version_javax_inject = "1"

์–˜๋Š” maven repository ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€ ๊ฐ€๋ณด๋‹ˆ ๊ตฌ๊ธ€์—์„œ ๋งŒ๋“ ๊ฑฐ ๊ฐ™๊ณ  ์ž๋™์œผ๋กœ ์˜์กด์„ฑ ์ฃผ์ž…ํ•ด์ฃผ๋Š” ๊ฑด๊ฐ€ ๋ณด๋‹ค. ํšŒ์‚ฌ ์ฝ”๋“œ ์–ด๋””์— ์“ฐ์˜€๋Š”์ง€ ๋‚˜์ค‘์— ๋ด๋ด์•ผ์ง€. ๋‚ด๊ฐ€ ๊ฒ€์ƒ‰ํ•ด์„œ ์•Œ์•„๋‚ด๋Š” ๊ฒƒ ๋ณด๋‹ค ๋น ๋ฅด๊ฒ ์ง€

๋‚˜๋Š” ์ฒ˜์Œ ๋ต™๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ๋ฐ ๊ตฌ์•„๋ฐ”, ์Šคํ”„๋ง ๋นˆ์ฆˆ์— ์“ฐ์ด์‹  ๊ฑด์ง€ Artifacts using Javax Inject ์น˜๋‹ˆ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ๋‚˜์˜ค๋Š” ๊ตฌ๋งŒ

JSR-330: Dependency Injection for Java Welcome to the home of JSR-330: Dependency Injection for Java.


image


์Œ ๋ญ”๊ฐ€ ๋‹จ์ถœํ•ด์„œ(?) ์ข‹๊ตฐ์š”!



version_jsr305 = "3.0.2"

jsr305๋„ ์ฒ˜์Œ ๋ณด๋Š”๋ฐ ์ปดํŒŒ์ผ ์‹œ์ ์— ์ •์ ์œผ๋กœ ๋ฒ„๊ทธ ์žก์•„ ์ค€๋‹ค๊ณ  ํ•˜๋Š”๋ฐ ์ด๊ฑฐ ์–ด๋””์„œ ์“ฐ์˜€์„๊นŒ ํ›”ํ›”

image

์˜คํ˜ธ ์–ด๋…ธํ…Œ์ด์…˜์ด javax.validation์—์„œ ๋ณด๋˜ ๊ฒƒ๊ณผ ๋น„์Šทํ•œ๊ฒŒ ๋ณด์ด๋Š”๋ฐ NonNull ๊ฐ™์€ ๊ฑฐ.

์ด๊ฑฐ ์ปดํŒŒ์ผ ํ•  ๋•Œ ์ €๊ธฐ ์–ด๋…ธํ…Œ์ด์…˜ ๋ถ™์€ ๊ฒƒ๋“ค ๋ฐ์ดํ„ฐ ์˜๋„ํ•œ๋Œ€๋กœ ๋‹ด๊ณ  ์žˆ๋Š”์ง€ ๋‹ค ์ฒดํฌํ•ด์ฃผ๋‚˜ ๋ณด๋‹ค. ์ด๊ฑฐ๋Š” ๋Œ€์ถฉ ๋ด๋„ ๊ฝค ์ข‹์€ ๊ฑฐ ๊ฐ™๋‹ค!! ๋‚˜์ค‘์— ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ ์ข€ ๋ณด๊ณ  ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ์— ์จ๋ด์•ผ์ง€.




์˜ค๋Š˜์€ ์—ฌ๊ธฐ๊นŒ์ง€ ํ•˜๊ณ  ๋‹ค๋ฅธ ๊ฑฐ ์ข€ ๋’ค์ ธ๋ณผ๊นŒ~? ํ•˜๋‹ค๊ฐ€ ์žฌ๋ฐŒ๋Š” ๊ฑธ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.

์žฌ๋ฐŒ๊ฒŒ ์ด๋Ÿฐ ์งˆ๋ฌธ์ด ์žˆ๋„ค!!!

// POINT: ์ด ํด๋ž˜์Šค๋ฅผ data class ๋กœ ์„ ์–ธํ•˜๊ณ , equals / hashCode ๋ฅผ ์‚ญ์ œํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ์—†์„๊นŒ์š”?
// POINT: Entity ์™€ Domain Model ์˜ ์ฐจ์ด๋ž€ ๋ญ˜๊นŒ์š”?

api-core-infra-impl ์ชฝ domain.user ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์— UserEntity ์œ„์— ๋‹ฌ๋ฆฐ ์žฌ๋ฐŒ๋Š” ์ฃผ์„์ด ๋‹ฌ๋ ค ์žˆ์—ˆ๋‹ค!

infra๋ผ๊ณ  ์จ์žˆ๋Š”๊ฒŒ JPA ๊ฐ™์€๊ฑฐ๋‚˜ ์™ธ๋ถ€ ์„œ๋น„์Šค, message ๊ด€๋ จ์ธ๊ฐ€ ์‹ถ๊ธด ํ–ˆ๋Š”๋ฐ domain.user ๋ฐ‘ repository๊ฐ€ ์žˆ์—ˆ๋‹ค. ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ๊ฐ€ ๋ญ”๊ฐ€ ์‹ ๊ธฐํ•œ๋ฐ ์ €๋ ‡๊ฒŒ ๋„๋ฉ”์ธ๋ณ„๋กœ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฑด๊ฐ€?


์ผ๋‹จ ์ฒซ ๋ฒˆ์งธ ํฌ์ธํŠธ์— ๋Œ€ํ•œ ์ƒ๊ฐ์„ ์ ์–ด๋ณด์ž๋ฉด(์ฝ”ํ‹€๋ฆฐ 3๊ฐœ์›”์ฐจ๋ผ ํ‹€๋ฆด ์ˆ˜ ์žˆ์Œ)

  1. data class ์ƒ์„ฑํ•˜๋ฉด ์•Œ์•„์„œ equals, hashCode ๊ฐ™์€๊ฑฐ ์ƒ์„ฑ๋˜์„œ ์ƒ๊ด€์€ ์—†๋Š”๋ฐ
  2. ๋ฌธ์ œ๊ฐ€ ์ €๊ฒŒ JPA๋ž‘ ๊ฐ™์ด ์“ธ ๋•Œ ์—๋Ÿฌ๊ฐ€ ๊ฝค ๋ฟœ๋ฟœ ํ–ˆ๋‹ค. ์–‘๋ฐฉํ–ฅ ๋งตํ•‘ ํ–ˆ์„ ๋•Œ toString() ๋•Œ๋ฌธ์— StackOverFlow ๋„ ๋œจ๊ณ , ๋ญ ์ด๋Ÿฐ์ €๋Ÿฐโ€ฆ
  3. ๊ฒฐ๋ก ์€ ์‚ญ์ œํ•ด๋„ ๋ฌธ์ œ๋Š” ์—†์œผ๋‚˜ data class๋ฅผ ์—”ํ‹ฐํ‹ฐ๋กœ ์“ธ ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” side effect๊ฐ€ ์žˆ์–ด์„œ ๊ผญ ์ ํ•ฉํ•œ์ง€๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค!
  4. ๊ทผ๋ฐ ์ง€๊ธˆ ๋ณด๋‹ˆ๊นŒ ์ด ํด๋ž˜์Šค JPA๋กœ ๋งŒ๋“  Entity๊ฐ€ ์•„๋‹ˆ๊ตฌ๋‚˜!
  5. equals๋ž‘ hashCode ์ž๋™ ์ƒ์„ฑํ•ด์„œ ๋น„๊ตํ•ด๋ณผ๊นŒ.
// ์ด๊ฒŒ ์›๋ž˜ ์žˆ๋˜ ์ฝ”๋“œ
override fun equals(other: Any?): Boolean =
  if (other !is UserEntity) {
      false
  } else {
      Objects.equals(id, other.id) &&
      Objects.equals(uuid, other.uuid) &&
      Objects.equals(nickname, other.nickname) &&
      Objects.equals(profileImageUrl, other.profileImageUrl) &&
      Objects.equals(deletedAt, other.deletedAt) &&
      Objects.equals(createdAt, other.createdAt) &&
      Objects.equals(updatedAt, other.updatedAt) &&
      Objects.equals(version, other.version)
  }
        
// ์ด๊ฒŒ ์ธํ…”๋ฆฌ์ œ์ด ๊ธฐ๋Šฅ์œผ๋กœ ๋งŒ๋“  ๊ฑฐ!
override fun equals(other: Any?): Boolean {
    if (this === other) return true
    if (javaClass != other?.javaClass) return false

    other as UserEntity

    if (id != other.id) return false
    if (uuid != other.uuid) return false
    if (deletedAt != other.deletedAt) return false
    if (createdAt != other.createdAt) return false
    if (version != other.version) return false
    if (nickname != other.nickname) return false
    if (profileImageUrl != other.profileImageUrl) return false
    if (updatedAt != other.updatedAt) return false

    return true
}

์Œ ์ž๋™ ์ƒ์„ฑํ•ด์„œ ๋งŒ๋“  ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ์—ˆ๋„ค. !is ๋ฅผ ์“ด ์ฝ”๋“œ ์ฒ˜์Œ ๋ณธ๋‹ค.

Object์˜ equals๋ฅผ ์จ์„œ ๊ฐ’์„ ํ•˜๋‚˜ํ•˜๋‚˜ ๋น„๊ตํ•˜๋Š”๊ตฌ๋‚˜.

Object ์•ˆ์— equals ํƒ€๊ณ  ๋“ค์–ด๊ฐ€๋‹ˆ ์•„๋ž˜ ์ฝ”๋“œ๊ฐ€ ๋‚˜์˜ค๋Š”๋ฐ ์ด๋ ‡๊ฒŒ ๋ณด๋‹ˆ๊นŒ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๊ฐ€๋…์„ฑ ์žˆ๊ฒŒ ๋‹ค์‹œ ์ผ๊ตฌ๋‚˜ ์‹ถ๋‹ค.

public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}


// ์ž‘์„ฑ๋˜์–ด ์žˆ๋˜ ์ฝ”๋“œ
override fun hashCode(): Int {
        return Objects.hash(
            this.id,
            this.uuid,
            this.nickname,
            this.profileImageUrl,
            this.deletedAt,
            this.createdAt,
            this.updatedAt,
            this.version
        )
    }

// ์ธํ…”๋ฆฌ ์ œ์ด ๊ธฐ๋Šฅ์œผ๋กœ ์ž๋™ ์ƒ์„ฑํ•œ ์ฝ”๋“œ
override fun hashCode(): Int {
    var result = id?.hashCode() ?: 0
    result = 31 * result + uuid.hashCode()
    result = 31 * result + (deletedAt?.hashCode() ?: 0)
    result = 31 * result + createdAt.hashCode()
    result = 31 * result + version.hashCode()
    result = 31 * result + nickname.hashCode()
    result = 31 * result + profileImageUrl.hashCode()
    result = 31 * result + updatedAt.hashCode()
    return result
}

hashCode ๋„ ๊ทธ๋ ‡๋„ค! ์–˜๋„ Object์˜ hash๋ฅผ ์จ์„œ ๋”ฐ๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์˜€๋‹ค.

์ž๋™์ƒ์„ฑ๋œ ์ฝ”๋“œ result ๋”ฐ๋‹ฅ๋”ฐ๋‹ฅ ์จ ์žˆ์–ด์„œ ์ง„์งœ ๊ผด๋ณด๊ธฐ ์‹ซ๋„ค

Object.hash๋กœ ํ•œ ๋ฒˆ์— ๋ฌถ์œผ๋‹ˆ๊นŒ ์—„์ฒญ ๊น”๋”ํ•˜๋‹ค. ์›Œํ›„

์‹ค์ œ Object ์•ˆ์— ์žˆ๋Š” hash()์˜ hashCode()๋ฅผ ํƒ€๊ณ  ๋“ค์–ด๊ฐ€๋‹ˆ result ๋˜‘๊ฐ™์ด ์จ์ฃผ๋Š” ๊ฑฐ ๋ณด๋‹ˆ ๊ธฐ๋Šฅ์€ ๋™์ผํ•˜๊ตฌ๋‚˜. ๋‚˜ hashCode ๊ตฌํ˜„ํ•ด๋ณธ ์  ์—†๋Š”๋ฐ ํ ๋ฏ

์ผ๋‹จ ์ƒ๊ฐ์—๋Š” data class๋Š” hashCode(), equals(), toString() ๋“ฑ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋‹ˆ ๋ฌธ์ œ๋Š” ์—†์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค.



2๋ฒˆ์งธ ํฌ์ธํŠธ๋Š” ์—”ํ‹ฐํ‹ฐ์™€ ๋„๋ฉ”์ธ์˜ ์ฐจ์ด์— ๋Œ€ํ•œ ์ ์ธ๋ฐ.

ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ•™์Šตํ•˜๋ฉด์„œ ๊ณต๋ถ€ํ–ˆ๋˜ ๋ถ€๋ถ„์ด๋ผ ์Œ ์ •๋ฆฌํ•ด๋ณด์ž๋ฉด.

๋„๋ฉ”์ธ์€ ์ˆœ์ˆ˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋งŒ์„ ํ‘œํ˜„ํ•˜๊ณ  ์บก์Аํ™”๋˜์–ด์„œ ๊ธฐ๋Šฅ์ ์ธ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์„ค๊ณ„๋ฅผ ํ•œ๋‹ค๊ณ  ๋ณด๋ฉด ๋˜๊ณ 

์—”ํ‹ฐํ‹ฐ๋Š” ์™ธ๋ถ€์˜ ์ธํ”„๋ผ์— ํ•ด๋‹นํ•ด์„œ ๋‚ด๋ถ€ ์˜์—ญ์ธ ๋„๋ฉ”์ธ๊ณผ ๋ถ„๋ฆฌํ•ด์„œ ๊ตฌ์„ฑํ•œ๋‹ค.

์ตœ๊ทผ์— ๋๋‚œ ์šด์˜์ฒด์ œ ์Šคํ„ฐ๋””์—์„œ ๋‚˜๋ณด๋‹ค ์„ ๋ฐฐ ๊ฐœ๋ฐœ์ž๋ถ„๋“ค์ด JPA ์“ฐ๊ธฐ ์‹ซ๋‹ค ๊ผด๋„ ๋ณด๊ธฐ ์‹ซ๋‹ค ์ด๋Ÿฐ ์–˜๊ธฐ ์—„์ฒญ ํ•˜์…จ๋Š”๋ฐ ๊ฒฐ๊ตญ DB์— ์˜์กด์ ์ด๊ฒŒ ๋˜๊ณ , JPA์— ์˜์กด์ ์ด๊ฒŒ ๋˜์„œ ๊ทธ ๋ถ€๋ถ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด์Šˆ์— ์ง„์ €๋ฆฌ(?)๊ฐ€ ๋‚˜์‹  ๊ฑฐ ๊ฐ™์•˜๋‹ค.

์—ฌํŠผ ํ—ฅ์‚ฌ๊ณ ๋‚ ์€ ๋‚ด๋ถ€์™€ ์™ธ๋ถ€๋ฅผ ๋‚˜๋ˆ ์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ํ‘œํ˜„ ๋กœ์ง์ด๋‚˜ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์— ์˜์กดํ•˜์ง€ ์•Š๊ฒŒ ๋งŒ๋“œ๋Š”๊ฒŒ ํฌ์ธํŠธ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์—ฌ๊ธฐ์„œ ๋‚ด๋ถ€์— ํ•ด๋‹นํ•˜๋Š”๊ฒŒ ๋„๋ฉ”์ธ! ์™ธ๋ถ€์— ํ•ด๋‹นํ•˜๋Š”๊ฒŒ ์—”ํ‹ฐํ‹ฐ๋ผ๊ณ  ๋ณด๋ฉด ๋  ๊ฑฐ ๊ฐ™๋‹ค!



๋ผ๊ณ  ์ผ์—ˆ๋Š”๋ฐ ํŠธ์นœ๋‹˜์ด ์ค€ ํ•œ ๋ฉ˜์…˜์œผ๋กœ ๋ธ”๋กœ๊ทธ ๊ธ€์„ ์ข€ ๋” ์ž์„ธํžˆ ์จ์•ผ ๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

image


๋ฃฐ๋ฃจ๋ž„๋ผ ๋ธ”๋กœ๊ทธ ๊ธ€ ์“ฐ๊ณ  ์ € ๊ธ€ ์ผ์–ด์š”! ํ•˜๊ณ  ํŠธ์œ„ํ„ฐ์— ์˜ฌ๋ ธ๋‹ค๊ฐ€ ์—”ํ‹ฐํ‹ฐ ์šฉ์–ด๊ฐ€ DDD์—์„œ ๋งํ•˜๋Š” ๊ฒƒ๊ณผ ํ—ท๊ฐˆ๋ฆด ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๋ง์„ ๋“ฃ๊ณ  ๋ ์˜น!!! ํ–ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๊ธ‰ ๊ณต๋ถ€ํ•ด์„œ ์ถ”๊ฐ€ํ•ด ๊ธ€์„ ์“ฐ๊ฒŒ ๋๋‹ค.


์ผ๋‹จ ๋‚˜๋Š” DDD๋ฅผ ์ž˜ ๋ชจ๋ฅด๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ๋„๋ฉ”์ธ, ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ƒ๊ฐํ•˜๊ณ  ์œ„์˜ ๊ธ€์„ ์ผ๋‹ค.

๋„๋ฉ”์ธ โ†’ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง

์—”ํ‹ฐํ‹ฐ โ†’ ์˜์†์„ฑ ๋กœ์ง

ํŠธ์นœ๋‹˜์ด ๋งํ•ด์ฃผ์‹  ๋ถ€๋ถ„์€ ์—”ํ‹ฐํ‹ฐ๋ผ๋Š” ์šฉ์–ด๊ฐ€ DDD์—์„œ ์ธํ”„๋ผ ์˜์—ญ์ด ์•„๋‹Œ Domain Model์˜ ํ•œ ์ข…๋ฅ˜๋ผ๋Š”! ๋ง์ด์—ˆ๋‹ค. ์Œ ์„ค๋กœ์ธ์— ์งˆ๋ฌธ์œผ๋กœ ๋‚˜์˜จ ํŒŒ์ผ์ด @Table ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด์„œ ๋‹น์—ฐํžˆ ์ธํ”„๋ผ ์˜์—ญ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๊ธ€์„ ์ผ๋Š”๋ฐ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ๋‚ด๊ฐ€ ์ด context๋ฅผ ์œ„์— ์„ค๋ช…ํ•˜์ง€ ์•Š๊ณ  ๊ธ€์„ ์ผ๊ตฌ๋‚˜! ์‹ถ์—ˆ๋‹ค.


๊ทธ๋ž˜์„œ ๋ฐ‘์—์„œ์ง€๋งŒ ์ถ”๊ฐ€๋ฅผ ํ•˜์ž๋ฉด ์œ„์˜ ์งˆ๋ฌธ์€ ์•„๋ž˜ ์ฝ”๋“œ์— ์žˆ๋˜ ์ฃผ์„์ด์—ˆ๋‹ค.

// ๋„๋ฉ”์ธ ๊ฐ์ฒด ์ƒ์„ฑ์— ์—ฌ๋Ÿฌ ํ•„๋“œ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆ๊ฐ€ํ”ผ
@Suppress("LongParameterList")
@Table("users")
// POINT: ์ด ํด๋ž˜์Šค๋ฅผ data class ๋กœ ์„ ์–ธํ•˜๊ณ , equals / hashCode ๋ฅผ ์‚ญ์ œํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ์—†์„๊นŒ์š”?
// POINT: Entity ์™€ Domain Model ์˜ ์ฐจ์ด๋ž€ ๋ญ˜๊นŒ์š”?
internal class UserEntity constructor(
    @get:Id
    var id: Long? = null,
    override val uuid: UUID,
    nickname: String,
    profileImageUrl: String,
    override var deletedAt: Instant?,
    override var createdAt: Instant,
    updatedAt: Instant,
    override var version: Long,
) : User.Editor {
    override var nickname: String = ""
        set(value) {
            field = value
            this.updatedAt = Instant.now()
        }
์ƒ๋žต ...


๊ทธ๋Ÿฐ๋ฐ DDD์—์„œ ๋งํ•˜๋Š” Entity๊ฐ€ ๋ญ˜๊นŒ? ๊ฐ‘์ž๊ธฐ ๊ถ๊ธˆํ•ด์ ธ์„œ ๊ฒ€์ƒ‰์„ ํ•ด๋ดค๋‹ค.

์œ„ ๊ธ€์€ ์—๋ฆญ ์—๋ฐ˜์Šจ์˜ ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„ CH5์—์„œ ๋ฐœ์ทŒ๋œ ๊ธ€์ด๋ผ๊ณ  ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ๋Š”

  • identity(ID)๋กœ ์ฃผ๋กœ ์ •์˜๋˜๋Š” ๊ฐ์ฒด์ด๊ณ 
  • ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ํ†ตํ•ด ์—ฐ์†์„ฑ์„ ๊ฐ–๊ณ (?)
  • ์•ฑ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ์ค‘์š”ํ•œ ํŠน์„ฑ์— ๊ตฌ๋ณ„๋˜๋Š” ๋…๋ฆฝ์ ์ด์–ด์•ผ ํ•œ๋‹ค๊ณ .

์ด๊ฒŒ ๋ญ” ๊ฐœ ํ’€ ๋œฏ์–ด ๋จน๋Š” ์†Œ๋ฆฌ์ง€?


์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ์— ์ด๋Ÿฐ ์˜ˆ์‹œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€ ์–ด๋–ค ์งˆ๋ฌธ๊ธ€์— ๋Œ€ํ•ด์„œ ์•ˆ์˜ ๋‚ด์šฉ์„ ๋ฐ”๊พธ๊ฑด ๊ทธ ๊ธ€์˜ ์ œ๋ชฉ์„ ๋ฐ”๊พธ๊ฑด ๋”ฐ๋ด‰ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ฃผ๋“  ๊ทธ๊ฑด ์—ฌ์ „ํžˆ ๊ฐ™์€ ์งˆ๋ฌธ์ด๋‹ค. ๊ณผ๊ฑฐ์˜ ํ…์ŠคํŠธ์—์„œ ํ˜„์žฌ์˜ ํ…์ŠคํŠธ๋กœ ์—ฌ์ „ํžˆ ์ง„ํ–‰๋˜๊ณ  ์žˆ๋‹ค. ํ…์ŠคํŠธ๋Š” ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๋ณ€ํ•œ๋‹ค.

๋„๋ฉ”์ธ ๋ชจ๋ธ์—์„œ์˜ ๊ฐ„๋‹จํ•œ ์—”ํ‹ฐํ‹ฐ๋Š” RDBMS์˜ ์—”ํ‹ฐํ‹ฐ์— ๋งคํ•‘๋  ์ˆ˜๋„ ์žˆ์œผ๋‚˜ ๊ผญ ๊ทธ๋Ÿฐ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์ •ํ™•ํžˆ ์–˜๊ธฐํ•˜๋ฉด, ์šฐ๋ฆฌ๋Š” ๋ฐ˜๋“œ์‹œ ์—”ํ‹ฐํ‹ฐ์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋‹จ์ผ ํ–‰์— ์ €์žฅํ•œ๋‹ค. ํ•˜์ง€๋งŒ ํ•ด๋‹น ์ƒํƒœ์— ์ปฌ๋ ‰์…˜์ด ํฌํ•จ๋œ๋‹ค๋ฉด ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์˜ ๋‹ค์ˆ˜์˜ ํ–‰์„ ํ†ตํ•ด ๋ถ„์‚ฐ๋  ๊ฒƒ์ด๋‹ค.(์ฆ‰, ํ•œ ์—”ํ‹ฐํ‹ฐ์—๋งŒ ์ข…์†๋˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค ๋ผ๋Š” ์–˜๊ธฐ์ธ ๋“ฏ)

์™€ ์ด๊ฑธ ๋ด๋„ ์ดํ•ด๊ฐ€ ์•ˆ ๊ฐ€์ง€๋งŒ ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ๋Š” ์•„๋งˆ๋„ ๋‹ค์ˆ˜์˜ ํ…Œ์ด๋ธ”์˜ ์ƒํƒœ๋กœ ๋ถ„์‚ฐ๋  ์ˆ˜ ์žˆ์œผ๋‹ˆ ํ•œ ์—”ํ‹ฐํ‹ฐ๋กœ ๋ฐ˜๋“œ์‹œ ๋งคํ•‘๋˜์ง€ ์•Š์Œ์„ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.


์ข€ ๋” ๊ฒ€์ƒ‰ํ•˜๋‹ค๊ฐ€ ๋งˆํ‹ด ํŒŒ์šธ๋Ÿฌ์˜ ๋ธ”๋กœ๊ทธ ๊ธ€์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.

๐Ÿง”โ€โ™‚๏ธ Entity: 
Objects that have a distinct identity that runs through time and different representations. 
You also hear these called "reference objects".

์œ„์—์„œ์™€ ๋น„์Šทํ•œ ์—”ํ‹ฐํ‹ฐ ์„ค๋ช…์ธ๋ฐ

  • ์‹œ๊ฐ„์— ๋”ฐ๋ผ, ๋‹ค๋ฅธ ํ‘œํ˜„์— ๋”ฐ๋ผ ๊ณ ์œ  ์ •์ฒด์„ฑ์„ ๊ฐ€์ง„ ๊ฐ์ฒด
  • ์ฐธ์กฐ ๊ฐ์ฒด๋ผ๊ณ ๋„ ๋“ค์–ด๋ดค์ง€? ๊ทธ๋ ‡๊ฒŒ ๋ถ€๋ฅด๊ธฐ๋„ ํ•ด.

์ € ๊ธ€์—์„œ runs through time ์„ ์–ด๋–ป๊ฒŒ ํ•ด์„ํ•ด์•ผ ํ•˜๋Š”๊ฑฐ์ง€? ์‹œ๊ฐ„์„ ๋”ฐ๋ผ ๋‹ฌ๋ฆฌ๋Š” ์†Œ๋…€?

์นœ์ ˆํ•œ ๋งˆํ‹ด ์•„์ €์”จ๊ฐ€ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด์ฃผ์‹ ๋‹ค.

๐Ÿง”โ€โ™‚๏ธ 
Entities are usually big things like Customer, Ship, Rental Agreement. 
Values are usually little things like Date, Money, Database Query.
Services are usually accesses to external resources like Database Connection, Messaging Gateway, Repository, Product Factory.

์—”ํ‹ฐํ‹ฐ๋Š” ๋ณดํ†ต ํฐ ๊ฒƒ๋“ค์ธ๋ฐ ๊ณ ๊ฐ, ๋ฐฐ, ๋ Œํƒˆ ๊ณ„์•ฝ ๊ฐ™์€๊ฑฐ์•ผ.

๊ฐ’์€ ๋ณดํ†ต ์ž‘์€ ๊ฒƒ๋“ค์ธ๋ฐ ๋‚ ์งœ, ๋ˆ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ๊ฐ™์€๊ฑฐ์•ผ.

์„œ๋น„์Šค๋Š” ๋ณดํ†ต ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์ด๋‚˜ ๋ฉ”์‹œ์ง• ๊ฒŒ์ดํŠธ์›จ์ด, ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ ๊ฐ™์€ ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ ๊ฐ™์€๊ฑฐ์•ผ.

์–ด์งธ Entity, Value Object(VO), Service๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์นœ์ ˆํžˆ ๊ตฌ๋ถ„ํ•ด์ฃผ์‹ ๋‹ค.

๊ทผ๋ฐ ๋งˆ์ง€๋ง‰์— ์ถฉ๊ฒฉ์ ์ธ ์†Œ์‹์„ ํ•˜๋‚˜ ์ „๋‹ฌํ•ด์ฃผ์‹ ๋‹ค.

๐Ÿง”โ€โ™‚๏ธ 
One of the problems with this area is that this terminology, although evocative, gets terribly muddled up with other ideas. 
Entity is often used to represent a database table or an object that corresponds to a database table. 
So if I use these terms I have to make it clear I'm using them within the context of Domain Models and according to their meaning within Eric's book. S
o be wary of assuming people are using these words like this - they are heavily overloaded. 
Sadly there's not much alternative.

DDD์˜ ์—”ํ‹ฐํ‹ฐ์˜ ๋ฌธ์ œ๋Š” ๋”์ฐํ•˜๊ฒŒ๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋งํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ์™€ ๊ฐœ๋…์ด ๋‹ค๋ฅด๋‹จ๋‹ค!

๊ทธ๋ž˜์„œ ๋‚˜๋Š” ์ด๊ฑธ ์„ค๋ช…ํ•  ๋•Œ ๋งค๋ฒˆ ์—๋ฆญ์˜ DDD์˜ ์—”ํ‹ฐํ‹ฐ๋ผ๊ณ  ๋ฏธ๋ฆฌ ์–ธ๊ธ‰ํ•˜๊ณ  ์–˜๊ธฐํ•ด ใ…‡ใ…‡.

์ด ๊ฐœ๋…์„ ๋‹ค๋ฅด๊ฒŒ ์ƒ๊ฐํ•ด์•ผ ํ•ด์„œ ๋จธ๋ฆฌ๊ฐ€ ํ„ฐ์งˆ ๊ฑฐ ๊ฐ™์ง€?

๊ทผ๋ฐ ์Šฌํ”„๊ฒŒ ๋Œ€์•ˆ์€ ์—†๋‹จ๋‹ค(?)

์ด๋Ÿฐ ๋งํ• 


๊ฒฐ๋ก 

DDD์—์„œ ๋งํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ๋ž€ ์†์„ฑ์ด ์•„๋‹Œ ID๋กœ ๊ตฌ๋ณ„๋˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งํ•˜๋Š” ๊ฒƒ ๊ฐ™์€๋ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์—”ํ‹ฐํ‹ฐ์™€ 100%๋กœ ์ผ์น˜ํ•˜๋Š” ๊ฐœ๋…์ด ์•„๋‹ˆ๋ž๋‹ˆ๋‹ค.

๋ณดํ†ต ์šฐ๋ฆฌ๊ฐ€๋‚ด๊ฐ€ ์ƒ๊ฐํ•˜๋Š” Entity๋Š” ORM์—์„œ ๋งํ•˜๋Š” Entity์ธ๋ฐ DB ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋  ๊ฑฐ ๊ฐ™๋‹ค. ๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ ๋ณดํ†ต ๊ฐ์ฒด๊ฐ€ ์–ธ์ œ, ์–ด๋””์„œ, ์–ด๋–ป๊ฒŒ ์ €์žฅ๋˜๋Š”์ง€๋ฅผ ๊ด€์‹ฌ์„ ๋‘๊ณ  ์žˆ๋‹ค.

DDD์˜ Entity๋Š” ์˜์†์„ฑ์— ๋Œ€ํ•ด์„œ๋Š” ๋ชจ๋ฅด๋Š” ๊ฐ์ฒด์ธ ๊ฑฐ ๊ฐ™๋‹ค.(์ธํ„ฐํŽ˜์ด์Šค ์ •๋„๋งŒ ์•Œ๊ณ  ์žˆ๋Š”๋“ฏ) ์˜์†์„ฑ์„ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ORM์—๋Š” ์ „ํ˜€ ๊ด€์‹ฌ์ด ์—†์ด ๊ฐ์ฒด๊ฐ€ ์–ด๋””์„œ ์–ด๋–ป๊ฒŒ ์ €์žฅ๋˜๋Š”์ง€์—” ๊ด€์‹ฌ์ด ์—†๋‹ค. ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ORM ๋งคํ•‘๋˜๋Š” ๊ฐ์ฒด๊ฐ€ ๋„๋ฉ”์ธ ๋ชจ๋ธ์ผ ๋•Œ ๊ฐ™์€ ๊ฐœ๋…์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜๋„ ์žˆ๊ธด ํ•œ ๊ฒƒ ๊ฐ™๋‹ค.(๋ญ” ์†Œ๋ฆฌ์•ผ)

์ถ”๊ฐ€ํ•ด์„œ ๋” ๊ณต๋ถ€ํ•ด๋ดค๋Š”๋ฐ ๋ญ”๊ฐ€ ๋”๋” ๋ฏธ๊ถ ์†์œผ๋กœ ๋“ค์–ด๊ฐ„ ๋А๋‚Œ์ด๋‹ค. ํ›„ํ›„ โ€ฆ



์•„ User ์—”ํ‹ฐํ‹ฐ Editor ํƒ€๊ณ  ๊ฐ”๋‹ค๊ฐ€ ๋˜ ์งˆ๋ฌธ ๋ฐœ๊ฒฌํ–ˆ๋‹ค. ์ด๊ฑด ๋‚ด์ผ ํ•˜๋Š” ๊ฑธ๋กœโ€ฆ

// POINT: ์™œ User ๋„๋ฉ”์ธ ๋ชจ๋ธ์„ mutable ๋กœ ์„ค๊ณ„ํ•˜์ง€ ์•Š๊ณ , ์ด๋Ÿฐ ํƒ€์ž…์„ ๋ณ„๋„๋กœ ๋งŒ๋“ค์—ˆ์„๊นŒ์š”?


์˜ค๋Š˜ ์•Œ ๊ฒŒ ๋œ ๊ฒƒ

  1. ์ƒˆ๋กœ ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค!
    1. javax_inject
    2. jsr305
    3. kover(์ด๊ฑด ์ฝ”ํ‹€๋ฆฐ ๋ธ”๋กœ๊ทธ์—์„œโ€ฆ)
  2. ๋ผ์ด์„ ์Šค ์ •์ฑ…

    CC BY-NC-SA - ๋‚˜์ค‘์— ๋‚ด๊ฐ€ ์ด๊ฑธ ์ง์ ‘ ํƒ€์ดํ•‘ํ•  ๋‚ ์ด ์˜ฌ๊นŒ?

  3. ์„ค๋กœ์ธ ์ฝ”๋“œ์—๋Š” ์งˆ๋ฌธ์ด ์‚ฐ๋‹ค!(๊ทธ๊ฒƒ๋„ ์—„์ฒญ ๋งŽ์ด!!)


๋‹ค์Œ์— ํ•  ๊ฒƒ

  1. User Domain ๋ชจ๋ธ์„ ๋ฎคํ„ฐ๋ธ”ํ•˜๊ฒŒ ์„ค๊ณ„ํ•˜๋ฉด ๋‹น์—ฐํžˆ ์•„๋ฌด๋ฐ์„œ๋‚˜ ์•„๋ฌด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด ํด๋ž˜์Šค๋ฅผ ์ฐธ์กฐํ•ด์„œ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฝ”๋“œ๊ฐ€ ๊ฐœํŒ๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง€๊ฒ ์ง€? ๊ทธ๋‹ˆ๊นŒ ๋„๋ฉ”์ธ์—์„œ fun์„ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์„œ ํ•„๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์•„๋‹ˆ๋ฉด ์—ฌ๊ธฐ ์žˆ๋Š” ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๊ฒ ๋‹ค. ์ด๋ ‡๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค ๋งŒ๋“ ๊ฑฐ ์ฒ˜์Œ ๋ณด๋Š”๋ฐ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด์„œ ์ˆ˜์ •ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ๋„ ์ฝ”๋“œ ๋ถ„๋ฆฌํ•˜๋Š” ๋ฉด์—์„œ๋„ ์ข‹๊ณ  ๋ช…์„ธ๋กœ์„œ๋„ ์ข‹์„ ๊ฑฐ ๊ฐ™๊ธด ํ•˜๋‹ค.

  2. ์•„ ๊ทธ๋ฆฌ๊ณ  ์„ค๋กœ์ธ์— jvm lib๊ฐ€ ๋”ฐ๋กœ ์žˆ์–ด์„œ ๊ทธ๊ฒŒ ๊ถ๊ธˆํ•ด์„œ ๋‚ด์ผ ๋ณผ๊นŒ ์‹ถ๋‹ค. ํ ๋ฏ

    ์›๋ž˜ ์˜ค๋Š˜ ๊ทธ๊ฑฐ ๋ณด๋ คํ–ˆ๋Š”๋ฐ ๋œฌ๊ธˆ ์—†์ด ์งˆ๋ฌธ ๋ฐœ๊ฒฌํ•ด์„œ ์‹œ๊ฐ„์ด ๋งŽ์ด ์ง€๋‚˜๋ฒ„๋ ธ๋„ค.

๊ฒฐ๋ก 

์˜ค๋Š˜๋„ ์žฌ๋ฏธ๊ฐ€ ์žˆ์—ˆ๋‹ค~!

(real mysql 1๊ถŒ ์ฝ๊ธฐ ์‹ซ๋‹ค!!)