애플리케이션 Use Cases 정의

Use cases๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ์˜๋„๋ฅผ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋กœ ๋ฐ”๊พธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต์˜ ์ง„์ž…์ ์ž…๋‹ˆ๋‹ค. Lino์—์„œ๋Š” Application/UseCases์— ์œ„์น˜ํ•˜๋ฉฐ ํ”„๋กœ์ ํŠธ์˜ ์ด์ „ ๋‹จ๊ณ„์—์„œ ์ •์˜ํ•œ ์—”ํ‹ฐํ‹ฐ, aggregates, ์—ด๊ฑฐํ˜•, ๋ชจ๋“ˆ, ์„œ๋น„์Šค๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.


Lino๋Š” CQRS ์ง€ํ–ฅ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. Commands๋Š” ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ž‘์—…์„ ๋‚˜ํƒ€๋‚ด๊ณ , Queries๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์ž‘์—…์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ๋ถ„๋ฆฌ๋Š” ์“ฐ๊ธฐ ๊ทœ์น™, read models, validation, tracing, logging, response contracts๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์œ ์ง€ํ•˜๊ณ  ๋” ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.


Result Pattern์€ ์„ฑ๊ณต, ์‹คํŒจ, ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€, ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์บก์Аํ™”ํ•˜์—ฌ ์ž‘์—…์˜ ๋ฐ˜ํ™˜๊ฐ’์„ ํ‘œ์ค€ํ™”ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์ƒ๋˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ํ๋ฆ„์— ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  handler๋Š” ์ƒํ™ฉ์— ๋”ฐ๋ผ ๊ฐ’, ์˜ค๋ฅ˜ ๋˜๋Š” no-content๋ฅผ ๋‹ด์€ Result ๋˜๋Š” Result<T>๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.


CLI๋Š” use case์˜ ์ดˆ๊ธฐ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์ง€๋งŒ, ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋Š” ๋„๋ฉ”์ธ ๋ถ„์„์„ ๋Œ€์ฒดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ์—ฌ์ „ํžˆ handler๋ฅผ ๊ฒ€ํ† ํ•˜๊ณ , ์„ ํƒ๋œ ์†์„ฑ์„ ํ™•์ธํ•˜๊ณ , ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์„ ์ถ”๊ฐ€ํ•˜๊ณ , validations๋ฅผ ์กฐ์ •ํ•˜๊ณ , use case๊ฐ€ ๋ชจ๋“ˆ๊ณผ ์„œ๋น„์Šค ๊ฒฝ๊ณ„๋ฅผ ์กด์ค‘ํ•˜๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ค‘์š”: Lino ํ”„๋กœ์ ํŠธ๋Š” CQRS ๋ฐ mediator ์ง€์›๊ณผ ํ•จ๊ป˜ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ์„ฑ๋œ Commands์™€ Queries๋Š” ์š”์ฒญ ๋ฐ ์ž‘์—… ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ๋ฅผ ํ‘œ์ค€ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ICommand, IQuery, ICommandHandler, IQueryHandler, Tolitech.Results ๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ถ”์ƒํ™”๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Use Cases ๊ฐœ์š”

Use Case๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์™„์ „ํ•œ ์ž‘์—…์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ž…๋ ฅ ๋ชจ๋ธ์„ ๋ฐ›๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๊ณ , ์˜์กด์„ฑ์„ ์กฐ์œจํ•˜๊ณ , ํ•„์š”ํ•  ๋•Œ ๋„๋ฉ”์ธ ๋™์ž‘์„ ํ˜ธ์ถœํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์กฐํšŒํ•œ ๋’ค ํ‘œ์ค€ํ™”๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋„๋ฉ”์ธ ๋ชจ๋ธ ๋ฐ–์œผ๋กœ ๋ถˆ๋ณ€์‹์„ ์˜ฎ๊ธฐ์ง€ ์•Š์œผ๋ฉด์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋น„์ฆˆ๋‹ˆ์Šค ํ๋ฆ„์„ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ํ•˜๋Š” ์œ„์น˜์ž…๋‹ˆ๋‹ค.

Lino๊ฐ€ ์ƒ์„ฑํ•œ ์†”๋ฃจ์…˜์—์„œ use cases๋Š” ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์ ํŠธ์— ๊ทธ๋ฃนํ™”๋ฉ๋‹ˆ๋‹ค:

src/Services/<ServiceName>/<ModuleName>/Application/UseCases/<EntityName>/
โ”œโ”€โ”€ Commands/
โ”‚   โ””โ”€โ”€ <CommandName>/
โ””โ”€โ”€ Queries/
    โ””โ”€โ”€ <QueryName>/

์ด ๊ตฌ์„ฑ์€ ๊ฐ feature๊ฐ€ ์–ด๋–ค ์„œ๋น„์Šค, ๋ชจ๋“ˆ, ์—”ํ‹ฐํ‹ฐ์— ์†ํ•˜๋Š”์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. ๋˜ํ•œ ํ™”๋ฉด, API, ํ†ตํ•ฉ ๋˜๋Š” background process๊ฐ€ ๋™์ž‘์˜ ํ•œ์ชฝ ๋ฉด๋งŒ ํ•„์š”๋กœ ํ•  ๋•Œ ์œ ์šฉํ•˜๋„๋ก ์“ฐ๊ธฐ ๋ชจ๋ธ๊ณผ ์ฝ๊ธฐ ๋ชจ๋ธ์„ ๋…๋ฆฝ์ ์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

