πŸš€ λ³΅μž‘ν•œ μ‹œμŠ€ν…œμ„ λ‹€λ£¨λŠ” 4κ°€μ§€ 핡심 κ°œλ…

Dev96Β·2025λ…„ 9μ›” 17일
post-thumbnail

ν˜„λŒ€μ˜ μ†Œν”„νŠΈμ›¨μ–΄λŠ” λ‹¨μˆœ CRUDλ₯Ό λ„˜μ–΄μ„œ λ³΅μž‘ν•œ 도메인 둜직과 높은 ν™•μž₯μ„± μš”κ΅¬λ₯Ό λ™μ‹œμ— λ§Œμ‘±ν•΄μ•Ό ν•©λ‹ˆλ‹€.
이 κ³Όμ •μ—μ„œ 자주 λ“±μž₯ν•˜λŠ” κ°œλ…μ΄ λ°”λ‘œ DDD, μ—κ·Έλ¦¬κ±°νŠΈ(Aggregate), λ°”μš΄λ””λ“œ μ»¨ν…μŠ€νŠΈ(Bounded Context), CQRS, 이벀트 μ†Œμ‹±(Event Sourcing) μž…λ‹ˆλ‹€.

이 κΈ€μ—μ„œλŠ” 이 λ‹€μ„― κ°€μ§€ κ°œλ…μ΄ μ–΄λ–»κ²Œ μ—°κ²°λ˜λŠ”μ§€ 큰 κ·Έλ¦Όκ³Ό 흐름을 닀루도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.


πŸ“– 1. DDD (Domain-Driven Design)

DDD의 핡심은 도메인 전문가와 κ°œλ°œμžκ°€ 같은 μ–Έμ–΄(μœ λΉ„μΏΌν„°μŠ€ μ–Έμ–΄)λ₯Ό μ‚¬μš©ν•˜μ—¬ μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό μ„€κ³„ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.
λ‹¨μˆœν•œ 데이터 쀑심 섀계가 μ•„λ‹ˆλΌ 도메인 둜직 μ€‘μ‹¬μœΌλ‘œ λͺ¨λΈμ„ λ§Œλ“€κ³ , μ½”λ“œμ™€ λΉ„μ¦ˆλ‹ˆμŠ€ κ°œλ…μ΄ μΌμΉ˜ν•˜λ„λ‘ ν•˜λŠ” 것이 λͺ©ν‘œμž…λ‹ˆλ‹€.

DDD의 μ£Όμš” κ°œλ…:

  • μœ λΉ„μΏΌν„°μŠ€ μ–Έμ–΄: 도메인 전문가와 κ°œλ°œμžκ°€ κ³΅μœ ν•˜λŠ” μš©μ–΄ 체계
  • λ°”μš΄λ””λ“œ μ»¨ν…μŠ€νŠΈ: λͺ¨λΈμ˜ 경계λ₯Ό λͺ…ν™•νžˆ ν•˜μ—¬ ν˜Όλž€ λ°©μ§€
  • μ—κ·Έλ¦¬κ±°νŠΈ: 경계 λ‚΄λΆ€μ˜ 일관성을 μœ μ§€ν•˜λŠ” λ‹¨μœ„

πŸ“– 2. λ°”μš΄λ””λ“œ μ»¨ν…μŠ€νŠΈ (Bounded Context)

ν˜„μ‹€ μ„Έκ³„μ˜ λΉ„μ¦ˆλ‹ˆμŠ€λŠ” 크고 λ³΅μž‘ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ "νšŒμ›(Member)"μ΄λΌλŠ” 단어도
결제 μ‹œμŠ€ν…œμ—μ„œλŠ” "고객(Customer)"
인사 μ‹œμŠ€ν…œμ—μ„œλŠ” "직원(Employee)" 으둜 λ‹€λ₯΄κ²Œ 쓰일 수 μžˆμŠ΅λ‹ˆλ‹€.

이λ₯Ό ν•΄κ²°ν•˜λŠ” 방법이 λ°”μš΄λ””λ“œ μ»¨ν…μŠ€νŠΈμž…λ‹ˆλ‹€.

  • 각 μ»¨ν…μŠ€νŠΈλŠ” 자체적인 λͺ¨λΈκ³Ό 의미λ₯Ό κ°€μ§‘λ‹ˆλ‹€.
  • μ„œλ‘œ λ‹€λ₯Έ μ»¨ν…μŠ€νŠΈλŠ” λͺ…μ‹œμ μΈ μΈν„°νŽ˜μ΄μŠ€(API, 이벀트)둜 ν†΅μ‹ ν•©λ‹ˆλ‹€.
  • 결과적으둜 경계λ₯Ό λͺ…ν™•νžˆ λ‚˜λˆ”μœΌλ‘œμ¨ λͺ¨λΈμ˜ ν˜Όλž€κ³Ό μΆ©λŒμ„ μ€„μž…λ‹ˆλ‹€.

