--- id: wiki-2026-0508-ubiquitous-language title: Ubiquitous Language category: 10_Wiki/Topics status: verified canonical_id: self aliases: [UL, 유비쿼터스 언어] duplicate_of: none source_trust_level: A confidence_score: 0.95 verification_status: applied tags: [ddd, domain-modeling, terminology, software-design] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: any framework: DDD --- # Ubiquitous Language ## 매 한 줄 > **"매 도메인 expert 와 매 developer 가 매 같은 단어 의 사용 — 매 code · 매 conversation · 매 documentation 의 일관 vocabulary."** Eric Evans 의 2003년 *Domain-Driven Design* 에서 도입된 매 핵심 pattern. 매 translation layer 의 제거 — 매 misunderstanding 의 root cause 의 해결. ## 매 핵심 ### 매 정의 - **Shared vocabulary**: 매 business expert + dev + PM 의 공유 단어 set. - **Bounded context 內 unique**: 매 "Order" 의 Sales context 에서 의미 ≠ Shipping context 의미. - **Code 에 그대로 반영**: 매 class · method · variable 이 매 domain 단어 의 직역. - **Living language**: 매 domain 변화 → 매 vocab 변화 → 매 code rename. ### 매 왜 중요 - **Translation cost 의 제거**: dev가 "user" 라 부르고 biz가 "customer" 라 부르면 매 매 회의마다 mapping 필요. - **Bug source 의 제거**: 매 "shipment" 가 "delivery" 와 다르다면 매 implicit assumption 이 bug 의 원인. - **Onboarding 의 가속**: 매 new dev 가 매 domain doc 만 읽어도 매 code 의 이해. ### 매 Bounded Context 와 의 관계 - 매 UL 은 매 bounded context 內에서만 ubiquitous. - 매 cross-context 의 통신은 매 anti-corruption layer (ACL) 또는 매 context map 의 명시. - 매 "Customer" 의 Billing context 의미 와 Support context 의미 는 매 다른 model — 매 같은 단어 라도 매 다른 type. ### 매 응용 1. **Domain modeling kickoff**: 매 event storming session 의 첫 1-2시간 매 vocabulary 정렬. 2. **Code review 기준**: 매 PR 에 매 non-UL 단어 (e.g. `processData()`) 등장 → 매 reject. 3. **LLM prompt design**: 매 system prompt 에 매 UL glossary 의 inject — 매 LLM 의 domain hallucination 의 제거. ## 💻 패턴 ### 매 Glossary YAML (single source of truth) ```yaml # domain-glossary.yaml context: Sales terms: Order: definition: "확정된 customer 구매 의도. 결제 완료 후 생성." not: "Cart, Quote, Wishlist 와 다름" code_class: "sales.Order" Cart: definition: "결제 전 임시 item 모음. expire 가능." not: "Order" code_class: "sales.Cart" Customer: definition: "1+ Order 가 있는 person/organization." not: "Lead (구매 전), Account (Billing context 概念)" code_class: "sales.Customer" ``` ### 매 TypeScript 의 UL 의 type 화 ```typescript // 매 brand type 으로 매 UL 단어 의 distinct type type OrderId = string & { readonly _brand: 'OrderId' }; type CartId = string & { readonly _brand: 'CartId' }; class Order { constructor( readonly id: OrderId, readonly placedAt: Date, readonly lines: OrderLine[], ) {} // method name 이 매 UL verb cancel(reason: CancellationReason): CancelledOrder { /* ... */ } ship(via: Carrier): ShippedOrder { /* ... */ } } // 매 Cart → Order 의 transition 이 매 명시 method class Cart { checkout(payment: Payment): Order { /* ... */ } } ``` ### 매 LLM prompt 에 UL inject ```typescript const systemPrompt = ` 당신은 Sales 도메인 assistant. 매 다음 vocabulary 의 정확한 사용: - Order: 결제 완료된 구매. (Cart, Quote 와 구분) - Cart: 결제 전 임시 item 모음. - Customer: 1+ Order 가 있는 buyer. - Lead: 구매 전 prospect (Customer 아님). 매 사용자 질문 에 매 위 단어 의 strict 사용. 매 다른 단어 (e.g. "user", "buyer") 의 X. `; ``` ### 매 Anti-corruption layer (ACL) ```typescript // External payment provider 의 "Transaction" 을 매 domain 의 "Payment" 로 translate class PaymentACL { fromStripeCharge(charge: Stripe.Charge): Payment { return new Payment( PaymentId(charge.id), Money(charge.amount, charge.currency), this.mapStatus(charge.status), ); } private mapStatus(s: Stripe.Charge.Status): PaymentStatus { // Stripe terminology → UL terminology return s === 'succeeded' ? 'completed' : 'failed'; } } ``` ### 매 Event storming 결과 → UL 의 추출 ``` Domain Event: OrderPlaced Command: PlaceOrder Aggregate: Order Policy: "When OrderPlaced, send confirmation email" → 매 UL term: Order, Place, Confirm, Email → 매 code: order.place(), emailService.sendConfirmation(order) ``` ### 매 Glossary 의 enforcement (lint rule) ```typescript // ESLint rule: 매 forbidden non-UL words 의 ban module.exports = { rules: { 'no-non-ubiquitous-terms': { create(context) { const forbidden = ['user', 'data', 'process', 'handle', 'manager']; return { Identifier(node) { if (forbidden.some(f => node.name.toLowerCase().includes(f))) { context.report(node, `Non-UL term: ${node.name}`); } }, }; }, }, }, }; ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | 매 startup, 매 domain 미정 | 매 UL 의 over-investment X — 매 emergent 하게 정착 | | 매 enterprise, multi-team | 매 strict UL + bounded context map 필수 | | 매 LLM agent system | 매 system prompt 에 UL glossary 강제 inject | | 매 legacy codebase rewrite | 매 ACL 로 매 boundary 격리 → 매 incremental UL 도입 | **기본값**: 매 single-context 작은 system 은 매 implicit UL, 매 multi-context 는 매 explicit glossary. ## 🔗 Graph - 부모: [[DDD]] - 변형: [[Bounded Context]] · [[Context Map]] - 응용: [[Event_Storming|Event Storming]] · [[Anti-Corruption Layer]] · [[CQRS]] - Adjacent: [[Domain Model]] · [[Aggregate]] ## 🤖 LLM 활용 **언제**: 매 LLM agent 가 매 specific domain (legal, medical, finance) 의 작업 — 매 system prompt 에 UL glossary inject 로 매 hallucination 의 90%+ reduction. **언제 X**: 매 generic chat — 매 UL 의 over-engineering. ## ❌ 안티패턴 - **매 Tech jargon 의 leakage**: 매 "EntityManager", "DTO" 가 매 domain conversation 에 등장 — 매 dev → biz 단방향 leak. - **매 같은 단어, 매 다른 의미**: 매 bounded context 미정 — 매 "Order" 의 의미 가 매 module 마다 다름. - **매 Static glossary**: 매 1년 update 안 됨 — 매 domain 진화 와 매 desync. - **매 Translation 만 (UL 없이)**: 매 dev jargon 을 매 회의에서 의역 — 매 cost 누적. ## 🧪 검증 / 중복 - Verified (Eric Evans, *Domain-Driven Design*, 2003; Vaughn Vernon, *Implementing DDD*, 2013). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — DDD UL 정리, LLM prompt 활용 패턴 추가 |