Command ๋˜๋Š” Query?

ํƒ€์ž… ์˜๋„ ์˜ˆ์‹œ ์ผ๋ฐ˜์ ์ธ ๊ฒฐ๊ณผ
Command ์‹œ์Šคํ…œ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. CreateOrder, UpdateVehicle, DeleteMaintenance, SavePermissionsByRoleId. ์„ฑ๊ณต ์‹œ Result, Result<CommandResult> ๋˜๋Š” no-content.
Query ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. GetOrderById, ListCustomers, GetVehicleAvailability. Result<QueryResult>, list, page ๋˜๋Š” consumer์šฉ ํŠน์ • DTO.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ use case์— ์†ํ•˜๋Š” ๊ฒƒ

  • ์ž…๋ ฅ contract: ์ž‘์—…์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ๊ฐ€์ง„ command ๋˜๋Š” query record.
  • Validation: handler๊ฐ€ ํ๋ฆ„์„ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ์š”์ฒญ ํ˜•์‹, ํ•„์ˆ˜ ํ•„๋“œ, ๋ฒ”์œ„, ์‹๋ณ„์ž, filters ๋ฐ ๊ธฐํƒ€ ์ž…๋ ฅ ์ œ์•ฝ์„ ํ™•์ธํ•˜๋Š” ๊ทœ์น™.
  • Handler ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜: ์˜์กด์„ฑ ํ˜ธ์ถœ, repository ์ ‘๊ทผ, context ์กฐํšŒ, Unit of Work ์‚ฌ์šฉ, ๊ฒฐ๊ณผ ๊ตฌ์„ฑ, logging, tracing.
  • ๊ฒฐ๊ณผ contract: caller๊ฐ€ ๊ณ„์† ์ง„ํ–‰ํ•˜๋Š” ๋ฐ ์ •ํ™•ํžˆ ํ•„์š”ํ•œ ๊ฒƒ์„ ์ „๋‹ฌํ•˜๋Š” ์ž‘์€ ์‘๋‹ต ๊ฐ์ฒด ๋˜๋Š” content ์—†๋Š” ๊ฒฐ๊ณผ.

use case ๋ฐ–์— ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ

  • ๋„๋ฉ”์ธ ๋ถˆ๋ณ€์‹์€ ์—”ํ‹ฐํ‹ฐ, Value Objects, domain services, ๋„๋ฉ”์ธ ๋ฉ”์„œ๋“œ์— ๋‚จ์•„ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Infrastructure ์„ธ๋ถ€ ์‚ฌํ•ญ์€ abstractions, repositories, database contexts, file services, messaging integrations, external clients ๋’ค์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Presentation ๊ด€์‹ฌ์‚ฌ, ์˜ˆ๋ฅผ ๋“ค์–ด UI ์ƒํƒœ, labels, layouts, component ๋™์ž‘์€ web app ๊ณ„์ธต์— ๋‚จ์•„ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ข‹์€ use case๋Š” ๋ช…์‹œ์ ์ด๊ณ , ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„ ๋งŒํผ ์ž‘์œผ๋ฉฐ, ๊ฒฝ๊ณ„์— ์—„๊ฒฉํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์„ ์กฐ์œจํ•˜์ง€๋งŒ ์‹œ์Šคํ…œ์˜ ๋ชจ๋“  ๊ทœ์น™์ด ๋’ค์„ž์ด๋Š” ์žฅ์†Œ๊ฐ€ ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

Commands

Command๋Š” ์‹œ์Šคํ…œ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋™์ž‘์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ๋‹ด๋Š” ๋ถˆ๋ณ€ ๋ฉ”์‹œ์ง€์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์˜ˆ๋กœ๋Š” CreateCustomer, UpdateVehicle, DeleteMaintenance, ConfirmOrder, SavePermissionsByRoleId๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Commands๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋ฌด์–ธ๊ฐ€๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ผ๊ณ  ์ง€์‹œํ•˜๋ฏ€๋กœ ๋™์ž‘ ์ด๋ฆ„์œผ๋กœ ๋ช…๋ช…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Lino์—์„œ ์ƒ์„ฑ๋œ Commands๋Š” command ์ถ”์ƒํ™”๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ํ‘œ์ค€ํ™”๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” records์ž…๋‹ˆ๋‹ค. ์ƒ์„ฑ Commands๋Š” ๋ณดํ†ต caller๊ฐ€ ์š”๊ตฌํ•˜๋Š” ์‹๋ณ„์ž๋‚˜ ์ตœ์†Œ ์ •๋ณด๋ฅผ ๋‹ด์€ ๊ฒฐ๊ณผ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์—…๋ฐ์ดํŠธ์™€ ์‚ญ์ œ commands๋Š” ์ž‘์—…์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ no-content๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Command์˜ ํŠน์ง•

  • ๋ถˆ๋ณ€์„ฑ: record ๋˜๋Š” get๋งŒ ์žˆ๋Š” ํด๋ž˜์Šค์ฒ˜๋Ÿผ ๊ณต๊ฐœ mutable setters ์—†์ด ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.
  • ๋ช…๋ นํ˜• ์ด๋ฆ„: CreateOrder, UpdateCustomerAddress, ChangeProductPrice์ฒ˜๋Ÿผ ๋น„์ฆˆ๋‹ˆ์Šค ๋™์ž‘์„ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์ตœ์†Œ ๋ฐ์ดํ„ฐ: ์ „์ฒด ์—”ํ‹ฐํ‹ฐ๋‚˜ ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์šด๋ฐ˜ํ•˜์ง€ ์•Š๊ณ  ์ž‘์—… ์‹คํ–‰์— ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • ๋ถ„๋ฆฌ๋œ ๊ฒ€์ฆ: ๊ฐ Command๋Š” ์š”์ฒญ์ด handler์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•˜๋Š” ์ž์ฒด ๊ทœ์น™์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
  • UI ๋…๋ฆฝ์„ฑ: Command๋Š” ์ž‘์—…์„ ์‹œ์ž‘ํ•œ ๋ฒ„ํŠผ, ํผ ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์˜๋„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

