nika-blog

๐Ÿ— ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„(DDD) - ํŒŒํŠธ 2 ๋ชจ๋ธ ์ฃผ๋„ ์„ค๊ณ„์˜ ๋นŒ๋”ฉ ๋ธ”๋ก w. ์ฝ”๋“œ ๋ณธ๋ฌธ

์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

๐Ÿ— ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„(DDD) - ํŒŒํŠธ 2 ๋ชจ๋ธ ์ฃผ๋„ ์„ค๊ณ„์˜ ๋นŒ๋”ฉ ๋ธ”๋ก w. ์ฝ”๋“œ

nika0 2025. 2. 23. 17:35

๐ŸŽฏ ๋„๋ฉ”์ธ ๋ชจ๋ธ๊ณผ ์ฝ”๋“œ์˜ ๊ด€๊ณ„

๐Ÿ“Œ DDD์˜ ํ•ต์‹ฌ ์›์น™:
"๋„๋ฉ”์ธ ๋ชจ๋ธ๊ณผ ์ฝ”๋“œ๋Š” ๊ฐ™์€ ์˜๋ฏธ๋ฅผ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค."
์ฆ‰, ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ๋„๋ฉ”์ธ ๋ชจ๋ธ์„ ๋ฐ˜์˜ํ•ด์•ผ ํ•˜๋ฉฐ, ๋ณ„๋„๋กœ ๋ฌธ์„œ๋ฅผ ์œ ์ง€๋ณด์ˆ˜ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์•ผ ํ•จ.

โœ… ํ•ด๊ฒฐํ•ด์•ผ ํ•  ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ
1๏ธโƒฃ ์š”๊ตฌ์‚ฌํ•ญ์— ์ ํ•ฉํ•œ ๋ชจ์Šต์œผ๋กœ ๋„๋ฉ”์ธ์„ ์–ด๋–ป๊ฒŒ ๋ชจ๋ธ๋งํ•  ๊ฒƒ์ธ๊ฐ€?
2๏ธโƒฃ ๋„๋ฉ”์ธ์„ ๋ฐ˜์˜ํ•œ ์ฝ”๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฐœ๋ฐœํ•  ๊ฒƒ์ธ๊ฐ€?

๐Ÿ’ก ์ฝ”๋“œ๊ฐ€ ๋ฌธ์„œ ์—ญํ• ์„ ํ•œ๋‹ค๋ฉด?
โœ” ๋ณ€๊ฒฝ๋˜๋Š” ๋ฌธ์„œ๋ฅผ ๋”ฐ๋กœ ์œ ์ง€๋ณด์ˆ˜ํ•  ํ•„์š” ์—†์ด,
โœ” ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋„๋ฉ”์ธ ๋ชจ๋ธ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ.


๐Ÿ”จ ๋ชจ๋ธ ์ฃผ๋„ ์„ค๊ณ„์˜ ๋นŒ๋”ฉ ๋ธ”๋ก

๋นŒ๋”ฉ ๋ธ”๋ก์€ DDD๋ฅผ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•  ๋•Œ ๋ณต์žก๋„๋ฅผ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•œ ๊ฐ€์ด๋“œ๋ผ์ธ์ž…๋‹ˆ๋‹ค.

๐Ÿ“Œ ํ•„์ˆ˜์ ์ธ ๊ฐœ๋…์€ ์•„๋‹ˆ์ง€๋งŒ, ์ง๊ด€์ ์ธ ๊ฐ€์ด๋“œ ์—ญํ• ์„ ์ˆ˜ํ–‰

โœ… ๋„๋ฉ”์ธ์„ ํ‘œํ˜„ํ•˜๋Š” ๋นŒ๋”ฉ ๋ธ”๋ก

  • Association (์—ฐ๊ด€ ๊ด€๊ณ„)
  • Value Object (๊ฐ’ ๊ฐ์ฒด)
  • Entity (์—”ํ„ฐํ‹ฐ)
  • Service (์„œ๋น„์Šค)
  • Module (๋ชจ๋“ˆ)

โœ… ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋นŒ๋”ฉ ๋ธ”๋ก

  • Aggregate (์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ)
  • Repository (๋ฆฌํฌ์ง€ํ† ๋ฆฌ)
  • Factory (ํŒฉํ† ๋ฆฌ)

