도메인 모델링

도메인 주도 섀계 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ ν•΅μ‹¬μ—λŠ” μ‹œμŠ€ν…œμ˜ 핡심 지식과 λΉ„μ¦ˆλ‹ˆμŠ€ κ·œμΉ™μ„ λ‚˜νƒ€λ‚΄λŠ” λͺ¨λΈμ΄ μžˆμŠ΅λ‹ˆλ‹€. 도메인을 잘 λͺ¨λΈλ§ν•œλ‹€λŠ” 것은 ν˜„μ‹€ μ„Έκ³„μ˜ κ°œλ…μ„ ν‘œν˜„λ ₯ 있고, 응집λ ₯ 있으며, 일관성 μžˆλŠ” μ†Œν”„νŠΈμ›¨μ–΄ ꡬ쑰둜 λ³€ν™˜ν•˜λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

μ—”ν‹°ν‹°

μ—”ν‹°ν‹°λŠ” 주둜 μ‹λ³„μ„±μœΌλ‘œ μ •μ˜λ˜λŠ” 객체이며 λ‹¨μˆœνžˆ μ†μ„±λ§ŒμœΌλ‘œ μ •μ˜λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 속성이 μ‹œκ°„μ΄ μ§€λ‚˜λ©΄μ„œ λ³€κ²½λ˜λ”λΌλ„ μ—”ν‹°ν‹°μ˜ 식별성은 λ³€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μ£Όμš” νŠΉμ§•:

  • κ³ μœ ν•œ 식별성(일반적으둜 Id)을 κ°€μ§‘λ‹ˆλ‹€.
  • μ€‘μš”ν•œ 것은 μ—”ν‹°ν‹°κ°€ 무엇을 ν¬ν•¨ν•˜λŠ”μ§€κ°€ μ•„λ‹ˆλΌ λˆ„κ΅¬μΈμ§€μž…λ‹ˆλ‹€.
  • 속성은 μ‹œκ°„μ΄ μ§€λ‚˜λ©΄μ„œ 변경될 수 μžˆμŠ΅λ‹ˆλ‹€.

Lino둜 μ—”ν‹°ν‹° μƒμ„±ν•˜κΈ°

Linoλ₯Ό μ‚¬μš©ν•˜μ—¬ μƒˆ μ—”ν‹°ν‹°λ₯Ό μƒμ„±ν•˜λ €λ©΄ λ‹€μŒμ„ μ‹€ν–‰ν•˜μ„Έμš”:

lino entity new

CLI λ„μš°λ―Έκ°€ μš”μ²­ν•©λ‹ˆλ‹€:

  • μ„œλΉ„μŠ€ – μ—”ν‹°ν‹°κ°€ 생성될 μ„œλΉ„μŠ€μž…λ‹ˆλ‹€.
  • λͺ¨λ“ˆ – μ—”ν‹°ν‹°κ°€ 생성될 λͺ¨λ“ˆ(λͺ¨λ“ˆν˜• μ„œλΉ„μŠ€μ—λ§Œ ν•΄λ‹Ή).
  • μ—”ν‹°ν‹° 이름 – 도메인과 λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”μ—μ„œ μ‚¬μš©λ˜λŠ” μ΄λ¦„μž…λ‹ˆλ‹€.

κ·Έ ν›„, 각 ν•„λ“œλ₯Ό μ„€μ •ν•˜μ—¬ μ—”ν‹°ν‹°λ₯Ό κ΅¬μ„±ν•©λ‹ˆλ‹€.

μ‚¬μš© κ°€λŠ₯ν•œ ν•„λ“œ νƒ€μž…

