๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Project ESG+AI/Tech Basics

24์ผ์ฐจ. IT ๊ฐœ๋… ์ •๋ฆฌ

by GreenJin_S2 2025. 11. 11.


์ŠคํŠธ๋ง๋ถ€ํŠธ์—์„œ DDD์ฒ ํ•™์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๊ฐœ๋ฐœํ•˜๋Š”๊ฒƒ๊ณผ EDD์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ์„ ๋น„๊ตํ•ด์ค˜

 

 

Spring Boot ํ™˜๊ฒฝ์—์„œ DDD(Domain-Driven Design, ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„) ์™€ EDD(Event-Driven Design, ์ด๋ฒคํŠธ ์ฃผ๋„ ์„ค๊ณ„) ๋Š” ๋ชจ๋‘ ๋Œ€๊ทœ๋ชจ ์‹œ์Šคํ…œ ์„ค๊ณ„์— ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ์ฒ ํ•™์ž…๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๋‘ ๋ฐฉ์‹์€ ๊ด€์ , ์ดˆ์ , ์•„ํ‚คํ…์ฒ˜ ๊ตฌ์„ฑ ๋ฐฉ์‹์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
์•„๋ž˜์— ๋น„๊ต๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ์ •๋ฆฌํ•ด๋“œ๋ฆด๊ฒŒ์š”.


๐Ÿงฉ ๊ฐœ์š” ๋น„๊ต

๊ตฌ๋ถ„DDD (๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„)EDD (์ด๋ฒคํŠธ ์ฃผ๋„ ์„ค๊ณ„)
ํ•ต์‹ฌ ๊ฐœ๋… ๋„๋ฉ”์ธ(๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง)์„ ์ค‘์‹ฌ์œผ๋กœ ์„ค๊ณ„ ์ด๋ฒคํŠธ(event)๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์‹œ์Šคํ…œ ๊ฐ„ ํ†ต์‹  ์„ค๊ณ„
์ฃผ์š” ๋ชฉ์  ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋ช…ํ™•ํžˆ ๋ชจ๋ธ๋ง ์‹œ์Šคํ…œ ๊ฐ„ ๋น„๋™๊ธฐ์  ์—ฐ๋™๊ณผ ํ™•์žฅ์„ฑ ํ™•๋ณด
์„ค๊ณ„ ์ดˆ์  ๋„๋ฉ”์ธ ๋ชจ๋ธ, ์• ๊ทธ๋ฆฌ๊ฒŒ์ž‡, ๋ฆฌํฌ์ง€ํ† ๋ฆฌ, ์„œ๋น„์Šค ์ด๋ฒคํŠธ ๋ฐœํ–‰(Publish)๊ณผ ๊ตฌ๋…(Subscribe) ํ๋ฆ„
์ฃผ์š” ๊ตฌ์„ฑ์š”์†Œ Entity, Value Object, Domain Service, Aggregate Root Event, Event Producer, Event Consumer, Message Broker
ํ†ต์‹  ๋ฐฉ์‹ ์ฃผ๋กœ ๋™๊ธฐ (๋ฉ”์„œ๋“œ ํ˜ธ์ถœ, REST ๋“ฑ) ๋น„๋™๊ธฐ (Kafka, RabbitMQ, Event Bus ๋“ฑ)
์ ํ•ฉํ•œ ์ƒํ™ฉ ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™ ์ค‘์‹ฌ์˜ ๋„๋ฉ”์ธ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ๊ฐ„ ๋น„๋™๊ธฐ ํ†ต์‹ ์ด ํ•„์š”ํ•œ ์‹œ์Šคํ…œ

โš™๏ธ Spring Boot ๊ธฐ๋ฐ˜ ๊ตฌํ˜„ ๊ด€์  ๋น„๊ต

๐ŸŸข DDD ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ ๋ฐฉ์‹

1. ๊ตฌ์กฐ ์˜ˆ์‹œ

 

2. ํŠน์ง•

  • ๋„๋ฉ”์ธ ์ค‘์‹ฌ์œผ๋กœ ํŒจํ‚ค์ง€๋ฅผ ๊ตฌ์„ฑํ•˜์—ฌ, ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์„ ์ฝ”๋“œ์— ๋ช…ํ™•ํžˆ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด Order ๋„๋ฉ”์ธ์˜ ์ƒํƒœ ๋ณ€ํ™”(OrderCreated, OrderPaid, OrderShipped)๋ฅผ ์—”ํ‹ฐํ‹ฐ ๋‚ด๋ถ€์—์„œ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฝ๊ณ , ๋„๋ฉ”์ธ ์ „๋ฌธ๊ฐ€(๊ธฐํš์ž)์™€์˜ ํ˜‘์—…์ด ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.