Command๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

  • ๋ฐ์ดํ„ฐ๊ฐ€ ์ƒ์„ฑ, ๋ณ€๊ฒฝ, ์ œ๊ฑฐ, ์—ฐ๊ฒฐ, ๊ฐ€์ ธ์˜ค๊ธฐ, ์Šน์ธ, ์ทจ์†Œ๋˜๊ฑฐ๋‚˜ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ๋ณ€๊ฒฝ๋  ๋•Œ Command๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • payload๋Š” ์ž‘์—…์— ์ง‘์ค‘๋˜๊ฒŒ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๋ช‡ ๊ฐœ์˜ ํ•„๋“œ๋งŒ ์ถฉ๋ถ„ํ•˜๋‹ค๋ฉด ์ „์ฒด ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์‹œ์ž‘ํ•œ ์‹œ๊ฐ์  ์ด๋ฒคํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ๋น„์ฆˆ๋‹ˆ์Šค ๋™์ž‘์„ ์„ค๋ช…ํ•˜๋Š” ์ด๋ฆ„์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.
  • ๋™์ž‘์ด ํ˜„์žฌ ๋ชจ๋“ˆ์— ์†ํ•˜๋Š”์ง€, ์•„๋‹ˆ๋ฉด ๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ ํ†ตํ•ฉ, ์ด๋ฒคํŠธ ๋˜๋Š” shadow entity๋กœ ํ‘œํ˜„๋˜์–ด์•ผ ํ•˜๋Š”์ง€ ๊ฒ€ํ† ํ•ฉ๋‹ˆ๋‹ค.

Command Validators

Command Validators๋Š” Command๊ฐ€ handler๋กœ ์ „์†ก๋˜๊ธฐ ์ „์— ์ž˜ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๊ณ  ์ž…๋ ฅ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜๋Š”์ง€ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. Lino์—์„œ ์ด๋Ÿฌํ•œ ๊ฒ€์ฆ์€ ๊ทœ์น™์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์œ ์ฐฝํ•˜๊ณ  ์ฝ๊ธฐ ์‰ฌ์šด API๋ฅผ ์ œ๊ณตํ•ด .NET ํ”„๋กœ์ ํŠธ์—์„œ ํ”ํžˆ ์“ฐ์ด๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ FluentValidation์œผ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ๊ฒ€์ฆ ๊ทœ์น™

  • ํ•„์ˆ˜ ํ•„๋“œ์—๋Š” NotEmpty ๋ฐ NotNull.
  • ์ˆซ์ž ๋ฒ”์œ„, ๊ธˆ์•ก, ๋ฐฑ๋ถ„์œจ, ์ตœ์†Œ ๋ฐ ์ตœ๋Œ€ ์ˆ˜๋Ÿ‰์—๋Š” InclusiveBetween.
  • ๋ฌธ์ž์—ด ๊ธธ์ด์—๋Š” MaximumLength, MinimumLength, Length.
  • List<T>์™€ ๊ฐ™์€ ์ปฌ๋ ‰์…˜ ํ•ญ๋ชฉ ๊ฒ€์ฆ์—๋Š” RuleForEach.
  • ๋ฌธ์„œ ํ˜•์‹, ๋‚ ์งœ ์ผ๊ด€์„ฑ, ์ž˜๋ชป๋œ ํ•„๋“œ ์กฐํ•ฉ ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ง€์ • ๊ทœ์น™์—๋Š” Must.

validator๋Š” ์ž…๋ ฅ ๊ฒฝ๊ณ„๋ฅผ ๋ณดํ˜ธํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ์ œํ•œ, ํ—ˆ์šฉ๋œ ์ „์ด, caller์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ํ•ญ์ƒ ์„ฑ๋ฆฝํ•ด์•ผ ํ•˜๋Š” ๊ทœ์น™ ๊ฐ™์€ ์‹ค์ œ ๋„๋ฉ”์ธ ๋ถˆ๋ณ€์‹์€ ๊ณ„์† aggregate, ์—”ํ‹ฐํ‹ฐ, Value Object ๋˜๋Š” domain service์— ์†ํ•ฉ๋‹ˆ๋‹ค.

Command Handlers

Command Handler๋Š” Command์™€ ์—ฐ๊ฒฐ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•  ๋•Œ repository, context, IUnitOfWork, ๋ณด์กฐ ์„œ๋น„์Šค, logging, tracing, ํ†ตํ•ฉ ํ˜ธ์ถœ, ๋„๋ฉ”์ธ ์ด๋ฒคํŠธ๋ฅผ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค.