๐Ÿ’ก ๊ฒฐ๋ก : ๋„๋ฉ”์ธ์˜ ๊ฐœ๋…์„ ์ฝ”๋“œ๋กœ ์˜ฎ๊ธฐ๊ธฐ ์œ„ํ•œ ์ง๊ด€์ ์ธ ๊ฐ€์ด๋“œ!
โœ” ํ•˜์ง€๋งŒ ๋ฐ˜๋“œ์‹œ ์ด ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹˜.


๐Ÿ”„ ๋ถˆ๋ณ€์‹ (Invariant)

๐Ÿ“Œ ๋ถˆ๋ณ€์‹์ด๋ž€?
์ •์ƒ์ ์ธ ์ƒํƒœ๋ฅผ ๊ทœ์ •ํ•˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™
์ฆ‰, ๋„๋ฉ”์ธ ๋ชจ๋ธ์ด ํ•ญ์ƒ ์œ ์ง€ํ•ด์•ผ ํ•˜๋Š” ์กฐ๊ฑด

โœ… ์˜ˆ์ œ: ์Œ์‹ ์ฃผ๋ฌธ ์‹œ์Šคํ…œ
1๏ธโƒฃ ํŒ๋งค ์ค‘์ธ ๋ฉ”๋‰ด์—๋Š” ์˜ต์…˜ ๊ทธ๋ฃน์ด ํ•œ ๊ฐœ ์ด์ƒ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.

  • โœ… ์˜ˆ: "๊ณ ๊ธฐ 1์ธ ์„ธํŠธ"์—๋Š” ์‚ผ๊ฒน์‚ด/๋ชฉ์‚ด ์˜ต์…˜์ด ์žˆ์–ด์•ผ ํ•จ
    2๏ธโƒฃ ํŒ๋งค ์ค‘์ธ ๋ฉ”๋‰ด์˜ ์˜ต์…˜ ๊ฐ€๊ฒฉ์€ 0์› ์ด์ƒ์ด์–ด์•ผ ํ•œ๋‹ค.
  • โœ… ์˜ˆ: ์‚ผ๊ฒน์‚ด ์˜ต์…˜์ด 0์› ์ด์ƒ์ด์–ด์•ผ ํ•จ
    3๏ธโƒฃ ํŒ๋งค ์ค‘์ธ ๋ฉ”๋‰ด์—๋Š” ํ•„์ˆ˜ ์˜ต์…˜ ๊ทธ๋ฃน์ด ํ•œ ๊ฐœ ์ด์ƒ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.
  • โœ… ์˜ˆ: "๊ณ ๊ธฐ ์ข…๋ฅ˜" ์˜ต์…˜์€ ๋ฐ˜๋“œ์‹œ ์„ ํƒํ•ด์•ผ ํ•จ

๐Ÿ“Œ ๋ถˆ๋ณ€์‹์ด ๊ธฐํš ๋‹จ๊ณ„์—์„œ ๊ทœ์ •๋˜๊ธฐ ์–ด๋ ค์šด ์ด์œ 
โœ” ๊ธฐํš์—์„œ๋Š” ์„ธ๋ถ€์ ์ธ ์กฐ๊ฑด์„ ๋ชจ๋‘ ์ •์˜ํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ
โœ” ๊ฐœ๋ฐœํŒ€์ด ๊ตฌํ˜„ ๋‹จ๊ณ„์—์„œ ์ •ํ™•ํ•œ ๋ถˆ๋ณ€์‹์„ ๋„์ถœํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•จ


๐Ÿ”— ์—”ํ„ฐํ‹ฐ(Entity)์™€ ๊ฐ’ ๊ฐ์ฒด(Value Object)์˜ ์ฐจ์ด

๐Ÿ“Œ ์—”ํ„ฐํ‹ฐ(Entity): ์‹๋ณ„์„ฑ์ด ์ค‘์š”ํ•œ ๊ฐ์ฒด
โœ” ๋™์ผํ•œ ๊ฐ์ฒด๊ฐ€ ๊ณ„์† ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ
โœ” ๊ณ ์œ ํ•œ ID(์‹๋ณ„์ž)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ๋ถ„๋จ