3. ๋‹จ์ 

  • ์ดˆ๊ธฐ ์„ค๊ณ„๊ฐ€ ๋ณต์žกํ•˜๊ณ , ๋„๋ฉ”์ธ ๋ชจ๋ธ๋ง์— ๋งŽ์€ ์‹œ๊ฐ„ ํˆฌ์ž ํ•„์š”
  • ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ์—” ๊ฒฝ๊ณ„ ์„ค์ •์ด ๋ชจํ˜ธํ•  ์ˆ˜ ์žˆ์Œ

๐ŸŸก EDD ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ ๋ฐฉ์‹

1. ๊ตฌ์กฐ ์˜ˆ์‹œ

 

2. ํŠน์ง•

  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์ด๋ฒคํŠธ ๋‹จ์œ„๋กœ ๋ถ„๋ฆฌ๋˜์–ด, ์„œ๋น„์Šค ๊ฐ„ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„์ง‘๋‹ˆ๋‹ค.
  • ์˜ˆ: ์ฃผ๋ฌธ ์ƒ์„ฑ → OrderCreatedEvent ๋ฐœํ–‰ → ์žฌ๊ณ  ์„œ๋น„์Šค์—์„œ ํ•ด๋‹น ์ด๋ฒคํŠธ ์†Œ๋น„
  • Spring Boot์—์„œ๋Š” Spring Cloud Stream, Kafka, RabbitMQ ๋“ฑ์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.

3. ๋‹จ์ 

  • ์ด๋ฒคํŠธ ํ๋ฆ„์„ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์›€ (๋””๋ฒ„๊น…, ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ๋ณต์žก)
  • ๋‹จ์ˆœํ•œ ์‹œ์Šคํ…œ์—์„œ๋Š” ์˜คํžˆ๋ ค ๊ณผ๋„ํ•œ ์„ค๊ณ„๊ฐ€ ๋  ์ˆ˜ ์žˆ์Œ

๐Ÿง  ๊ฒฐํ•ฉ ์ „๋žต (DDD + EDD)

์‚ฌ์‹ค ์ตœ๊ทผ์—๋Š” DDD์™€ EDD๋ฅผ ๊ฒฐํ•ฉํ•˜๋Š” ์„ค๊ณ„๊ฐ€ ๋งŽ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
DDD๋ฅผ ํ†ตํ•ด ๋„๋ฉ”์ธ ๋ชจ๋ธ์„ ๋ช…ํ™•ํžˆ ์ •์˜ํ•˜๊ณ , ๊ทธ ์•ˆ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋„๋ฉ”์ธ ์ด๋ฒคํŠธ๋ฅผ EDD๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

 
// DDD ๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ public class Order { private OrderId id; private Money totalPrice; private OrderStatus status; public OrderCreatedEvent create() { this.status = OrderStatus.CREATED; return new OrderCreatedEvent(this.id); } }
 
// EDD ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ @Component public class OrderEventHandler { @EventListener public void handle(OrderCreatedEvent event) { inventoryService.decreaseStock(event.getOrderId()); } }

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด

  • DDD์˜ ๋„๋ฉ”์ธ ๋ช…ํ™•์„ฑ
  • EDD์˜ ๋น„๋™๊ธฐ ํ™•์žฅ์„ฑ
    ์„ ๋™์‹œ์— ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ… ์ •๋ฆฌ ์š”์•ฝ

๊ตฌ๋ถ„DDDEDD
์ดˆ์  ๋„๋ฉ”์ธ ๋กœ์ง๊ณผ ๋ชจ๋ธ๋ง ์‹œ์Šคํ…œ ๊ฐ„ ์ด๋ฒคํŠธ ํ๋ฆ„
์žฅ์  ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ํ‘œํ˜„์— ๊ฐ•ํ•จ ์„œ๋น„์Šค ๊ฐ„ ํ™•์žฅ์„ฑ๊ณผ ๋А์Šจํ•œ ๊ฒฐํ•ฉ
๋‹จ์  ์ดˆ๊ธฐ ์„ค๊ณ„ ๋ณต์žก, ํ™•์žฅ์„ฑ ํ•œ๊ณ„ ์ถ”์  ์–ด๋ ค์›€, ํŠธ๋žœ์žญ์…˜ ๋ณต์žก
๊ถŒ์žฅ ์กฐํ•ฉ DDD ๊ธฐ๋ฐ˜ + ๋„๋ฉ”์ธ ์ด๋ฒคํŠธ๋ฅผ EDD๋กœ ์ฒ˜๋ฆฌ  