handler ๊ตฌํ˜„ ํŒจํ„ด

  • repository, ์™ธ๋ถ€ ์„œ๋น„์Šค, context, Unit of Work ๊ฐ™์€ ์˜์กด์„ฑ์„ dependency injection์œผ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.
  • ์ž‘์—…์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ์˜ ์กด์žฌ ์—ฌ๋ถ€์™€ ์‚ฌ์šฉ ๊ฐ€๋Šฅ์„ฑ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
  • ์ž‘์—…์ด ๊ธฐ์กด ์ƒํƒœ์— ์˜์กดํ•  ๋•Œ ์˜ฌ๋ฐ”๋ฅธ aggregate ๋˜๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
  • handler์—์„œ ๋ถˆ๋ณ€์‹์„ ์ค‘๋ณตํ•˜์ง€ ์•Š๊ณ  ๋„๋ฉ”์ธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • IUnitOfWork ๋˜๋Š” ํ”„๋กœ์ ํŠธ์˜ persistence ์ถ”์ƒํ™”๋ฅผ ํ†ตํ•ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ์ž‘์—…์ด ์‹œ์Šคํ…œ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„๊ณผ ํ†ต์‹ ํ•ด์•ผ ํ•  ๋•Œ ๋„๋ฉ”์ธ ์ด๋ฒคํŠธ, Outbox ๋˜๋Š” ํ†ตํ•ฉ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.
  • ์„ฑ๊ณต, ์•Œ๋ ค์ง„ ์‹คํŒจ ๋˜๋Š” ์ตœ์†Œ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„ Result ๋˜๋Š” Result<T>๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Command Results ๋ฐ Result Pattern

Command Result๋Š” caller๊ฐ€ ๊ณ„์† ์ง„ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ๊ฐ€์ง„ ๋‹จ์ˆœ DTO์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ์—์„œ๋Š” ๋ณดํ†ต ์ƒ์„ฑ๋œ Id๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์—…๋ฐ์ดํŠธ๋‚˜ ์‚ญ์ œ์—์„œ๋Š” payload๊ฐ€ ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—…์ด ์˜ˆ์ƒ๋œ ์กฐ๊ฑด์œผ๋กœ ์‹คํŒจํ•˜๋ฉด ๋ฐ˜ํ™˜๊ฐ’์€ ํ‘œ์ค€ํ™”๋œ ์˜ค๋ฅ˜ ์ •๋ณด๋ฅผ ๋‹ด์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Result Pattern์€ ์ž‘์—… ๊ฒฐ๊ณผ๋ฅผ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ๋กœ ์บก์Аํ™”ํ•ฉ๋‹ˆ๋‹ค. ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ, ์ž˜๋ชป๋œ ์ƒํƒœ, ๋น„์ฆˆ๋‹ˆ์Šค ๊ฒ€์ฆ ๊ฐ™์€ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์— ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋Š” ๋Œ€์‹ , handler๋Š” ํ•„์š”ํ•  ๋•Œ ๊ฐ’, ์˜ค๋ฅ˜, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•œ Result<T> ๊ฐ™์€ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์„ฑ๊ณต ์‹œ ๊ฒฐ๊ณผ๋Š” ์ž‘์€ DTO ๋˜๋Š” ์ƒ์„ฑ๋œ ์‹๋ณ„์ž ๊ฐ™์€ Value๋ฅผ ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‹คํŒจ ์‹œ ๊ฒฐ๊ณผ๋Š” ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ error definitions์— ์ž์ฃผ ์ •์˜๋˜๋Š” ํ‘œ์ค€ํ™”๋œ ์ฝ”๋“œ๋‚˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ํ๋ฆ„์€ Application, API, typed clients, UI ์ „๋ฐ˜์—์„œ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

CLI๋กœ Command ๋งŒ๋“ค๊ธฐ

Lino๋Š” ๋‹ค์Œ command๋ฅผ ํ†ตํ•ด ์ƒˆ Command์— ํ•„์š”ํ•œ artifacts ์ƒ์„ฑ์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค:

lino command new

CLI๋Š” ๋งˆ๋ฒ•์‚ฌ์˜ ์งˆ๋ฌธ์„ ์ค„์ด๊ธฐ ์œ„ํ•œ ์˜ต์…˜๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค:

lino command new --service <ServiceName> --module <ModuleName> --entity <EntityName> --name <CommandName>
lino command new --name <CommandName> --service <ServiceName> --module <ModuleName> --entity <EntityName>
lino command list --service <ServiceName> --module <ModuleName> --entity <EntityName>
  • -s ๋˜๋Š” --service: ๋Œ€์ƒ ์„œ๋น„์Šค.
  • -m ๋˜๋Š” --module: ๋ชจ๋“ˆํ™”๋œ ์„œ๋น„์Šค์˜ ๋Œ€์ƒ ๋ชจ๋“ˆ.
  • -e ๋˜๋Š” --entity: Command์™€ ์—ฐ๊ฒฐ๋œ ์—”ํ‹ฐํ‹ฐ.
  • -n, --name, -c ๋˜๋Š” --command: Command ์ด๋ฆ„.

๋Œ€ํ™”ํ˜• ํ๋ฆ„ ์ค‘ Lino๋Š” ์„œ๋น„์Šค, ๋ชจ๋“ˆ, ์—”ํ‹ฐํ‹ฐ, Command ์ด๋ฆ„, Command ํƒ€์ž…, ๊ทธ๋ฆฌ๊ณ  ์ƒ์„ฑ ๋˜๋Š” ์—…๋ฐ์ดํŠธ ์ž‘์—…์˜ ๊ฒฝ์šฐ ์š”์ฒญ์— ํฌํ•จ๋  ์†์„ฑ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. CLI๊ฐ€ ๋…ธ์ถœํ•˜๋Š” ํƒ€์ž…์€ Create, Update, Delete์ž…๋‹ˆ๋‹ค.