โœ… ์˜ˆ์ œ
๐Ÿ’ฐ "๋‚ด๊ฐ€ ๋นŒ๋ ค์ค€ ๋งŒ ์›์งœ๋ฆฌ ์ง€ํ๋Š” ๋ฐ˜๋“œ์‹œ ๊ฐ™์€ ์ง€ํ์—ฌ์•ผ ํ•œ๋‹ค!"
โžก ์ด ๊ฒฝ์šฐ "ํ˜„๊ธˆ" ๊ฐ์ฒด๋Š” ์—”ํ„ฐํ‹ฐ(Entity)

 

๐Ÿ“Œ JPA ์—”ํ„ฐํ‹ฐ(Entity)์™€ DDD ์—”ํ„ฐํ‹ฐ๋Š” ๋‹ค๋ฅธ ๊ฐœ๋…
โœ” DDD ์—”ํ„ฐํ‹ฐ: ๋„๋ฉ”์ธ ํ–‰์œ„ ์ค‘์‹ฌ, ๋ถˆ๋ณ€์‹ ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„
โœ” JPA ์—”ํ„ฐํ‹ฐ: ํ…Œ์ด๋ธ” ๋งคํ•‘ ์ค‘์‹ฌ, ๋ฐ์ดํ„ฐ ์ €์žฅ์„ ์œ„ํ•œ ORM ๊ตฌ์กฐ

๐Ÿ’ก JPA๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์ 

  • JPA๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„๋จ
  • DDD์˜ ๊ฐœ๋…๊ณผ ์ถฉ๋Œํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Œ
  • ์—”ํ„ฐํ‹ฐ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์ •์˜ํ•ด์•ผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋†’์•„์ง

 

๐Ÿ“Œ ๊ฐ’ ๊ฐ์ฒด(Value Object): ์‹๋ณ„์„ฑ์ด ํ•„์š” ์—†๋Š” ๊ฐ์ฒด
โœ” ๊ฐ์ฒด์˜ ์†์„ฑ์ด ์ค‘์š”ํ•˜๊ณ , ๊ณ ์œ ํ•œ ์‹๋ณ„์ž๋Š” ํ•„์š” ์—†์Œ
โœ” ๊ฐ’์ด ๋™์ผํ•˜๋ฉด ๊ฐ™์€ ๊ฐ์ฒด๋กœ ๊ฐ„์ฃผ

โœ… ์˜ˆ์ œ
๐Ÿ’ณ "๋‚ด๊ฐ€ ๋นŒ๋ ค์ค€ ๋งŒ ์›์งœ๋ฆฌ ์ง€ํ๋ฅผ ๋„ค์ด๋ฒ„ ํŽ˜์ด๋กœ ๋ฐ›์•„๋„ ๋œ๋‹ค."
โžก ์ด ๊ฒฝ์šฐ "๊ธˆ์•ก(Money)"์€ ๊ฐ’ ๊ฐ์ฒด(Value Object)

๐Ÿ’ก ์—”ํ„ฐํ‹ฐ๋ณด๋‹ค ๊ฐ’ ๊ฐ์ฒด๊ฐ€ ๋” ๋‹ค๋ฃจ๊ธฐ ์‰ฌ์›€!
โžก ์ฒ˜์Œ์—๋Š” ๊ฐ’์„ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค๊ณ , ํ•„์š”ํ•  ๋•Œ ์—”ํ„ฐํ‹ฐ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ.

 

๐Ÿ’ก DDD ๊ด€์ ์—์„œ ๊ฐ’ ๊ฐ์ฒด๋Š” ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅ(Immutable)ํ•ด์•ผ ํ•œ๋‹ค.

  • ๋งŒ์•ฝ ๊ฐ’ ๊ฐ์ฒด์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค๋ฉด,
    ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•จ
  • DB ๊ด€์ ์—์„œ๋Š” trade-off๊ฐ€ ์žˆ์Œ
    • ๊ฐ’ ๊ฐ์ฒด๋ฅผ ์‚ญ์ œ ํ›„ ๋‹ค์‹œ ์ €์žฅํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒ
    • ํ•˜์ง€๋งŒ, DDD์—์„œ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋ชจ๋ธ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ค‘์š”