@Bean @component @controller @ service @repository @ entity ์ค‘์—์„œ ์„ฑ๊ฒฉ์ด ๋‹ค๋ฅธ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ๋ถ„๋ฆฌํ•ด์ฃผ๊ณ , ์ด๊ฑฐ๋“ค์ด ์Šคํ”„๋ง์˜ bean ๊ฐ์ฒด์™€ ์–ด๋–ค ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š”์ง€ ์•Œ๋ ค์ค˜

 

 

์Šคํ”„๋ง(Spring)์—์„œ @Bean, @Component, @Controller, @Service, @Repository, @Entity๋Š” ๋ชจ๋‘ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ •์˜ํ•˜๊ฑฐ๋‚˜ ๋“ฑ๋กํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด์ง€๋งŒ, ๊ทธ ์—ญํ• ๊ณผ ๋™์ž‘ ๋ฐฉ์‹์ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
ํŠนํžˆ, ์ด ์ค‘์—๋Š” Spring Bean๊ณผ ๋ฌด๊ด€ํ•˜๊ฑฐ๋‚˜ ๊ฐ„์ ‘์ ์œผ๋กœ๋งŒ ๊ด€๋ จ๋œ ๊ฒƒ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
์•„๋ž˜์— ์ •๋ฆฌํ•ด๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.


๐Ÿงฉ ๋จผ์ € ๋ถ„๋ฅ˜๋ถ€ํ„ฐ

๋ถ„๋ฅ˜์–ด๋…ธํ…Œ์ด์…˜์—ญํ• ์Šคํ”„๋ง Bean ๋“ฑ๋ก ์—ฌ๋ถ€
โœ… ์Šคํ”„๋ง ๋นˆ(Bean) ๊ด€๋ จ ๊ทธ๋ฃน @Component, @Controller, @Service, @Repository, @Bean ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ Spring IoC ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋˜๋Š” ๊ฐ์ฒด๋ฅผ ์ •์˜ Bean์œผ๋กœ ๋“ฑ๋ก๋จ
๐Ÿšซ ์„ฑ๊ฒฉ์ด ๋‹ค๋ฅธ ๊ทธ๋ฃน @Entity JPA์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋˜๋Š” ๋„๋ฉ”์ธ ๊ฐ์ฒด Bean์œผ๋กœ ๋“ฑ๋ก๋˜์ง€ ์•Š์Œ

๐ŸŸข 1. ์Šคํ”„๋ง ๋นˆ ๊ด€๋ จ ์–ด๋…ธํ…Œ์ด์…˜

์ด๋“ค์€ ๋ชจ๋‘ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด, ์ฆ‰ Spring Bean์„ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค.

๐Ÿ”ธ @Component

  • ์Šคํ”„๋ง์ด ๊ด€๋ฆฌํ•ด์•ผ ํ•  ๊ธฐ๋ณธ์ ์ธ ํด๋ž˜์Šค์— ๋ถ™์ด๋Š” ์–ด๋…ธํ…Œ์ด์…˜
  • ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ด๊ณ  ์ƒ์œ„ ๊ฐœ๋…
  • ์˜ˆ์‹œ:
  •  
    @Component
  • public class MailSender { ... }

๐Ÿ”ธ @Controller

  • @Component์˜ ํŠน์ˆ˜ํ™” ์–ด๋…ธํ…Œ์ด์…˜
  • ์›น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” MVC ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์ธ์‹
  • ์Šคํ”„๋ง์ด DispatcherServlet์„ ํ†ตํ•ด ์š”์ฒญ์„ ๋งคํ•‘ํ•จ
  • ์˜ˆ์‹œ:
  •  
    @Controller
  • public class UserController { ... }

๐Ÿ”ธ @Service

  • @Component์˜ ํŠน์ˆ˜ํ™”
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๋‹นํ•˜๋Š” ๊ณ„์ธต์„ ๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„
  • ํŠธ๋žœ์žญ์…˜์ด๋‚˜ ๋กœ๊น… ๋“ฑ AOP(๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ) ์ ์šฉ ์‹œ ์ธ์‹์— ์œ ๋ฆฌ
  • ์˜ˆ์‹œ:
  •  
    @Service
  • public class OrderService { ... }