μ˜ˆμ‹œ)

            [ λΉ„μ¦ˆλ‹ˆμŠ€ 전체 도메인 ]
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚   νšŒμ‚¬ 운영   β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                                      β”‚
 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   결제 μ‹œμŠ€ν…œ                            인사 μ‹œμŠ€ν…œ 
   Payment BC                               HR BC     
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                                      β”‚
 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     Customer                               Employee     
      (고객)                                  (직원)       
    - 이름                                  - 이름        
    - κ²°μ œμˆ˜λ‹¨                              - λΆ€μ„œ        
    - ꡬ맀내역                              - κΈ‰μ—¬        
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                                      β”‚
        └──────────── λͺ…μ‹œμ  μΈν„°νŽ˜μ΄μŠ€(API/이벀트

πŸ“– 3. μ—κ·Έλ¦¬κ±°νŠΈ (Aggregate)

λ°”μš΄λ””λ“œ μ»¨ν…μŠ€νŠΈ λ‚΄λΆ€μ—μ„œλ„ λͺ¨λ“  객체가 λ’€μ—‰μΌœ 있으면 μœ μ§€λ³΄μˆ˜κ°€ μ–΄λ ΅μŠ΅λ‹ˆλ‹€.
κ·Έλž˜μ„œ 일관성 경계(Consistency Boundary)λ₯Ό μ •ν•˜κ³  κ·Έ μ•ˆμ—μ„œ 항상 κ·œμΉ™μ΄ μ§€μΌœμ§€λ„λ‘ ν•˜λŠ” λ‹¨μœ„κ°€ μ—κ·Έλ¦¬κ±°νŠΈμž…λ‹ˆλ‹€.

  • Aggregate Root: μ™ΈλΆ€μ—μ„œ μ ‘κ·Ό κ°€λŠ₯ν•œ μœ μΌν•œ μ§„μž…μ 
  • λ‚΄λΆ€ μ—”ν‹°ν‹°(Value Object 포함): Rootλ₯Ό ν†΅ν•΄μ„œλ§Œ μ ‘κ·Ό/μˆ˜μ • κ°€λŠ₯

μ˜ˆμ‹œ)

  • Order (Root) + OrderItem (λ‚΄λΆ€ μ—”ν‹°ν‹°)
  • Post (Root) + Comment (λ‚΄λΆ€ μ—”ν‹°ν‹°)
  • Account (Root) + Transaction (λ‚΄λΆ€ μ—”ν‹°ν‹°)

πŸ‘‰ 핡심은 νŠΈλžœμž­μ…˜μ€ Aggregate λ‹¨μœ„λ‘œ 보μž₯λœλ‹€λŠ” μ μž…λ‹ˆλ‹€.


πŸ“– 4. CQRS (Command Query Responsibility Segregation)

일반적으둜 ν•˜λ‚˜μ˜ λͺ¨λΈλ‘œ 읽기와 μ“°κΈ°λ₯Ό λ™μ‹œμ— μ²˜λ¦¬ν•©λ‹ˆλ‹€.
ν•˜μ§€λ§Œ νŠΈλž˜ν”½μ΄ 컀지고 λ³΅μž‘λ„κ°€ μ˜¬λΌκ°€λ©΄ μ“°κΈ°(Command)와 읽기(Query)λ₯Ό λΆ„λ¦¬ν•˜λŠ” CQRS νŒ¨ν„΄μ΄ λ“±μž₯ν•©λ‹ˆλ‹€.

  • Command λͺ¨λΈ: μƒνƒœ λ³€κ²½ λ‹΄λ‹Ή (도메인 κ·œμΉ™, νŠΈλžœμž­μ…˜)
  • Query λͺ¨λΈ: 데이터 쑰회 λ‹΄λ‹Ή (μ„±λŠ₯ μ΅œμ ν™”, 캐싱, 별도 μ €μž₯μ†Œ)

μž₯점:

  • 읽기와 μ“°κΈ°λ₯Ό λ”°λ‘œ ν™•μž₯ κ°€λŠ₯
  • λ³΅μž‘ν•œ 도메인 둜직과 λ‹¨μˆœ 쑰회 둜직 뢄리

단점:

  • κ²°κ΅­ Eventual Consistency(μ΅œμ’…μ  일관성) 문제λ₯Ό 닀뀄야 함
  • λ‹¨μˆœ CRUD μ‹œμŠ€ν…œμ—λŠ” κ³Όλ„ν•œ 섀계

μ˜ˆμ‹œ)

UserRepositoryλŠ” μ“°κΈ°μš© DB(JPA 기반)
UserReadRepositoryλŠ” 읽기용 DB(μΊμ‹œ or 쑰회 μ „μš© DB)둜 λ‚˜λˆŒ 수 μžˆλ‹€.

πŸ“– 5. 이벀트 μ†Œμ‹± (Event Sourcing)

일반적으둜 DBμ—λŠ” "ν˜„μž¬ μƒνƒœ"만 μ €μž₯ν•©λ‹ˆλ‹€.
이벀트 μ†Œμ‹±μ€ λ‹€λ₯Έ 접근을 νƒν•©λ‹ˆλ‹€. μƒνƒœ λ³€ν™”λ₯Ό λ§Œλ“  λͺ¨λ“  이벀트λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.