ํ™•์ธ ํ›„ Lino๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:

  • CreateOrderCommand.cs
  • CreateOrderCommandValidator.cs
  • CreateOrderCommandHandler.cs
  • CreateOrderCommandResult.cs

์ƒ์„ฑ๋œ ๊ตฌ์กฐ ์˜ˆ์‹œ

CreatePerson Command๋ฅผ ๊ณ ๋ คํ•ด ๋ณด์„ธ์š”. ์ƒ์„ฑ๋œ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค:

<ProjectName>/
โ””โ”€โ”€ src/
    โ””โ”€โ”€ Services/
        โ””โ”€โ”€ <ServiceName>/
            โ””โ”€โ”€ Application/
                โ”œโ”€โ”€ <ProjectName>.<ServiceName>.Application.csproj
                โ””โ”€โ”€ UseCases/
                    โ””โ”€โ”€ People/
                        โ”œโ”€โ”€ Commands/
                        โ”‚   โ””โ”€โ”€ CreatePerson/
                        โ”‚       โ”œโ”€โ”€ CreatePersonCommand.cs
                        โ”‚       โ”œโ”€โ”€ CreatePersonCommandValidator.cs
                        โ”‚       โ”œโ”€โ”€ CreatePersonCommandHandler.cs
                        โ”‚       โ””โ”€โ”€ CreatePersonCommandResult.cs
                        โ””โ”€โ”€ Queries/
                            โ””โ”€โ”€ ...

Fleet์˜ ์‚ฌ์šฉ์ž ์ง€์ • Command๋„ ๊ฐ™์€ ํŒจํ„ด์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค:

Application/UseCases/Vehicles/Commands/UpdateVehicle/
โ”œโ”€โ”€ UpdateVehicleCommand.cs
โ”œโ”€โ”€ UpdateVehicleCommandValidator.cs
โ”œโ”€โ”€ UpdateVehicleCommandHandler.cs
โ””โ”€โ”€ UpdateVehicleCommandResult.cs

Command ํŒŒ์ผ์˜ ์ฑ…์ž„

  • Command: ์ž‘์—… ์ž…๋ ฅ์„ ๋‹ด๋Š” ๋ถˆ๋ณ€ ์š”์ฒญ contract.
  • Validator: ์ผ๋ฐ˜์ ์œผ๋กœ ํ•„์ˆ˜ ์—ฌ๋ถ€, ๊ธธ์ด, ๋ฒ”์œ„, ์‹๋ณ„์ž, ์ปฌ๋ ‰์…˜ ๊ทœ์น™์„ ํฌํ•จํ•˜๋Š” ์ž…๋ ฅ ๊ฒ€์ฆ.
  • Handler: repository, Unit of Work, context, ๋„๋ฉ”์ธ ๋ฉ”์„œ๋“œ, logging, tracing, ๊ฒฐ๊ณผ ์ƒ์„ฑ์„ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค.
  • Result: ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” ์„ฑ๊ณต ์ž‘์—…์„ ์œ„ํ•œ ์ตœ์†Œ ์‘๋‹ต contract.

๊ตฌํ˜„ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  1. lino command new๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅธ ์„œ๋น„์Šค, ๋ชจ๋“ˆ, ์—”ํ‹ฐํ‹ฐ, ํƒ€์ž…, ์†์„ฑ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
  2. ์ƒ์„ฑ๋œ Command๋ฅผ ์—ด๊ณ  ์ž‘์—… contract์— ์†ํ•˜์ง€ ์•Š๋Š” ํ•„๋“œ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
  3. ์ž๋™์œผ๋กœ ์ถ”๋ก ํ•  ์ˆ˜ ์—†๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ์ž…๋ ฅ ๊ทœ์น™์œผ๋กœ validator๋ฅผ ๊ฐ•ํ™”ํ•ฉ๋‹ˆ๋‹ค.
  4. handler๋ฅผ ๊ฒ€ํ† ํ•˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต์—์„œ ๋ถˆ๋ณ€์‹์„ ์ค‘๋ณตํ•˜์ง€ ์•Š๊ณ  ๋„๋ฉ”์ธ ๋™์ž‘์„ ํ˜ธ์ถœํ•˜๋Š”์ง€ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
  5. persistence์—๋Š” IUnitOfWork๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ž‘์—…์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋ฒคํŠธ ๋˜๋Š” Outbox๋„ ์š”๊ตฌํ•  ๋•Œ๋Š” transactional save๋ฅผ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.
  6. ์˜ˆ์ƒ๋œ ๋น„์ฆˆ๋‹ˆ์Šค ๊ฒฐ๊ณผ์—๋Š” ์˜ˆ์™ธ๊ฐ€ ์•„๋‹ˆ๋ผ Result ์˜ค๋ฅ˜๋กœ ์‹คํŒจ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  7. Command๋ฅผ ํ˜ธ์ถœํ•  endpoint, page ๋˜๋Š” integration์„ ์ปดํŒŒ์ผํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.

์‹ค๋ฌด ๊ทœ์น™: generator๋Š” architectural skeleton์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ตœ์ข… ์ •ํ™•์„ฑ์€ ๋„๋ฉ”์ธ ์–ธ์–ด, ๋ถˆ๋ณ€์‹, persistence ์š”๊ตฌ ์‚ฌํ•ญ, ๋ชจ๋“ˆ ๊ฒฝ๊ณ„์— ๋น„์ถ”์–ด use case๋ฅผ ๊ฒ€ํ† ํ•˜๋Š” ๋ฐ์„œ ๋‚˜์˜ต๋‹ˆ๋‹ค.