๐Ÿ”ธ @Repository

  • @Component์˜ ํŠน์ˆ˜ํ™”
  • ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต(DAO) ์—์„œ ์‚ฌ์šฉ
  • ์Šคํ”„๋ง์ด JPA ์˜ˆ์™ธ๋ฅผ Spring DataAccessException์œผ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์ž๋™ ์ธ์‹
  • ์˜ˆ์‹œ:
  •  
    @Repository
  • public class OrderRepository { ... }

๐Ÿ”ธ @Bean

  • ์ง์ ‘ Bean์„ ์ƒ์„ฑํ•ด์„œ ๋“ฑ๋กํ•  ๋•Œ ์‚ฌ์šฉ
  • ๋ฉ”์„œ๋“œ ๋‹จ์œ„์—์„œ Bean์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, @Configuration ํด๋ž˜์Šค ์•ˆ์— ์„ ์–ธ๋จ
  • ์ฆ‰, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ˆ˜๋™์œผ๋กœ Bean์„ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ์‹
  • ์˜ˆ์‹œ:
  •  
    @Configuration
  • public class AppConfig { @Bean public MailSender mailSender() { return new MailSender(); } }

๐Ÿ“Œ ์ •๋ฆฌํ•˜์ž๋ฉด

  • @Component, @Controller, @Service, @Repository → ์ž๋™ ์Šค์บ”(Auto-detection) ์œผ๋กœ Bean ๋“ฑ๋ก
  • @Bean → ์ˆ˜๋™ ๋“ฑ๋ก(Explicit registration) ๋ฐฉ์‹

๐Ÿ”ด 2. ์„ฑ๊ฒฉ์ด ๋‹ค๋ฅธ ์–ด๋…ธํ…Œ์ด์…˜: @Entity

@Entity

  • JPA(Java Persistence API)์—์„œ DB ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋˜๋Š” ํด๋ž˜์Šค์ž„์„ ํ‘œ์‹œ
  • ์Šคํ”„๋ง ๋นˆ๊ณผ๋Š” ๋ณ„๊ฐœ์˜ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.
  • @Entity ๊ฐ์ฒด๋Š” ์Šคํ”„๋ง IoC ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์•„๋‹Œ JPA EntityManager์— ์˜ํ•ด ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ:
  •  
    @Entity
  • public class User { @Id private Long id; private String name; }

์ฆ‰,
๐Ÿ‘‰ @Entity๋Š” Spring Bean์ด ์•„๋‹ˆ๋ผ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ ˆ๋ฒจ์˜ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.


๐Ÿง  ์Šคํ”„๋ง Bean๊ณผ์˜ ๊ด€๊ณ„ ์š”์•ฝ

์–ด๋…ธํ…Œ์ด์…˜Bean ๋“ฑ๋ก ๋ฐฉ์‹๊ด€๋ฆฌ ์ฃผ์ฒด์ฃผ์š” ์—ญํ• 
@Component ์ž๋™ Spring IoC ์ผ๋ฐ˜ ์ปดํฌ๋„ŒํŠธ
@Controller ์ž๋™ Spring IoC ์›น ์š”์ฒญ ์ฒ˜๋ฆฌ
@Service ์ž๋™ Spring IoC ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ
@Repository ์ž๋™ Spring IoC ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต
@Bean ์ˆ˜๋™ Spring IoC ๋ช…์‹œ์  Bean ๋“ฑ๋ก
@Entity โŒ Bean ์•„๋‹˜ JPA EntityManager DB ๋งคํ•‘ ๊ฐ์ฒด

โœ… ๊ฒฐ๋ก  ์š”์•ฝ

  • @Component, @Controller, @Service, @Repository, @Bean → Spring Bean ๋“ฑ๋ก์šฉ
  • @Entity → JPA ์ „์šฉ, Spring Bean ์•„๋‹˜
  • ์Šคํ”„๋ง์—์„œ Bean์œผ๋กœ ๊ด€๋ฆฌ๋œ๋‹ค๋Š” ๊ฒƒ์€ IoC ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ฐ์ฒด์˜ ์ƒ์„ฑ, ์ดˆ๊ธฐํ™”, ์ฃผ์ž…, ์†Œ๋ฉธ์„ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.