โœ… ์˜ˆ์ œ: ์ฃผ๋ฌธ ํ•ญ๋ชฉ(OrderItem)

  • price๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ, ๊ธฐ์กด OrderItem์„ ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ์šด OrderItem์„ ์ƒ์„ฑํ•ด์•ผ ํ•จ
  • DB์—์„œ๋Š” ์ด๋ฅผ UPDATE ๋Œ€์‹  DELETE + INSERT๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ

๐Ÿ”„ ์—ฐ๊ด€ ๊ด€๊ณ„์™€ ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ (Aggregate)

๐Ÿ“Œ ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ๋ž€?
โœ” ์—”ํ„ฐํ‹ฐ์™€ ๊ฐ’ ๊ฐ์ฒด๋ฅผ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ฌถ์–ด์„œ ๋‹จ์ˆœํ™”ํ•˜๋Š” ๊ฐœ๋…
โœ” ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์˜ ๋‹จ์œ„๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์—ญํ• 

๐Ÿ“Œ ์™œ ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ๊ฐ€ ํ•„์š”ํ• ๊นŒ?

  • ๋„๋ฉ”์ธ ๋ชจ๋ธ์ด ๋ณต์žกํ• ์ˆ˜๋ก, ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ๋‹จ์ˆœํ™”ํ•ด์•ผ ํ•จ
  • ์—”ํ„ฐํ‹ฐ ๊ฐ„ ์ง์ ‘์ ์ธ ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ๋งบ์œผ๋ฉด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์ง

โœ… ์˜ˆ์ œ: ์Œ์‹ ์ฃผ๋ฌธ ์‹œ์Šคํ…œ
โœ” "์ฃผ๋ฌธ(Order) - ์ฃผ๋ฌธ ํ•ญ๋ชฉ(OrderLineItem)"
โœ” ์ฃผ๋ฌธ ํ•ญ๋ชฉ์€ ์ฃผ๋ฌธ ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ ๋‚ด์—์„œ ๊ด€๋ฆฌ๋จ
โœ” ๊ณ ๊ฐ(Customer)๊ณผ ์ฃผ๋ฌธ(Order)์€ ๋ณ„๊ฐœ์˜ ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ๋กœ ๋ถ„๋ฆฌ

๐Ÿ’ก ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์ •์˜ํ•˜๋ฉด ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ์ตœ์†Œํ™”ํ•˜์—ฌ, ์ฝ”๋“œ ๋ณต์žก์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ์Œ.


๐Ÿ›  ์ฝ”๋“œ ์˜ˆ์ œ: ๋ฐฐ๋‹ฌ ๋„๋ฉ”์ธ

๐Ÿ›’ ์ฃผ๋ฌธ(Order) ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ

class Order {
  private orderId: string;
  private customerId: string;
  private items: OrderItem[];
  private status: OrderStatus;

  constructor(orderId: string, customerId: string, items: OrderItem[]) {
    if (items.length === 0) {
      throw new Error("์ฃผ๋ฌธ์—๋Š” ์ตœ์†Œ ํ•œ ๊ฐœ ์ด์ƒ์˜ ์ƒํ’ˆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.");
    }
    this.orderId = orderId;
    this.customerId = customerId;
    this.items = items;
    this.status = OrderStatus.PENDING;
  }

  completeOrder() {
    if (this.status !== OrderStatus.PENDING) {
      throw new Error("์ฃผ๋ฌธ์„ ์™„๋ฃŒํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.");
    }
    this.status = OrderStatus.COMPLETED;
  }
}

๐Ÿ” ์ฃผ๋ฌธ ํ•ญ๋ชฉ(OrderItem) - ๊ฐ’ ๊ฐ์ฒด

class OrderItem {
  private productId: string;
  private quantity: number;
  private price: number;