Queries

Query๋Š” ๋„๋ฉ”์ธ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์œผ๋ ค๋Š” ์˜๋„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. Queries๋Š” ํšจ์œจ์ ์ธ ์ฝ๊ธฐ๋ฅผ ์œ„ํ•ด ์„ค๊ณ„๋˜๋ฉฐ, ํ•„์š”ํ•˜์ง€ ์•Š์„ ๋•Œ ์ „์ฒด ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋กœ๋“œํ•˜์ง€ ์•Š๊ณ  caller์—๊ฒŒ ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ์ •ํ™•ํžˆ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ์˜ˆ๋กœ๋Š” GetCustomerById, ListCustomers, ListPhoneTypes, ListOrdersByDateRange, ๊ทธ๋ฆฌ๊ณ  GetVehicleAvailability ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ง€์ • query๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Query๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ • ์งˆ๋ฌธ์— ๋‹ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Query์˜ ํŠน์ง•

  • ๋ถˆ๋ณ€: Commands์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Query๋Š” ์ƒ์„ฑ๋œ ํ›„ ๋ณ€๊ฒฝ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์„ค๋ช…์ ์ธ ์ด๋ฆ„: GetCustomerById ๋˜๋Š” ListOrdersByDateRange์ฒ˜๋Ÿผ ์ฐพ๋Š” ์ •๋ณด๋ฅผ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.
  • Filters ๋ฐ pagination: dates, status, page, page size, search text, ordering ๋ฐ ๊ธฐํƒ€ ์ฝ๊ธฐ parameters๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Projection: ๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ง์ ‘ ๋…ธ์ถœํ•˜์ง€ ์•Š๊ณ  ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ๊ฐ€์ง„ DTO ๋˜๋Š” view model์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ถ€์ž‘์šฉ ์—†์Œ: ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ database์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ €์žฅํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

Query๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

  • ์ž‘์—…์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ด์„œ๋Š” ์•ˆ ๋  ๋•Œ Query๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒ์„ธ ํ™”๋ฉด, ์‹๋ณ„์ž ๊ฒ€์ƒ‰, availability checks ๋˜๋Š” ๋‹จ์ผ ๊ฐ์ฒด ์‘๋‹ต์—๋Š” ๋‹จ์ผ ๊ฒฐ๊ณผ Query๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • grids, option lists, child collections, selection controls์—๋Š” list Query๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • grids ๋ฐ ์ž ์žฌ์ ์œผ๋กœ ํฐ ๋ฐ์ดํ„ฐ ์„ธํŠธ์—๋Š” pagination์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ž‘์€ reference data, enumerations, options endpoints์—๋Š” ๋‹จ์ˆœ lists๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Query Validators

Query Validators๋Š” filters, pagination values, date ranges, identifiers, visibility rules ๊ฐ™์€ ์ž…๋ ฅ parameters๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ์ด๋“ค๋„ FluentValidation์œผ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.

Queries์˜ ์ผ๋ฐ˜์ ์ธ ๊ฒ€์ฆ ๊ทœ์น™

  • ์‹œ์ž‘์ผ๊ณผ ์ข…๋ฃŒ์ผ ๊ฐ™์€ range filters์—๋Š” GreaterThanOrEqualTo ๋ฐ LessThanOrEqualTo.
  • ์ด๋ฆ„, email, search term ๊ฐ™์€ text filters์—๋Š” Length, MaximumLength, MinimumLength.
  • page ๋ฐ pageSize๋ฅผ ์ œํ•œํ•˜๋Š” pagination์—๋Š” InclusiveBetween.
  • detail queries์˜ ํ•„์ˆ˜ identifiers์—๋Š” NotEmpty.
  • ์ข…๋ฃŒ์ผ์ด ์‹œ์ž‘์ผ๋ณด๋‹ค ๋น ๋ฅธ ๊ฒฝ์šฐ์ฒ˜๋Ÿผ ์ž˜๋ชป๋œ filter ์กฐํ•ฉ์—๋Š” Must.

Query Handlers

Query Handler๋Š” repositories ๋˜๋Š” database context๋ฅผ ์กฐํšŒํ•˜๊ณ  ์ตœ์ ํ™”๋œ projections๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. Lino์—์„œ๋Š” ์ ์ ˆํ•  ๋•Œ Select๋ฅผ ์‚ฌ์šฉํ•œ projections, ๋ช…์‹œ์  filters, ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ordering, no-tracking reads๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

Query handler๋Š” read-only์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋„๋ฉ”์ธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ , ์˜์† ๋ณ€๊ฒฝ์„ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š์œผ๋ฉฐ, SaveChanges๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฝ๊ธฐ ์ž‘์—…์ด audit์„ ๊ธฐ๋กํ•˜๊ฑฐ๋‚˜ integration์„ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ์ƒํƒœ๋ฅผ ์žฌ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ์ด๋Š” ๋ณดํ†ต ๋‹ค๋ฅธ use case ๋˜๋Š” ๋ณ„๋„ process๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค.

Query Results

Lino์—์„œ Queries์˜ ๊ฒฐ๊ณผ๋Š” QueryResult suffix๊ฐ€ ๋ถ™์€ records๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค. ์ด convention์€ ๋‹จ์ผ ์‘๋‹ต, ๋‹จ์ˆœ list, paginated list, ๋˜๋Š” ํ™”๋ฉด, API, integration, background process์šฉ ํŠน์ • DTO ๋ชจ๋‘์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