νƒ€μž… μ„€λͺ… λ²”μœ„ / μ°Έκ³  사항
short16λΉ„νŠΈ μ •μˆ˜-32,768 β†’ 32,767
int32λΉ„νŠΈ μ •μˆ˜-2,147,483,648 β†’ 2,147,483,647
long64λΉ„νŠΈ μ •μˆ˜-9,223,372,036,854,775,808 β†’ 9,223,372,036,854,775,807
stringν…μŠ€νŠΈμ•½ 20μ–΅ λ¬ΈμžκΉŒμ§€
boolλΆˆλ¦¬μ–Έ κ°’true λ˜λŠ” false
GuidκΈ€λ‘œλ²Œ 고유 μ‹λ³„μžλΆ„μ‚°λœ κ³ μœ μ„±
decimalκ³ μ • μ†Œμˆ˜μ  숫자금육 값에 적합
float뢀동 μ†Œμˆ˜μ  숫자 (32λΉ„νŠΈ)μ•½ 6–9자리 정밀도
double뢀동 μ†Œμˆ˜μ  숫자 (64λΉ„νŠΈ)μ•½ 15–17자리 정밀도
DateTimeλ‚ μ§œ 및 μ‹œκ°„μ‹œκ°„λŒ€ 포함
DateOnlyλ‚ μ§œλ§Œ (C# 10+)–
TimeOnlyμ‹œκ°„λ§Œ (C# 10+)–
Entityλ‹€λ₯Έ μ—”ν‹°ν‹° μ°Έμ‘°1 : 1 λ˜λŠ” 1 : N
Value ObjectλΆˆλ³€ Value Object예: μ£Όμ†Œ, CPF
Enumμ—΄κ±°ν˜•κ³ μ •λœ κ°’ μ§‘ν•©
List<Entity>μ—”ν‹°ν‹° 리슀트1 : N
ManyToManyλ‹€λŒ€λ‹€ 관계쑰인 ν…Œμ΄λΈ” ν•„μš”

예제

Person μ—”ν‹°ν‹° μƒμ„±ν•˜κΈ°:

β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PK β”‚ FK β”‚ Property name β”‚ Type   β”‚ Length β”‚ Required  β”‚ Auto-increment β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ x  β”‚    β”‚ Id            β”‚ int    β”‚        β”‚     x     β”‚       x        β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    β”‚    β”‚ Name          β”‚ string β”‚  100   β”‚     x     β”‚                β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Linoκ°€ μƒμ„±ν•œ ꡬ쑰:

<ProjectName>/
└── src/
    └── Services/
        └── <ServiceName>/
            └── Domain/
                β”œβ”€β”€ <ProjectName>.<ServiceName>.Domain.csproj
                └── Aggregates/
                    └── People/
                        β”œβ”€β”€ Person.cs
                        β”œβ”€β”€ Errors/
                        β”‚   └── PersonErrors.cs
                        β”œβ”€β”€ Repositories/
                        β”‚   └── IPersonRepository.cs
                        └── Resources/
                            └── Person/
                                β”œβ”€β”€ PersonResources.resx
                                β”œβ”€β”€ PersonResources.en.resx
                                └── PersonResources.pt-BR.resx

μ—”ν‹°ν‹°λ₯Ό μ •μ˜ν•œ ν›„, Linoλ₯Ό μ‚¬μš©ν•˜μ—¬ Migrationsλ₯Ό κ΄€λ¦¬ν•˜κ³  λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό λ™κΈ°ν™”ν•˜μ„Έμš”. 이 과정은 Persistence Layer μ„Ήμ…˜μ—μ„œ μžμ„Ένžˆ λ‹€λ£° μ˜ˆμ •μž…λ‹ˆλ‹€.

ν˜„μž¬ μ§„ν™” μ›Œν¬ν”Œλ‘œ

lino entity new λŒ€ν™”ν˜• 흐름 외에도, μ„œλΉ„μŠ€, λͺ¨λ“ˆ, 이름을 이미 μ•Œκ³  μžˆλ‹€λ©΄ CLI λͺ…λ Ήμ—μ„œ μ˜λ„λ₯Ό λͺ…μ‹œν•  수 μžˆμŠ΅λ‹ˆλ‹€:

lino entity new --name <EntityName> --service <ServiceName> --module <ModuleName>
lino entity edit --service <ServiceName> --module <ModuleName> --entity <EntityName>
lino entity list --service <ServiceName> --module <ModuleName>

큰 λͺ¨λ“ˆμ—μ„œ μƒˆ κ°œλ…μ„ λ§Œλ“€κΈ° 전에 entity listλ₯Ό μ‚¬μš©ν•˜μ‹­μ‹œμ˜€. νŽΈμ§‘ μ€‘μ—λŠ” μ‹λ³„μž, 속성, ν•„μˆ˜ μ—¬λΆ€, 길이, 관계, 인덱슀, ownership, tenant, migrations 영ν–₯도λ₯Ό κ²€ν† ν•©λ‹ˆλ‹€.

Strongly Typed IDs, ownership, invariants

Strongly Typed IDsκ°€ ν™œμ„±ν™”λ˜λ©΄ μ‹λ³„μžλŠ” ProductId와 같은 μ „μš© νƒ€μž…μ΄ λ˜μ–΄ μ„œλ‘œ λ‹€λ₯Έ μ—”ν‹°ν‹°μ˜ IDsλ₯Ό μ‹€μˆ˜λ‘œ λ°”κΎΈλŠ” 일을 μ€„μž…λ‹ˆλ‹€. κ΄€κ³„λŠ” μ‹€μ œ 도메인 ownership을 λ°˜μ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€. λͺ¨λ“  μ°Έμ‘°κ°€ 직접 탐색이 될 ν•„μš”λŠ” μ—†μœΌλ©°, λ§Žμ€ 경우 μ‹λ³„μž, shadow entity, integration event λ˜λŠ” λͺ…μ‹œμ  쿼리가 λͺ¨λ“ˆ 경계λ₯Ό 더 잘 λ³΄ν˜Έν•©λ‹ˆλ‹€.

invariantsλŠ” UI, λ°μ΄ν„°λ² μ΄μŠ€ λ˜λŠ” validatorsμ—λ§Œ 두지 말고 도메인에 λ‘μ‹­μ‹œμ˜€. μ—”ν‹°ν‹°λ₯Ό λ³€κ²½ν•œ ν›„μ—λŠ” buildλ₯Ό μ‹€ν–‰ν•˜κ³  diffλ₯Ό κ²€ν† ν•œ λ‹€μŒ migrationsλ₯Ό μƒμ„±ν•˜κ±°λ‚˜ μ—…λ°μ΄νŠΈν•˜μ‹­μ‹œμ˜€.

Value Object

Value ObjectλŠ” 였직 μ†μ„±λ“€λ‘œλ§Œ μ •μ˜λ˜λŠ” 도메인 κ°œλ…μ„ λ‚˜νƒ€λ‚΄λ©°, 자체적인 μ‹λ³„μžκ°€ μ—†μŠ΅λ‹ˆλ‹€. 두 Value ObjectλŠ” λͺ¨λ“  값이 κ°™μœΌλ©΄ λ™μΌν•˜λ‹€κ³  κ°„μ£Όλ©λ‹ˆλ‹€.

μ£Όμš” νŠΉμ§•:

  • 생성 ν›„ λΆˆλ³€μž…λ‹ˆλ‹€.
  • Idκ°€ μ—†μŠ΅λ‹ˆλ‹€.

Lino둜 Value Object μƒμ„±ν•˜κΈ°

λ‹€μŒ λͺ…령을 μ‹€ν–‰ν•˜μ„Έμš”:

lino value-object new

CLIκ°€ λ‹€μŒμ„ μš”μ²­ν•©λ‹ˆλ‹€:

  • μ„œλΉ„μŠ€ – 객체가 생성될 μ„œλΉ„μŠ€.
  • λͺ¨λ“ˆ – 객체가 생성될 λͺ¨λ“ˆ(λͺ¨λ“ˆν˜• μ„œλΉ„μŠ€μ—λ§Œ ν•΄λ‹Ή).
  • μœ„μΉ˜ – 도메인 루트 λ˜λŠ” νŠΉμ • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ.
  • Value Object 이름.

그런 λ‹€μŒ 객체λ₯Ό κ΅¬μ„±ν•˜λŠ” ν•„λ“œλ₯Ό μ •μ˜ν•˜μ„Έμš”.

μ‚¬μš© κ°€λŠ₯ν•œ ν•„λ“œ νƒ€μž…

νƒ€μž…μ„€λͺ…λΉ„κ³ 
short16λΉ„νŠΈ μ •μˆ˜-32,768 β†’ 32,767
int32λΉ„νŠΈ μ •μˆ˜-2,147,483,648 β†’ 2,147,483,647
long64λΉ„νŠΈ μ •μˆ˜-9,223,372,036,854,775,808 β†’ 9,223,372,036,854,775,807
stringν…μŠ€νŠΈμ•½ 20μ–΅ λ¬ΈμžκΉŒμ§€
boolλΆˆλ¦¬μ–Έtrue/false
decimalμ •ν™•ν•œ μ†Œμˆ˜μ  μˆ«μžκΈˆμ•‘ κ°’
float뢀동 μ†Œμˆ˜μ  숫자 (32λΉ„νŠΈ)μ•½ 6~9자리
double뢀동 μ†Œμˆ˜μ  숫자 (64λΉ„νŠΈ)μ•½ 15~17자리
DateTimeλ‚ μ§œ/μ‹œκ°„νƒ€μž„μ‘΄ 포함
DateOnlyλ‚ μ§œλ§ŒC# 10 이상
TimeOnlyμ‹œκ°„λ§ŒC# 10 이상

예제

Value Object Address:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Property name β”‚ Type   β”‚ Length β”‚ Required  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Street        β”‚ string β”‚  100   β”‚     x     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Number        β”‚ string β”‚   10   β”‚     x     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Neighborhood  β”‚ string β”‚   50   β”‚           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ City          β”‚ string β”‚  100   β”‚     x     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ State         β”‚ string β”‚   2    β”‚     x     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ PostalCode    β”‚ string β”‚   20   β”‚     x     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Country       β”‚ string β”‚  100   β”‚     x     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

μƒμ„±λœ 파일 ꡬ쑰 (μ• κ·Έλ¦¬κ²Œμ΄νŠΈ Person):

<ProjectName>/
└── src/
    └── Services/
        └── <ServiceName>/
            └── Domain/
                β”œβ”€β”€ <ProjectName>.<ServiceName>.Domain.csproj
                └── Aggregates/
                    └── People/
                        β”œβ”€β”€ Person.cs
                        β”œβ”€β”€ ValueObjects/
                        β”‚   └── Address.cs
                        β”œβ”€β”€ Errors/
                        β”‚   β”œβ”€β”€ AddressErrors.cs
                        β”‚   └── PersonErrors.cs
                        β”œβ”€β”€ Repositories/
                        β”‚   └── IPersonRepository.cs
                        └── Resources/
                            β”œβ”€β”€ Address/
                            β”‚   β”œβ”€β”€ AddressResources.resx
                            β”‚   β”œβ”€β”€ AddressResources.en.resx
                            β”‚   └── AddressResources.pt-BR.resx
                            └── Person/
                                β”œβ”€β”€ PersonResources.resx
                                β”œβ”€β”€ PersonResources.en.resx
                                └── PersonResources.pt-BR.resx

엔티티와 λ§ˆμ°¬κ°€μ§€λ‘œ MigrationsλŠ” Lino에 μ˜ν•΄ κ΄€λ¦¬λ˜μ–΄ 데이터 λͺ¨λΈμ„ 동기화 μƒνƒœλ‘œ μœ μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν˜„μž¬ μ§„ν™” μ›Œν¬ν”Œλ‘œ

λŒ€ν™”ν˜• λͺ…λ Ή 외에도 κ°œλ…μ„ 어디에 λ§Œλ“€μ–΄μ•Ό ν•˜λŠ”μ§€ 이미 μ•Œκ³  μžˆλ‹€λ©΄ νŒŒλΌλ―Έν„°λ₯Ό μ‚¬μš©ν•˜μ‹­μ‹œμ˜€:

lino value-object new --name <ValueObjectName> --service <ServiceName> --module <ModuleName>
lino value-object edit --service <ServiceName> --module <ModuleName> --value-object <ValueObjectName>
lino value-object list --service <ServiceName> --module <ModuleName>

μ—”ν‹°ν‹° 속성이 ValueObject둜 μ„ μ–Έλ˜λ©΄ LinoλŠ” μ—”ν‹°ν‹° λͺ¨λΈλ§ 쀑 κΈ°μ‘΄ Value Objectλ₯Ό μž¬μ‚¬μš©ν•˜κ±°λ‚˜ μƒˆλ‘œ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€. ν•„λ“œ 집합이 κΈˆμ•‘, μ£Όμ†Œ, 치수, κΈ°κ°„ λ˜λŠ” λ¬Έμ„œμ²˜λŸΌ ν•˜λ‚˜μ˜ κ°œλ…μ„ λ‚˜νƒ€λ‚Ό λ•Œ 이 μ˜΅μ…˜μ„ μš°μ„ ν•˜μ‹­μ‹œμ˜€.

μ˜μ†μ„±, UI 및 ν˜„μ§€ν™”

LinoλŠ” λͺ¨λ“ˆμ˜ μ˜μ†μ„± 계측을 톡해 Value Objects의 속성을 λ§€ν•‘ν•˜κ³  ν‘œμ‹œ 메타데이터λ₯Ό resources둜 μ „λ‹¬ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μ€‘μ²©λœ 값에 λŒ€ν•΄ ν˜„μ§€ν™”λœ labels와 λ©”μ‹œμ§€λ₯Ό μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€. Value ObjectλŠ” μƒμ„±λœ λͺ¨λ“ˆμ— μ†ν•˜λ©°, λͺ…μ‹œμ μΈ integration μ—†μ΄λŠ” λͺ¨λ“ˆ κ°„ 곡유 계약이 λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

invariantsλŠ” νƒ€μž… μžμ²΄μ—μ„œ λ³΄ν˜Έν•˜μ‹­μ‹œμ˜€. 음수 κ°’, 잘λͺ»λœ 톡화, λ’€μ§‘νžŒ κΈ°κ°„ λ˜λŠ” 잘λͺ»λœ ν˜•μ‹μ˜ λ¬Έμ„œκ°€ μœ νš¨ν•˜κ²Œ μƒμ„±λ˜μ–΄μ„œλŠ” μ•ˆ λ©λ‹ˆλ‹€.

μ—΄κ±°ν˜•

DDDμ—μ„œ μ—΄κ±°ν˜•μ€ C#의 전톡적인 enum을 λ„˜μ–΄μ„€ 수 μžˆμŠ΅λ‹ˆλ‹€. μƒνƒœλ₯Ό ν‘œν˜„ν•˜λŠ” ν’λΆ€ν•œ κ°μ²΄λ‘œμ„œ μœ νš¨μ„± 검사, 보쑰 λ©”μ„œλ“œ, 심지어 λ™μž‘κΉŒμ§€ 포함할 수 μžˆμŠ΅λ‹ˆλ‹€.

동기:

  • C#의 enum은 μ •μˆ˜ λ˜λŠ” λ¬Έμžμ—΄ κ°’μ—λ§Œ μ œν•œλ©λ‹ˆλ‹€.
  • 클래슀둜 μ—΄κ±°ν˜•μ„ λͺ¨λΈλ§ν•˜λ©΄ 더 큰 μœ μ—°μ„±κ³Ό ν‘œν˜„λ ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.

μ£Όμš” νŠΉμ§•:

  • 곡톡 κΈ°λ³Έ 클래슀λ₯Ό μƒμ†ν•˜λ©° Id와 이름을 μΊ‘μŠν™”ν•˜λŠ” ν΄λž˜μŠ€μž…λ‹ˆλ‹€.
  • μœ νš¨μ„± 검사, 보쑰 λ©”μ„œλ“œ 및 λ™μž‘μ„ μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Lino둜 μ—΄κ±°ν˜• μƒμ„±ν•˜κΈ°

λ‹€μŒ λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•˜μ„Έμš”:

lino enumeration new

도움말이 λ‹€μŒμ„ μš”μ²­ν•©λ‹ˆλ‹€:

  • μ„œλΉ„μŠ€.
  • λͺ¨λ“ˆ (적용 κ°€λŠ₯ν•œ 경우).
  • μœ„μΉ˜ – 도메인 루트 λ˜λŠ” μ• κ·Έλ¦¬κ²Œμ΄νŠΈ.
  • μ—΄κ±°ν˜• 이름.
  • μœ ν˜• – 전톡적인 enum λ˜λŠ” 슀마트 Enum (class).
  • μ €μž₯ 방식 – λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ int λ˜λŠ” string.

예제

PersonStatus μ—΄κ±°ν˜•:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Value β”‚ Name      β”‚ Display Name β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 1     β”‚ Active    β”‚ Active       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 2     β”‚ Inactive  β”‚ Inactive     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 3     β”‚ Suspended β”‚ Suspended    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 4     β”‚ Deleted   β”‚ Deleted      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

μƒμ„±λœ ꡬ쑰:

<ProjectName>/
└── src/
    └── Services/
        └── <ServiceName>/
            └── Domain/
                β”œβ”€β”€ <ProjectName>.<ServiceName>.Domain.csproj
                └── Aggregates/
                    └── People/
                        β”œβ”€β”€ Person.cs
                        β”œβ”€β”€ Enums/
                        β”‚   └── PersonStatus.cs
                        β”œβ”€β”€ ValueObjects/
                        β”‚   └── Address.cs
                        β”œβ”€β”€ Errors/
                        β”‚   β”œβ”€β”€ AddressErrors.cs
                        β”‚   └── PersonErrors.cs
                        β”œβ”€β”€ Repositories/
                        β”‚   └── IPersonRepository.cs
                        └── Resources/
                            β”œβ”€β”€ Address/
                            β”‚   β”œβ”€β”€ AddressResources.resx
                            β”‚   β”œβ”€β”€ AddressResources.en.resx
                            β”‚   └── AddressResources.pt-BR.resx
                            β”œβ”€β”€ Person/
                            β”‚   β”œβ”€β”€ PersonResources.resx
                            β”‚   β”œβ”€β”€ PersonResources.en.resx
                            β”‚   └── PersonResources.pt-BR.resx
                            └── PersonStatus/
                                β”œβ”€β”€ PersonStatusResources.resx
                                β”œβ”€β”€ PersonStatusResources.en.resx
                                └── PersonStatusResources.pt-BR.resx

μ—΄κ±°ν˜• 값을 string으둜 μ €μž₯ν•˜λŠ” 것도 κ°€λŠ₯ν•˜λ©° 가독성을 높일 수 μžˆμ§€λ§Œ, μ„±λŠ₯κ³Ό μ €μž₯ 곡간 λ©΄μ—μ„œλŠ” 덜 효율적일 수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 값은 int둜 μ €μž₯ν•˜κ³ , 무결성 μœ μ§€μ™€ μœ μ§€λ³΄μˆ˜λ₯Ό μ‰½κ²Œ ν•˜κΈ° μœ„ν•΄ μ—΄κ±°ν˜• κ°’κ³Ό μΌμΉ˜ν•˜λŠ” κΈ°λ³Έ ν‚€λ₯Ό κ°€μ§„ 보쑰 μ—”ν‹°ν‹°(ν…Œμ΄λΈ”)λ₯Ό μƒμ„±ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.

μ—΄κ±°ν˜•μ„ μ •μ˜ν•œ ν›„μ—λŠ” Linoλ₯Ό μ‚¬μš©ν•˜μ—¬ Migrationsλ₯Ό μƒμ„±ν•˜κ³  μ μš©ν•˜μ—¬ λ°μ΄ν„°λ² μ΄μŠ€κ°€ 도메인 λͺ¨λΈμ„ λ°˜μ˜ν•˜λ„λ‘ ν•˜μ„Έμš”. μžμ„Έν•œ λ‚΄μš©μ€ μ˜μ†μ„± 계측 μ„Ήμ…˜μ„ μ°Έκ³ ν•˜μ‹­μ‹œμ˜€.

ν˜„μž¬ μ§„ν™” μ›Œν¬ν”Œλ‘œ

λŒ€ν™”ν˜• λͺ…λ Ή 외에도 μœ„μΉ˜μ™€ 이름이 이미 μ •ν•΄μ Έ μžˆλ‹€λ©΄ νŒŒλΌλ―Έν„°λ₯Ό μ‚¬μš©ν•˜μ‹­μ‹œμ˜€:

lino enumeration new --name <EnumerationName> --service <ServiceName> --module <ModuleName>
lino enumeration edit --service <ServiceName> --module <ModuleName> --enumeration <EnumerationName>
lino enumeration list --service <ServiceName> --module <ModuleName>

Enumeration, μ—”ν‹°ν‹° λ˜λŠ” μ„€μ •

Enumeration μ‚¬μš©μ—”ν‹°ν‹° λ˜λŠ” μ„€μ • μ‚¬μš©
μ£Όλ¬Έ μƒνƒœ, κ²Œμ‹œ μƒνƒœ, 기술적 톡합 μœ ν˜•μ‚¬μš©μžκ°€ κ΄€λ¦¬ν•˜λŠ” μΉ΄ν…Œκ³ λ¦¬, tenantλ³„λ‘œ μ„€μ • κ°€λŠ₯ν•œ μ‚¬μœ , backofficeμ—μ„œ κ΄€λ¦¬λ˜λŠ” κ³΅κΈ‰μž
μ½”λ“œμ™€ ν•¨κ»˜ 버전 κ΄€λ¦¬λ˜λŠ” κ°’runtime에 λ³€κ²½λ˜κ±°λ‚˜ κΆŒν•œμœΌλ‘œ μ œμ–΄λ˜λŠ” κ°’
값별 λ‹¨μˆœ κ·œμΉ™ λ˜λŠ” μž‘μ€ λ™μž‘λΌμ΄ν”„μ‚¬μ΄ν΄, 감사, 동적 λ²ˆμ—­ λ˜λŠ” 자체 관계

Enumeration이 ν‘œμ‹œ 이름을 λ…ΈμΆœν•˜λ©΄ LinoλŠ” ν˜„μ§€ν™”λœ labels용 resourcesλ₯Ό 생성할 수 μžˆμŠ΅λ‹ˆλ‹€. μ§€μ†λ˜κ±°λ‚˜ seed data둜 μ‚¬μš©λ˜λŠ” 경우 값을 μΆ”κ°€, 제거 λ˜λŠ” 이름 λ³€κ²½ν•œ λ’€ migrationsλ₯Ό κ²€ν† ν•˜μ‹­μ‹œμ˜€. μ½”λ“œ, λ°μ΄ν„°λ² μ΄μŠ€, UI κ°„ 일관성도 도메인 λ³€κ²½μ˜ μΌλΆ€μž…λ‹ˆλ‹€.

처리되지 않은 오류가 발생했습니다. 새로 고침 πŸ—™