  constructor(productId: string, quantity: number, price: number) {
    if (quantity <= 0) {
      throw new Error("์ˆ˜๋Ÿ‰์€ 1๊ฐœ ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
    }
    if (price < 0) {
      throw new Error("๊ฐ€๊ฒฉ์€ 0์› ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
    }
    this.productId = productId;
    this.quantity = quantity;
    this.price = price;
  }

  getTotalPrice(): number {
    return this.quantity * this.price;
  }
}

 

๐Ÿ“ฆ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ (Repository)

class OrderRepository {
  private orders: Map<string, Order> = new Map();

  save(order: Order) {
    this.orders.set(order.getOrderId(), order);
  }

  findById(orderId: string): Order | undefined {
    return this.orders.get(orderId);
  }
}

 


๐Ÿ”ง Factory ํŒจํ„ด (๊ฐ์ฒด ์ƒ์„ฑ ๋กœ์ง์„ ๋ถ„๋ฆฌ)

๐Ÿ“Œ Factory ํŒจํ„ด์ด ํ•„์š”ํ•œ ์ด์œ 
โœ” ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ ์ƒ์„ฑ์ด ๋ณต์žกํ•  ๋•Œ, ์ด๋ฅผ ์บก์Аํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
โœ” ์™ธ๋ถ€ DB ์กฐํšŒ๊ฐ€ ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ๋ถˆ๋ณ€์‹์ด ๋ณต์žกํ•œ ๊ฒฝ์šฐ Factory๋กœ ์ด๊ด€

โœ… ์˜ˆ์ œ: ์žฅ๋ฐ”๊ตฌ๋‹ˆ (Cart)

 

class CartFactory {
  static createCart(customerId: string, items: CartItem[]): Cart {
    if (items.length === 0) {
      throw new Error("์žฅ๋ฐ”๊ตฌ๋‹ˆ์—๋Š” ์ตœ์†Œ ํ•œ ๊ฐœ์˜ ์ƒํ’ˆ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
    }
    return new Cart(customerId, items);
  }
}

 

๐Ÿ’ก Factory๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋„๋ฉ”์ธ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์„ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ.


๐ŸŽฏ ๋„๋ฉ”์ธ ์„œ๋น„์Šค (Domain Service)

๐Ÿ“Œ ๋„๋ฉ”์ธ ์„œ๋น„์Šค๋ž€?
โœ” ํŠน์ • ์—”ํ„ฐํ‹ฐ์— ์†ํ•˜์ง€ ์•Š๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋น„์Šค
โœ” ๊ฐ์ฒด ๊ฐ„์˜ ์ฑ…์ž„์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์„ ๋•Œ, ๋ณ„๋„์˜ ์„œ๋น„์Šค๋กœ ๋ถ„๋ฆฌ

โœ” ๊ผญ ํ•„์š”ํ•œ์ง€ ๊ฒ€ํ† ํ•ด ๋ณผ ํ•„์š” ์žˆ์Œ

โœ… ์˜ˆ์ œ: ํ• ์ธ ๋กœ์ง (Discount Service)

 

class DiscountService {
  static applyDiscount(order: Order, discountRate: number): number {
    if (discountRate < 0 || discountRate > 1) {
      throw new Error("ํ• ์ธ์œจ์€ 0~1 ์‚ฌ์ด์˜ ๊ฐ’์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
    }
    return order.getTotalPrice() * (1 - discountRate);
  }
}

 

๐Ÿ’ก ํŠน์ • ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ์— ํฌํ•จํ•˜๊ธฐ ์–ด๋ ค์šด ๋กœ์ง์„ ๋„๋ฉ”์ธ ์„œ๋น„์Šค๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ.


๐Ÿ† ๊ฒฐ๋ก : DDD์˜ ๋นŒ๋”ฉ ๋ธ”๋ก์„ ํ™œ์šฉํ•˜๋ฉด?

โœ… ๋„๋ฉ”์ธ ๋ชจ๋ธ๊ณผ ์ฝ”๋“œ๋ฅผ ์ผ์น˜์‹œ์ผœ ์œ ์ง€๋ณด์ˆ˜ ๋ถ€๋‹ด์„ ์ค„์ผ ์ˆ˜ ์žˆ์Œ
โœ… ์—”ํ„ฐํ‹ฐ์™€ ๊ฐ’ ๊ฐ์ฒด๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ์‹๋ณ„์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ
โœ… ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์˜ ๊ฒฝ๊ณ„๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Œ
โœ… Factory๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์„ ์บก์Аํ™”ํ•  ์ˆ˜ ์žˆ์Œ
โœ… ๋„๋ฉ”์ธ ์„œ๋น„์Šค๋กœ ํŠน์ • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿ’ก DDD์˜ ๋นŒ๋”ฉ ๋ธ”๋ก์€ ๋ณต์žกํ•œ ๋„๋ฉ”์ธ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ฐ•๋ ฅํ•œ ๊ฐ€์ด๋“œ์ž…๋‹ˆ๋‹ค! ๐Ÿš€