query results๋Š” ์•ˆ์ •์ ์ธ read contracts์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ง์ ‘ ๋…ธ์ถœํ•˜๊ธฐ ์œ„ํ•œ shortcut์ด ์•„๋‹ˆ๋ผ consumer๋ฅผ ์œ„ํ•ด ์„ค๊ณ„๋œ DTOs๋กœ ๋‹ค๋ฃจ์„ธ์š”.

CLI๋กœ Query ๋งŒ๋“ค๊ธฐ

Commands์™€ ๋น„์Šทํ•˜๊ฒŒ Lino๋Š” ๋‹ค์Œ command๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

lino query new

CLI๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ต์…˜๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค:

lino query new --service <ServiceName> --module <ModuleName> --entity <EntityName> --name <QueryName>
lino query new --name <QueryName> --service <ServiceName> --module <ModuleName> --entity <EntityName>
lino query list --service <ServiceName> --module <ModuleName> --entity <EntityName>
  • -s ๋˜๋Š” --service: ๋Œ€์ƒ ์„œ๋น„์Šค.
  • -m ๋˜๋Š” --module: ๋Œ€์ƒ ๋ชจ๋“ˆ.
  • -e ๋˜๋Š” --entity: Query์™€ ์—ฐ๊ฒฐ๋œ ์—”ํ‹ฐํ‹ฐ.
  • -n, --name, -q ๋˜๋Š” --query: Query ์ด๋ฆ„.

๋Œ€ํ™”ํ˜• ํ๋ฆ„ ์ค‘ Lino๋Š” Query๊ฐ€ ๋‹จ์ผ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€ list๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€ ๋ฌป์Šต๋‹ˆ๋‹ค. ์‘๋‹ต์ด list์ด๋ฉด pagination์ด ํ•„์š”ํ•œ์ง€๋„ ๋ฌป์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฐ˜ํ™˜๋˜๊ฑฐ๋‚˜ ์ƒ์„ฑ๋œ projection์—์„œ ์‚ฌ์šฉ๋  ์†์„ฑ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

Lino๋Š” ์ž๋™์œผ๋กœ ๋‹ค์Œ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:

  • GetOrderByIdQuery.cs
  • GetOrderByIdQueryValidator.cs
  • GetOrderByIdQueryHandler.cs
  • GetOrderByIdQueryResult.cs

Queries์šฉ ์ƒ์„ฑ ๊ตฌ์กฐ ์˜ˆ์‹œ

<ProjectName>/
โ””โ”€โ”€ src/
    โ””โ”€โ”€ Services/
        โ””โ”€โ”€ <ServiceName>/
            โ””โ”€โ”€ Application/
                โ”œโ”€โ”€ <ProjectName>.<ServiceName>.Application.csproj
                โ””โ”€โ”€ UseCases/
                    โ””โ”€โ”€ Orders/
                        โ”œโ”€โ”€ Commands/
                        |   โ””โ”€โ”€ ...
                        โ””โ”€โ”€ Queries/
                            โ””โ”€โ”€ GetOrderById/
                                โ”œโ”€โ”€ GetOrderByIdQuery.cs
                                โ”œโ”€โ”€ GetOrderByIdQueryValidator.cs
                                โ”œโ”€โ”€ GetOrderByIdQueryHandler.cs
                                โ””โ”€โ”€ GetOrderByIdQueryResult.cs

Vehicle availability์šฉ ์‚ฌ์šฉ์ž ์ง€์ • Query๋„ ๊ฐ™์€ ํŒจํ„ด์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค:

Application/UseCases/Vehicles/Queries/GetVehicleAvailability/
โ”œโ”€โ”€ GetVehicleAvailabilityQuery.cs
โ”œโ”€โ”€ GetVehicleAvailabilityQueryValidator.cs
โ”œโ”€โ”€ GetVehicleAvailabilityQueryHandler.cs
โ””โ”€โ”€ GetVehicleAvailabilityQueryResult.cs

Query ํŒŒ์ผ์˜ ์ฑ…์ž„

  • Query: identifiers, filters, ordering, pagination ๋˜๋Š” date ranges๋ฅผ ๋‹ด๋Š” ๋ถˆ๋ณ€ ์š”์ฒญ contract.
  • Validator: identifiers, pagination, required filters, date ranges, search criteria ๊ฒ€์ฆ.
  • Handler: application context, projections, filters, ordering, pagination, logging, tracing, ๊ฒฐ๊ณผ ์ƒ์„ฑ์„ ์‚ฌ์šฉํ•œ read orchestration.
  • Result: caller๋ฅผ ์œ„ํ•ด ๋ชจ๋ธ๋ง๋œ response DTO์ด๋ฉฐ, list items๋ฅผ ์œ„ํ•œ ๋‚ด๋ถ€ records๋ฅผ ์ž์ฃผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