μž₯점:

  • λͺ¨λ“  λ³€κ²½ 이λ ₯을 100% 보쑴 (좔적 용이)
  • μ›ν•˜λŠ” μ‹œμ μ˜ μƒνƒœ 볡원 κ°€λŠ₯
  • 이벀트λ₯Ό λ‹€λ₯Έ μ‹œμŠ€ν…œμ— μ‰½κ²Œ 전달 κ°€λŠ₯ (이벀트 λ“œλ¦¬λΈ μ•„ν‚€ν…μ²˜)

단점:

  • μ΄λ²€νŠΈκ°€ λ§Žμ•„μ§€λ©΄ λ¦¬ν”Œλ ˆμ΄ λΉ„μš© λ°œμƒ β†’ μŠ€λƒ…μƒ· ν•„μš”
  • 이벀트 μŠ€ν‚€λ§ˆ μ§„ν™” 관리 어렀움

μ˜ˆμ‹œ)

μ‚¬μš©μžκ°€ 주문을 생성/결제/μ·¨μ†Œν•˜λŠ” 과정을 이벀트둜 μ €μž₯


πŸ“– 6. κ°œλ…λ“€μ˜ μ—°κ²°

이 λ‹€μ„― κ°€μ§€ κ°œλ…μ€ λ”°λ‘œ λ…ΈλŠ” 것이 μ•„λ‹ˆλΌ ν•˜λ‚˜μ˜ μŠ€ν† λ¦¬λ₯Ό μ΄λ£Ήλ‹ˆλ‹€.

  • DDD: λ³΅μž‘ν•œ 도메인을 닀루기 μœ„ν•œ μ² ν•™
  • λ°”μš΄λ””λ“œ μ»¨ν…μŠ€νŠΈ: λͺ¨λΈμ˜ 경계λ₯Ό λ‚˜λˆ„λŠ” 방법
  • μ—κ·Έλ¦¬κ±°νŠΈ: 경계 λ‚΄λΆ€μ˜ 일관성을 μ§€ν‚€λŠ” λ‹¨μœ„
  • CQRS: ν™•μž₯성을 μœ„ν•œ 읽기/μ“°κΈ° 뢄리
  • 이벀트 μ†Œμ‹±: CQRS와 잘 μ–΄μšΈλ¦¬λŠ” μƒνƒœ 관리 방식

DDD β†’ BC β†’ Aggregate β†’ CQRS β†’ Event Sourcing 이런 νλ¦„μœΌλ‘œ μ—°κ²°λ©λ‹ˆλ‹€.


πŸ“– 7. μ–Έμ œ μ“°λ©΄ μ’‹μ„κΉŒ?

  • λ‹¨μˆœν•œ CRUD μ„œλΉ„μŠ€ β†’ ν•„μš” μ—†μŒ (μ˜€λ²„μ—”μ§€λ‹ˆμ–΄λ§)
  • λ³΅μž‘ν•œ λΉ„μ¦ˆλ‹ˆμŠ€ κ·œμΉ™ + 높은 ν™•μž₯μ„± μš”κ΅¬ β†’ 적합
  • 금육, 이컀머슀, λ‘œκΉ…/좔적 μ‹œμŠ€ν…œ β†’ 이벀트 μ†Œμ‹± + CQRS κ°•λ ₯ μΆ”μ²œ

πŸ“– 8. 마무리

λͺ¨λ‘ λ³΅μž‘ν•œ 도메인을 효과적으둜 닀루기 μœ„ν•œ λ„κ΅¬μž…λ‹ˆλ‹€.
ν•˜μ§€λ§Œ "무쑰건 μ“°λŠ” νŒ¨ν„΄"이 μ•„λ‹ˆλΌ 도메인 νŠΉμ„±κ³Ό μš”κ΅¬μ‚¬ν•­μ— 맞좰 μ„ νƒμ μœΌλ‘œ μ μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.


ν˜Ήμ‹œ κΆκΈˆν•œ λΆ€λΆ„μ΄λ‚˜ 더 보고 싢은 μ£Όμ œκ°€ μžˆλ‹€λ©΄ λŒ“κΈ€λ‘œ λ‚¨κ²¨μ£Όμ„Έμš” πŸ™Œ

profile
λ‹€μ–‘ν•œ κ²½ν—˜κ³Ό μ‹€λ¬΄μ˜ 깊이둜 평가받고 싢은 μ‚¬λžŒλ“€μ„ μœ„ν•΄ κΈ°λ‘ν•©λ‹ˆλ‹€. μ‹€λ¬΄μ—μ„œ λΆ€λ”ͺ히며 배운 것듀이 κ°€μž₯ 였래 λ‚¨λŠ”λ‹€κ³  λ―ΏμŠ΅λ‹ˆλ‹€.

0개의 λŒ“κΈ€