๊ตฌํ˜„ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  1. lino query new๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์„œ๋น„์Šค, ๋ชจ๋“ˆ, ์—”ํ‹ฐํ‹ฐ, Query ์ด๋ฆ„, ๋ฐ˜ํ™˜ ํƒ€์ž…, pagination mode, ์†์„ฑ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
  2. ์š”์ฒญ contract๋ฅผ ๊ฒ€ํ† ํ•˜๊ณ  caller์—๊ฒŒ ์‹ค์ œ๋กœ ํ•„์š”ํ•œ filters๋งŒ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  3. ํŠนํžˆ ํ•„์ˆ˜ identifiers, date ranges, page size limits, ์ž˜๋ชป๋œ filter ์กฐํ•ฉ์— ๋Œ€ํ•ด validator๋ฅผ ๊ฐ•ํ™”ํ•ฉ๋‹ˆ๋‹ค.
  4. handler projection์„ ์กฐ์ •ํ•ด UI, API, integration ๋˜๋Š” background process๊ฐ€ ์š”๊ตฌํ•˜๋Š” ํ•„๋“œ๋งŒ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  5. Query๋ฅผ read-only๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋„๋ฉ”์ธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  handler์—์„œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ €์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  6. ์ ์ ˆํ•  ๋•Œ ๊ธฐ์กด ํ‘œ์ค€ ์˜ค๋ฅ˜๋ฅผ ์‚ฌ์šฉํ•ด ์˜ˆ์ƒ๋œ ์‹คํŒจ๋ฅผ Result๋กœ ์ „ํŒŒํ•ฉ๋‹ˆ๋‹ค.
  7. API endpoint, Blazor page, in-process integration ๋˜๋Š” typed client์ฒ˜๋Ÿผ Query๋ฅผ ํ˜ธ์ถœํ•˜๋Š” consumer๋ฅผ ์ปดํŒŒ์ผํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ง€์ • Query ์˜ˆ์‹œ

SaaS์˜ ๋ชจ๋“ˆ ๊ฐ„ integration ํ๋ฆ„์—์„œ๋Š” lino query new๋กœ vehicle availability์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • Query๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ์„ฑ๋œ ๊ตฌ์กฐ๋Š” Query, Handler, Result, Validator๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ ๊ฐœ๋ฐœ์ž๋Š” vehicle identifier, start date, end date ๊ฐ™์€ ํ•„์š”ํ•œ ์ž…๋ ฅ์„ ์ถ”๊ฐ€ํ•˜๊ณ , range๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ์ง€ ๊ฒ€์ฆํ•˜๊ณ , handler logic์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๊ธฐ๋Œ€๋˜๋Š” ํ๋ฆ„์ž…๋‹ˆ๋‹ค. ๋จผ์ € ์ผ๊ด€๋œ ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•œ ๋’ค ๋ช…์‹œ์ ์ธ ์ฝ”๋“œ๋กœ ๋„๋ฉ”์ธ๋ณ„ ๋™์ž‘์„ ์™„์„ฑํ•ฉ๋‹ˆ๋‹ค.

Read model ์ง€์นจ: Query results๋Š” ์•ˆ์ •์ ์ธ contracts์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ง์ ‘ ๋…ธ์ถœํ•˜๊ธฐ ์œ„ํ•œ shortcut์ด ์•„๋‹ˆ๋ผ caller๋ฅผ ์œ„ํ•ด ์„ค๊ณ„๋œ DTOs๋กœ ๋‹ค๋ฃจ์„ธ์š”.

๊ฒฐ๋ก 

Lino์—์„œ use cases๋ฅผ ์ •์˜ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋„๋ฉ”์ธ ๋ชจ๋ธ์„ ๋ช…ํ™•ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž‘์—…์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Commands๋Š” ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , Queries๋Š” ์ฝ๊ธฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, validators๋Š” ์ž…๋ ฅ ๊ฒฝ๊ณ„๋ฅผ ๋ณดํ˜ธํ•˜๊ณ , handlers๋Š” ํ๋ฆ„์„ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ํ•˜๋ฉฐ, ๊ฒฐ๊ณผ ๊ฐ์ฒด๋Š” ์ถœ๋ ฅ์„ ํ‘œ์ค€ํ™”ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ๋น ๋ฅธ ํ๋ฆ„์€ ๋ณดํ†ต ๋„๋ฉ”์ธ์„ ๋ชจ๋ธ๋งํ•˜๊ณ , ํ•„์š”ํ•œ Commands์™€ Queries๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ƒ์„ฑ๋œ ํŒŒ์ผ์„ ๊ฒ€ํ† ํ•˜๊ณ , ๋น„์ฆˆ๋‹ˆ์Šค ๋™์ž‘์„ ์™„์„ฑํ•˜๊ณ , ํ•„์š”ํ•  ๋•Œ API ๋˜๋Š” page๋กœ use case๋ฅผ ๋…ธ์ถœํ•œ ๋’ค build์™€ tests๋กœ ๋ชจ๋‘ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด architectural control์„ ์žƒ์ง€ ์•Š์œผ๋ฉด์„œ ๊ฐœ๋ฐœ ์†๋„๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ๊ฐ use case๋ฅผ ํ•˜๋‚˜์˜ ๋น„์ฆˆ๋‹ˆ์Šค ์˜๋„์— ์ง‘์ค‘์‹œํ‚ค๊ณ , ์„œ๋น„์Šค์™€ ๋ชจ๋“ˆ ๊ฒฝ๊ณ„๋ฅผ ์กด์ค‘ํ•˜๋ฉฐ, ๋‹ค๋ฅธ ๋ชจ๋“ˆ์ด ํ”„๋กœ์„ธ์Šค์— ์ฐธ์—ฌํ•ด์•ผ ํ•  ๋•Œ๋Š” ์ด๋ฒคํŠธ, ํ†ตํ•ฉ ๋˜๋Š” shadow entities๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

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