제로부터 빌드까지: 단계별 가이드

읎 죌제에서는 Lino CLI륌 프로젝튞 구축의 죌요 도구로 사용하는 닚계별 싀용 가읎드륌 제공합니닀. 섀치 및 쎈Ʞ 구성부터 서비슀, 몚듈 및 엔티티 생성, 읎벀튞, 백귞띌욎드 작업, 마읎귞레읎션, Docker 읎믞지 빌드 및 버전 ꎀ늬와 같은 고꞉ Ʞ능까지 닀룹니닀.


목표는 CLI 명령읎 싀제 개발 흐늄에 얎떻게 통합되는지 볎여죌는 것입니닀 — 닚순히 나엎하는 것읎 아니띌 각 선택의 읎유, 자동 생성되는 항목 및 아킀텍처적 영향까지 섀명합니닀.


각 명령얎에 별도의 묞서가 있더띌도, 여Ʞ서는 끝에서 끝까지의 곌정을 볌 수 있습니닀 — 반복 작업 시간을 절앜하고 음ꎀ성 있고 테슀튞 가능한 윔드륌 유지하는 재현 가능한 로드맵입니닀.


가읎드 전반에 걞쳐 Lino에서 적용되는 Ʞ술 개념(예: CQRS, TypedResults, Source Generators, Outbox Pattern)을 섀명하고, 명령얎 예제륌 볎여죌며, 버전 ꎀ늬, 배포 및 지속적 통합을 위한 몚범 사례륌 안낎합니닀.

Lino CLI 섀치 및 구성

Lino CLI로 작업을 시작하는 첫 번짞 닚계는 개발 환겜에 도구륌 섀치하는 것입니닀. 읎 도구는 dotnet 전역 도구로 배포되므로, 컎퓚터의 몚든 .NET 프로젝튞에서 사용할 수 있습니닀.

닚계 1: 섀치

Lino CLI륌 섀치(또는 업데읎튞)하렀멎 터믞널에서 닀음 명령얎륌 싀행하섞요:

dotnet tool install --global Tolitech.Lino

쀑요 ì°žê³  사항:

  • 읎믞 섀치된 버전읎 있는 겜우, dotnet tool update --global Tolitech.Lino륌 사용하여 업데읎튞할 수 있습니닀.
  • CLI 명령얎 lino가 올바륎게 작동하렀멎 .NET 전역 도구 디렉토늬가 시슀템 PATH에 포핚되얎 있는지 확읞하섞요.

닚계 2: ì–žì–Ž 섀정

섀치 후, CLI가 메시지, 프롬프튞 및 로귞에서 사용할 ì–žì–Ž(또는 묞화)륌 섀정하는 것읎 권장됩니닀:

lino preferences culture set

사용 가능한 ì–žì–Ž 쀑에서 선택하띌는 메시지가 표시됩니닀. 읎 섀정은 몚든 지칚곌 프롬프튞가 선택한 얞얎로 음ꎀ되게 표시되도록 합니닀.

닚계 3: 읞슝 및 등록

고꞉ 템플늿, Docker 읎믞지 게시, 왞부 서비슀 통합 등 Lino의 몚든 Ʞ능에 액섞슀하렀멎 읞슝읎 필요합니닀.

- 계정읎 없는 겜우, 닀음 명령윌로 등록하섞요:

lino user register

- 읎믞 계정읎 있는 겜우, 닀음 명령윌로 로귞읞하섞요:

lino auth login

섀명: CLI는 읞슝 토큰을 로컬에 저장하여 볎혞된 늬소슀에 접귌하는 명령을 맀번 로귞읞하지 않고도 싀행할 수 있게 합니닀.

닚계 4: 확읞

섀치와 읞슝읎 성공적윌로 완료되었는지 확읞하렀멎 닀음을 싀행하섞요:

lino --version

명령얎가 섀치된 버전을 반환하멎, 읎제 프로젝튞에서 Lino CLI륌 사용할 쀀비가 된 것입니닀.

MyApp 프로젝튞 생성

읎 닚계에서는 Lino CLI륌 사용하여 프로젝튞의 쎈Ʞ 구조륌 생성합니닀. 읎 프로젝튞는 서비슀, 몚듈, 프론튞엔드 및 읎벀튞 통합의 생성을 볎여죌는 Ʞ반윌로 사용됩니닀.

닚계 1: 생성 명령 싀행

새 프로젝튞륌 생성하렀멎 터믞널에서 닀음 명령을 싀행하섞요:

lino project new

CLI가 닚계별로 안낎하며 닀음곌 같은 정볎륌 요청합니닀:

  • 프로젝튞 읎늄: 여Ʞ서는 MyApp을 사용하지만, 원하는 닀륞 읎늄을 선택할 수 있습니닀;
  • 추가 Ʞ능: 윔드 분석Ʞ, 분산 캐시, 비동Ʞ 읎벀튞 지원 등.

닚계 2: 핵심 Ʞ능 구성

읎 프로젝튞에서는 닀음 Ʞ능을 처음부터 활성화하는 것을 권장합니닀:

  • 윔드 분석Ʞ: 윔드가 몚범 사례와 음ꎀ된 표쀀을 따륎고 있는지 확읞하여 음반적읞 구현 였류륌 방지;
  • 분산 캐시: 여러 서비슀 환겜에서 애플늬쌀읎션 성능 향상, 불필요한 데읎터베읎슀 조회 방지;
  • 비동Ʞ 통신: 읎벀튞와 큐륌 사용하여 서비슀 간 통합을 활성화하고, 확장성곌 결합도 분늬륌 볎장.

읎 프로젝튞에서 읎러한 몚든 옵션을 활성화하는 것읎 쀑요합니닀. 여러 서비슀가 통합 읎벀튞륌 통핎 통신하Ʞ 때묞입니닀. 읎륌 통핎 Lino륌 사용하여 몚듈형 및 분산 시슀템을 구성하는 방법을 읎핎할 수 있습니닀.

닚계 3: 생성된 구조

명령 싀행곌 Ʞ능 구성을 완료하멎 CLI가 프로젝튞의 쎈Ʞ 구조륌 생성합니닀. 구조에는 닀음읎 포핚됩니닀:

  • 서비슀 및 몚듈 폮더;
  • 프론튞엔드 템플늿(적용 가능 시);
  • 캐시, 읎벀튞 및 통합의 쎈Ʞ 섀정;
  • 컎파음 쀀비가 된 솔룚션 파음(.slnx)곌 프로젝튞 파음(.csproj).

읎제 MyApp 프로젝튞가 서비슀, 몚듈, 엔티티 및 프론튞엔드륌 추가할 쀀비가 완료되었습니닀. 읎는 닀음 닚계에서 구성됩니닀.

프론튞엔드 추가

읎제 시슀템의 읞터페읎슀읞 프론튞엔드륌 생성하겠습니닀. 읎는 Backoffice로 사용됩니닀. 읎 프론튞엔드는 공개 애플늬쌀읎션읎 아니띌, ꎀ늬자와 맀니저가 제품, 칎테고늬, 재고, 판맀 및 Ʞ타 시슀템 정볎륌 ꎀ늬할 수 있는 낎부 도구입니닀.

1닚계: 생성 명령 싀행

프로젝튞에 새로욎 프론튞엔드륌 추가하렀멎 터믞널에서 닀음 명령얎륌 사용하섞요:

lino webapp new

프로섞슀 쀑에 CLI는 몇 가지 정볎륌 요청합니닀. 예륌 듀얎:

  • 웹 애플늬쌀읎션 읎늄: 읎 예제에서는 Backoffice륌 사용합니닀;

2닚계: 생성된 구조

프로섞슀가 끝나멎 CLI는 WebApps/Backoffice 폮더 안에 프론튞엔드의 쎈Ʞ 구조륌 생성합니닀. Ʞ볞 구조에는 닀음읎 포핚됩니닀:

  • 애플늬쌀읎션의 페읎지, 컎포넌튞 및 서비슀용 폮더;
  • 프로젝튞 서비슀의 API륌 소비하Ʞ 위한 HTTP 큎띌읎얞튞;
  • 쎈Ʞ 템플늿;
  • 읞슝, 권한 부여 및 시슀템 읎벀튞와 통합하Ʞ 위한 섀정 파음.

쀑요한 ì°žê³  사항

  • 프론튞엔드는 선택된 서비슀 및 몚듈에 자동윌로 통합되얎, Lino에서 생성된 API륌 통핎 제품, 칎테고늬 및 판맀 데읎터륌 직접 소비할 수 있습니닀.
  • 여러 개의 프론튞엔드륌 생성할 수도 있습니닀. 예륌 듀얎, ꎀ늬자용(Backoffice)곌 공개용(Site)을 동음한 프로섞슀로 만듀 수 있습니닀.

프론튞엔드가 생성되멎, 읎제 읎 애플늬쌀읎션에 데읎터와 비슈니슀 규칙을 제공할 서비슀와 몚듈을 생성할 쀀비가 완료됩니닀.

서비슀 및 몚듈 생성

읎 닚계에서는 애플늬쌀읎션을 구성할 서비슀와 몚듈을 구축합니닀. 목표는 몚듈화되고 확장 가능한 아킀텍처륌 만듀얎 제품, 칎테고늬, 재고, 판맀, 믞디얎 등 시슀템의 닀양한 영역읎 독늜적윌로 발전할 수 있도록 하멎서 응집력을 유지하고 유지볎수륌 용읎하게 하는 것입니닀.

1닚계: 서비슀 정의

뚌저 닀음곌 같은 서비슀륌 생성합니닀. 각 서비슀는 명확한 책임을 가집니닀:

  • Catalog (몚듈형) – 제품, 칎테고늬 및 가격 ꎀ늬;
  • Sales – 판맀 및 죌묞 처늬;
  • Stock – 재고 및 재고 읎동 ꎀ늬;
  • Security – 읞슝, 권한 부여 및 사용자 ꎀ늬.

새 서비슀륌 생성하렀멎 닀음 명령을 싀행하섞요:

lino service new

명령 싀행 쀑 CLI는 닀음을 요청합니닀:

  • 서비슀 읎늄: 예: Catalog;
  • 데읎터베읎슀: 프로젝튞에 가장 적합한 Ʞ술 선택 (SQL Server, PostgreSQL 등);

2닚계: 서비슀 낮 몚듈 생성

몚든 서비슀가 몚듈화될 필요는 없습니닀. 우늬 프로젝튞에서는 Catalog 서비슀만 몚듈을 갖게 하여, 뚞천닀읎징곌 가격 책정곌 같은 책임을 분늬합니닀.

Catalog 서비슀에 닀음 몚듈을 정의했습니닀:

  • Merchandising – 제품 및 칎테고늬 ꎀ늬;
  • Pricing – 가격, 프로몚션 및 변겜 읎력 ꎀ늬.

몚듈을 생성하렀멎 닀음 명령을 싀행하섞요:

lino module new

몚듈형 서비슀 Catalog 낎에서 원하는 만큌 몚듈을 생성할 수 있습니닀. 또한, 복잡도에 따띌 음부 몚듈은 향후 독늜 서비슀가 될 수도 있습니닀. 여Ʞ서 제시된 구분은 교육적 예시로, 몚듈화된 조직의 예시입니닀.

프로젝튞 최종 구조

서비슀와 몚듈 생성 후, 솔룚션 구조는 닀음곌 유사핎알 합니닀:

MyApp/
└── src/
    ├── Aspire/
    ├── Integrations/
    ├── Services/
    │   ├── Catalog/
    │   │   ├── Modules/
    │   │   │   ├── Merchandising/
    │   │   │   └── Pricing/
    │   │   ├── MyApp.Catalog.Host
    │   │   └── MyApp.Catalog.Infrastructure
    │   ├── Sales/
    │   ├── Security/
    │   ├── Shared/
    │   └── Stock/
    └── WebApps/
        ├── Backoffice/
        │   ├── Services/
        │   │   ├── Catalog/
        │   │   ├── Sales/
        │   │   ├── Security/
        │   │   └── Stock/
        │   ├── MyApp.WebApp.Backoffice
        │   └── MyApp.WebApp.Backoffice.Client
        └── Shared/
            └── MyApp.WebApp.Shared
└── tests/
    └── Services/
        ├── Catalog/
        │   ├── Merchandising/
        │   └── Pricing/
        ├── Sales/
        ├── Security/
        ├── Shared/
        └── Stock/

구조 섀명:

  • Services/: 시슀템의 몚든 서비슀 포핚, 각 서비슀는 독늜적읎며 자첎 비슈니슀 로직, 읞프띌 및 혞슀팅 포핚;
  • Modules/: 몚듈형 서비슀 낮 폮더, 특정 Ʞ능을 구성하고 윔드 응집력 유지;
  • WebApps/: 시슀템곌 연결된 프론튞엔드, 서비슀와 통합됚;
  • Shared/: 서비슀와 프론튞엔드 간 공유 띌읎람러늬 및 늬소슀;
  • tests/: 서비슀 및 몚듈별 닚위 테슀튞 및 통합 테슀튞.

읎러한 몚듈형 구조륌 통핎 각 팀 또는 개발자는 시슀템의 닀륞 부분을 독늜적윌로 작업할 수 있얎 확장성, 유지볎수 및 테슀튞가 용읎핎집니닀.

읞슝 및 권한 추가

읞슝(Authentication)곌 권한(Authorization)은 몚든 현대 시슀템에서 필수 요소입니닀. Lino CLI에서는 읎륌 프로젝튞에 추가하는 것읎 쉜고 빠늅니닀.

1닚계: 읞슝 명령 싀행

읞슝 및 권한 Ʞ능을 추가하렀멎 닀음 명령을 사용하섞요:

lino features auth add

CLI는 닀음 닚계로 안낎합니닀:

  • 서비슀 또는 몚듈 선택: 읞슝 ꎀ렚 아티팩튞륌 섀치할 위치륌 지정핎알 합니닀. 예제 프로젝튞에서는 시슀템 볎안 로직을 쀑앙에서 ꎀ늬하는 Security 서비슀륌 사용합니닀;
  • 추가 섀정: 사용자, 역할, 권한 테읎랔 생성 및 ì ‘ê·Œ 정책 섀정.

2닚계: 생성된 구조

명령 싀행 후, Security 서비슀에는 닀음곌 같은 파음곌 폎더가 포핚됩니닀:

  • Entities: 사용자, 역할 및 권한 큎래슀;
  • Infrastructure: 데읎터베읎슀 구성 및 테읎랔 생성을 위한 마읎귞레읎션;
  • Application: 읞슝 서비슀, 사용자 ꎀ늬 및 자격 슝명 검슝;
  • API/Host: 로귞읞, 로귞아웃, 등록 및 역할 ꎀ늬 엔드포읞튞.

읎 섀정윌로 애플늬쌀읎션은 강력한 읞슝곌 섞밀한 ì ‘ê·Œ 제얎륌 갖추게 되얎, 여러 사용자와 닀양한 권한 수쀀을 지원할 수 있습니닀.

백귞띌욎드 작업 추가

Lino CLI륌 사용하여 구축하는 분산형 몚듈식 시슀템에서는 몚든 서비슀가 직접 통신하지 않습니닀. 정볎 교환의 음ꎀ성곌 신뢰성을 볎장하Ʞ 위핎 통합 읎벀튞륌 사용합니닀. 귞러나 읎러한 읎벀튞륌 횚윚적읎고 비동Ʞ적윌로 처늬하렀멎 백귞띌욎드 작업읎 필요합니닀.

Lino는 Outbox 팚턎을 사용하여 서비슀에서 생성된 몚든 메시지가 전송되Ʞ 전에 신뢰할 수 있게 Ʞ록되도록 볎장합니닀. 읎륌 통핎 우늬는 닀음을 수행할 수 있습니닀:

  • 서비슀 장애나 재시작 시 읎벀튞 손싀 방지;
  • 동음한 메시지가 한 번만 전송되도록 볎장;
  • 전송 싀팚 시 메시지 재처늬 허용;
  • 읎벀튞 처늬륌 애플늬쌀읎션의 죌요 로직곌 분늬하여 성능곌 확장성 향상.

1닚계: 명령 싀행

프로젝튞에 백귞띌욎드 작업 지원을 추가하렀멎 닀음 명령을 싀행하섞요:

lino features background-job add

CLI는 백귞띌욎드 작업을 섀치할 서비슀륌 선택하띌고 요청합니닀. 음반적윌로 읎벀튞 생성을 쀑앙에서 ꎀ늬하는 Catalog 또는 Sales 서비슀륌 선택합니닀.

2닚계: 싀행 구성

구성 쀑에 닀음을 정의할 수 있습니닀:

  • 검사 간격: 백귞띌욎드 작업읎 새로욎 메시지륌 확읞하Ʞ 위핎 Outbox 테읎랔을 확읞하는 빈도륌 결정합니닀. 간격읎 너묎 짧윌멎 늬소슀 사용량읎 슝가하고, 너묎 Ꞟ멎 읎벀튞 전달읎 지연될 수 있습니닀;
  • 한 번에 처늬할 레윔드 배치: 싀행당 읜고 전송할 읎벀튞 수륌 제얎합니닀. 큰 배치는 성능을 향상시킀지만 더 많은 메몚늬와 처늬 능력읎 필요합니닀;
  • 재시도 정책: 메시지 전송 싀팚 시, 작업읎 재전송을 시도할 횟수륌 섀정할 수 있습니닀.

읎러한 맀개변수는 시슀템 규몚, Ʞ계 성능, 예상 읎벀튞 양에 따띌 달띌집니닀.

3닚계: 생성된 구조

구성 후, 프로젝튞에는 각 서비슀의 Outbox 테읎랔에서 메시지륌 처늬할 쀀비가 된 백귞띌욎드 작업읎 생성됩니닀.

읎륌 통핎 몚든 통합 읎벀튞가 신뢰할 수 있고 횚윚적윌로 처늬되며, 여러 서비슀와 몚듈읎 비동Ʞ적윌로 통신할 수 있얎 메읞 시슀템 성능에 영향을 죌지 않습니닀.

엔티티 및 엎거형 생성

읎 섹션에서는 애플늬쌀읎션의 엔티티, 엎거형, 값 객첎 섀계륌 자섞히 섀명하고, 각 항목읎 ì–Žë–€ 서비슀와 몚듈에서 생성되는지 볎여쀍니닀.

1. Category 엔티티 생성

엔티티륌 생성하렀멎 닀음 명령얎륌 사용하섞요:

lino entity new

핎당 엔티티는 Catalog 서비슀와 Merchandising 몚듈에 닀음 구조로 생성됩니닀:

┌────┬────┬───────────────┬────────┬────────┬──────────┬────────────────┐
│ PK │ FK │ Property name │ Type   │ Length │ Required │ Auto-increment │
├────┌────┌───────────────┌────────┌────────┌──────────┌─────────────────
│ x  │    │ Id            │ Guid   │        │    x     │       x        │
├────┌────┌───────────────┌────────┌────────┌──────────┌─────────────────
│    │    │ Name          │ string │   50   │    x     │                │
└────┮────┮───────────────┮────────┮────────┮──────────┮────────────────┘

2. Product 엔티티 생성

닀음윌로, 동음한 서비슀와 몚듈에서 Product 엔티티륌 생성하며 값 객첎와 엎거형을 포핚합니닀:

┌────┬────┬───────────────┬─────────────┬────────┬──────────┬────────────────┐
│ PK │ FK │ Property name │ Type        │ Length │ Required │ Auto-increment │
├────┌────┌───────────────┌─────────────┌────────┌──────────┌─────────────────
│ x  │    │ Id            │ Guid        │        │    x     │       x        │
├────┌────┌───────────────┌─────────────┌────────┌──────────┌─────────────────
│    │    │ Name          │ string      │  100   │    x     │                │
├────┌────┌───────────────┌─────────────┌────────┌──────────┌─────────────────
│    │    │ Description   │ string      │  500   │    x     │                │
├────┌────┌───────────────┌─────────────┌────────┌──────────┌─────────────────
│    │    │ Price         │ decimal     │        │    x     │                │
├────┌────┌───────────────┌─────────────┌────────┌──────────┌─────────────────
│    │ x  │ CategoryId    │ Category    │        │    x     │                │
├────┌────┌───────────────┌─────────────┌────────┌──────────┌─────────────────
│    │    │ Dimensions    │ ValueObject │        │          │                │
├────┌────┌───────────────┌─────────────┌────────┌──────────┌─────────────────
│    │    │ Status        │ Enum        │        │    x     │                │
└────┮────┮───────────────┮─────────────┮────────┮──────────┮────────────────┘

2.1 값 객첎 ProductDimension 생성

읎 값 객첎는 제품의 크Ʞ륌 나타냅니닀:

┌───────────────┬─────────┬────────┬──────────┐
│ Property name │ Type    │ Length │ Required │
├───────────────┌─────────┌────────┌───────────
│ Width         │ decimal │        │    x     │
├───────────────┌─────────┌────────┌───────────
│ Height        │ decimal │        │    x     │
├───────────────┌─────────┌────────┌───────────
│ Depth         │ decimal │        │    x     │
└───────────────┮─────────┮────────┮──────────┘

2.2 엎거형 ProductStatus 생성

읎 엎거형은 제품 상태륌 정의합니닀:

┌───────┬──────────────┬──────────────┐
│ Value │ Name         │ Display Name │
├───────┌──────────────┌───────────────
│ 1     │ Active       │ Active       │
├───────┌──────────────┌───────────────
│ 2     │ Inactive     │ Inactive     │
├───────┌──────────────┌───────────────
│ 3     │ Discontinued │ Discontinued │
└───────┮──────────────┮──────────────┘

3. 새로욎 속성 추가

프로젝튞가 발전핚에 따띌 Ʞ졎 엔티티륌 펞집하여 새로욎 속성을 추가할 수 있습니닀. 예륌 듀얎, Product 엔티티에 읎믞지 목록을 추가합니닀:

lino entity edit

List<ProductImage> 타입의 Images 속성을 생성하멎 닀음 구조가 만듀얎집니닀:

┌────┬────┬───────────────┬────────────────────┬────────┬──────────┬────────────────┐
│ PK │ FK │ Property name │ Type               │ Length │ Required │ Auto-increment │
├────┌────┌───────────────┌────────────────────┌────────┌──────────┌─────────────────
│ x  │    │ Id            │ Guid               │        │    x     │       x        │
├────┌────┌───────────────┌────────────────────┌────────┌──────────┌─────────────────
│    │    │ Name          │ string             │  100   │    x     │                │
├────┌────┌───────────────┌────────────────────┌────────┌──────────┌─────────────────
│    │    │ Description   │ string             │  500   │    x     │                │
├────┌────┌───────────────┌────────────────────┌────────┌──────────┌─────────────────
│    │    │ Price         │ decimal            │        │    x     │                │
├────┌────┌───────────────┌────────────────────┌────────┌──────────┌─────────────────
│    │ x  │ CategoryId    │ EntityId           │        │    x     │                │
├────┌────┌───────────────┌────────────────────┌────────┌──────────┌─────────────────
│    │    │ Dimensions    │ ValueObject        │        │          │                │
├────┌────┌───────────────┌────────────────────┌────────┌──────────┌─────────────────
│    │    │ Status        │ Enum               │        │    x     │                │
├────┌────┌───────────────┌────────────────────┌────────┌──────────┌─────────────────
│    │ x  │ Images        │ List<ProductImage> │        │          │                │
└────┮────┮───────────────┮────────────────────┮────────┮──────────┮────────────────┘

3.1 ProductImage 엔티티 생성

읎 엔티티는 Product 애귞늬거튞에 속하며 닀음 구조륌 갖습니닀:

┌────┬────┬───────────────┬────────────────┬────────┬──────────┬────────────────┐
│ PK │ FK │ Property name │ Type           │ Length │ Required │ Auto-increment │
├────┌────┌───────────────┌────────────────┌────────┌──────────┌─────────────────
│ x  │    │ Id            │ Guid           │        │    x     │       x        │
├────┌────┌───────────────┌────────────────┌────────┌──────────┌─────────────────
│    │ x  │ ProductId     │ EntityId       │        │    x     │                │
├────┌────┌───────────────┌────────────────┌────────┌──────────┌─────────────────
│    │    │ UploadDate    │ DateTimeOffset │        │    x     │                │
├────┌────┌───────────────┌────────────────┌────────┌──────────┌─────────────────
│    │    │ Image         │ File           │        │    x     │                │
└────┮────┮───────────────┮────────────────┮────────┮──────────┮────────────────┘

4. 닀륞 서비슀용 엔티티 생성

Sales 서비슀에서는 ProductSnapshot 엔티티륌 생성하며, 읎 엔티티는 통합 읎벀튞륌 통핎 데읎터륌 채웁니닀. 원래 Product 엔티티의 Id는 Catalog 서비슀에서 였므로, 여Ʞ서는 자동 슝가될 수 없습니닀.

┌────┬────┬───────────────┬─────────┬────────┬──────────┬────────────────┐
│ PK │ FK │ Property name │ Type    │ Length │ Required │ Auto-increment │
├────┌────┌───────────────┌─────────┌────────┌──────────┌─────────────────
│ x  │    │ Id            │ Guid    │        │    x     │                │
├────┌────┌───────────────┌─────────┌────────┌──────────┌─────────────────
│    │    │ Name          │ string  │  100   │    x     │                │
├────┌────┌───────────────┌─────────┌────────┌──────────┌─────────────────
│    │    │ Price         │ decimal │        │    x     │                │
└────┮────┮───────────────┮─────────┮────────┮──────────┮────────────────┘

ì°žê³ : Sales 서비슀의 ProductSnapshot에는 필수 필드만 복제되었습니닀. Customer, Order, StockItem와 같은 추가 엔티티는 묞서륌 닚순화하Ʞ 위핎 여Ʞ서 자섞히 닀룚지 않습니닀.

읎벀튞 및 핎당 핞듀러 생성

읎전 섹션을 복습하멎, 몚듈형 서비슀 Catalog.Merchandising에서 Product, Category, ProductImage 엔티티륌 생성했고, 서비슀 Sales에서는 ProductSnapshot 엔티티륌 생성했습니닀.

읎제 도메읞 읎벀튞와 통합 읎벀튞륌 생성할 찚례입니닀. 목표는 Catalog 서비슀에서 제품을 생성하거나 업데읎튞할 때, 읎러한 변겜 사항읎 Sales 및 Stock 같은 소비 서비슀로 복제되도록 하는 것입니닀.

1. 도메읞 읎벀튞 생성

첫 번짞 닚계는 닀음 명령얎륌 사용하여 도메읞 읎벀튞 ProductCreated 및 ProductUpdated륌 생성하는 것입니닀:

lino event new

생성 곌정에서 읎벀튞륌 핞듀러에 연결하고 동시에 통합 읎벀튞 튞늬거륌 섀정할 수 있습니닀. 읎륌 통핎 전첎 필요한 흐멄 생성읎 쀑앙화됩니닀.

┌──────────────────────────────────────────────────────┬────────────────────────────────┐
│ Question                                             │ Answer                         │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Select a service:                                    │ Catalog                        │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Select a module:                                     │ Merchandising                  │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Select a entity:                                     │ Product                        │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Select the event type:                               │ Domain Event                   │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Enter the name of the event:                         │ ProductCreated                 │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Do you want to create an associated event handler?   │ Yes                            │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Trigger a integration event?                         │ Yes                            │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Choose the integration event to be triggered:        │ (Create new integration event) │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Enter the name of the event:                         │ ProductCreated                 │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Which model will be used for this integration event? │ Creation model                 │
└──────────────────────────────────────────────────────┮────────────────────────────────┘

동음하게 ProductUpdated 읎벀튞도 생성합니닀:

┌──────────────────────────────────────────────────────┬────────────────────────────────┐
│ Question                                             │ Answer                         │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Select a service:                                    │ Catalog                        │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Select a module:                                     │ Merchandising                  │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Select a entity:                                     │ Product                        │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Select the event type:                               │ Domain Event                   │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Enter the name of the event:                         │ ProductUpdated                 │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Do you want to create an associated event handler?   │ Yes                            │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Trigger a integration event?                         │ Yes                            │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Choose the integration event to be triggered:        │ (Create new integration event) │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Enter the name of the event:                         │ ProductUpdated                 │
├──────────────────────────────────────────────────────┌─────────────────────────────────
│ Which model will be used for this integration event? │ Update model                   │
└──────────────────────────────────────────────────────┮────────────────────────────────┘

따띌서 닀음곌 같읎 됩니닀:

  • 생성된 도메읞 읎벀튞 (ProductCreated 및 ProductUpdated);
  • 핎당 도메읞 읎벀튞 핞듀러;
  • 도메읞 읎벀튞 핞듀러에 의핎 Outbox에 자동 등록된 통합 읎벀튞.

2. 통합 읎벀튞 핞듀러 생성

닀음 닚계는 ì–Žë–€ 서비슀가 통합 읎벀튞륌 소비할지 정의하는 것입니닀. 읎륌 위핎 닀음 명령얎륌 사용합니닀:

lino event-handler new

생성 곌정에는 닀음읎 포핚됩니닀:

  • 핞듀러가 포핚될 서비슀, 몚듈, 엔티티 선택;
  • 소비할 통합 읎벀튞와 핎당 읎벀튞가 ì–Žë–€ 서비슀/몚듈/엔티티에서 왔는지 선택.

예륌 듀얎, Sales 서비슀에서는 ProductCreated와 ProductUpdated 읎벀튞 핞듀러륌 생성하여 Catalog.Merchandising.Product에서 발생한 읎벀튞륌 소비합니닀:

┌────────────────────────────────────────────┬───────────────────┐
│ Question                                   │ Answer            │
├────────────────────────────────────────────┌────────────────────
│ Select a service:                          │ Sales             │
├────────────────────────────────────────────┌────────────────────
│ Select a entity:                           │ ProductSnapshot   │
├────────────────────────────────────────────┌────────────────────
│ Select the event type:                     │ Integration Event │
├────────────────────────────────────────────┌────────────────────
│ Select the event's service to be consumed: │ Catalog           │
├────────────────────────────────────────────┌────────────────────
│ Select the event's module to be consumed:  │ Merchandising     │
├────────────────────────────────────────────┌────────────────────
│ Select the event's entity to be consumed:  │ Product           │
├────────────────────────────────────────────┌────────────────────
│ Choose the event to be consumed:           │ ProductCreated    │
├────────────────────────────────────────────┌────────────────────
│ Enter the name of the event handler:       │ ProductCreated    │
└────────────────────────────────────────────┮───────────────────┘
┌────────────────────────────────────────────┬───────────────────┐
│ Question                                   │ Answer            │
├────────────────────────────────────────────┌────────────────────
│ Select a service:                          │ Sales             │
├────────────────────────────────────────────┌────────────────────
│ Select a entity:                           │ ProductSnapshot   │
├────────────────────────────────────────────┌────────────────────
│ Select the event type:                     │ Integration Event │
├────────────────────────────────────────────┌────────────────────
│ Select the event's service to be consumed: │ Catalog           │
├────────────────────────────────────────────┌────────────────────
│ Select the event's module to be consumed:  │ Merchandising     │
├────────────────────────────────────────────┌────────────────────
│ Select the event's entity to be consumed:  │ Product           │
├────────────────────────────────────────────┌────────────────────
│ Choose the event to be consumed:           │ ProductUpdated    │
├────────────────────────────────────────────┌────────────────────
│ Enter the name of the event handler:       │ ProductUpdated    │
└────────────────────────────────────────────┮───────────────────┘

읎렇게 하멎 Sales 서비슀에 두 개의 통합 읎벀튞 핞듀러가 생Ʞ며, Catalog.Merchandising에서 였는 통합 읎벀튞의 필요한 필드만 소비합니닀. 읎륌 통핎 복제된 테읎랔에는 핵심 데읎터만 낚아 저장 공간곌 성능을 최적화할 수 있습니닀.

웹 페읎지, API, Commands 및 Queries 생성

Lino CLI의 큰 장점 쀑 하나는 웹 페읎지, API, Commands 및 Queries륌 자동윌로 통합 생성할 수 있얎 전첎 개발 흐늄을 닚순화할 수 있닀는 점입니닀. 시작하렀멎 닀음 명령을 싀행하섞요:

lino page new

곌정 쀑에 닀음을 수행하게 됩니닀:

  • 녞출할 서비슀, 몚듈 및 엔티티 선택;
  • 목록에 포핚될 필드 선택;
  • 목록 페읎지(페읎지넀읎션 귞늬드) 및 생성/펞집 폌 자동 생성;
  • 프론튞엔드에서 사용할 HttpClient 큎래슀 생성;
  • 필요한 몚든 REST API 생성(POST, PUT, PATCH, DELETE, GET);
  • Commands 및 Queries와 핎당 Handlers 생성, 데읎터베읎슀와 연동하여 CRUD 전첎 흐멄 볎장.

읎 명령을 사용하멎 읞터페읎슀, API 및 비슈니슀 로직을 수동윌로 작성하지 않고도 Ʞ능적읞 애플늬쌀읎션을 얻을 수 있윌며, 서비슀 간 표쀀곌 음ꎀ성을 유지할 수 있습니닀.

읎 프로젝튞에서는 닀음 엔티티에 대한 통합 페읎지륌 생성할 수 있습니닀:

  • Catalog.Merchandising.Category
  • Catalog.Merchandising.Product
  • Sales.ProductSnapshot

페읎지, API 및 Commands/Queries륌 생성한 후, 애플늬쌀읎션은 프론튞엔드와 백엔드 간 완전한 상혞 작용읎 가능하며, 몚든 검슝, 띌우튞 및 데읎터 저장읎 Lino CLI에 의핎 자동윌로 섀정됩니닀.

데읎터베읎슀 마읎귞레읎션 생성

읎제 몚든 엔티티가 생성되었윌므로, 정의된 몚덞에 따띌 데읎터베읎슀륌 생성하거나 업데읎튞하Ʞ 위핎 마읎귞레읎션을 생성할 시간입니닀. Lino CLI는 읎 곌정을 자동화하며, Entity Framework와 통합되얎 싀행 가능한 슀크늜튞륌 생성합니닀.

새 마읎귞레읎션을 생성하렀멎 닀음 명령을 싀행하섞요:

lino database migrations new

싀행 쀑에 닀음을 수행핎알 합니닀:

  • 마읎귞레읎션을 받을 서비슀와 몚듈 선택;
  • 마읎귞레읎션에 대한 섀명 입력, 예: "Initial migration".

┌───────────────────────────────────────────┬───────────────────┐
│ Question                                  │ Answer            │
├───────────────────────────────────────────┌────────────────────
│ Select a service:                         │ Catalog           │
├───────────────────────────────────────────┌────────────────────
│ Select a module:                          │ Merchandising     │
├───────────────────────────────────────────┌────────────────────
│ Current version of the service:           │ 0.1.0             │
├───────────────────────────────────────────┌────────────────────
│ Provide a description for this migration: │ Initial migration │
└───────────────────────────────────────────┮───────────────────┘

확읞하멎 Lino CLI가 닀음을 생성합니닀:

  • 서비슀 현재 버전의 새 데읎터베읎슀 마읎귞레읎션;
  • 핎당 SQL 슀크늜튞, Infrastructure.Persistence 레읎얎에 위치, 겜로: /scripts/<version>/<파음명>;
  • 서비슀 Ʞ록에 마읎귞레읎션 버전 등록, 추적 가능성곌 음ꎀ성 볎장.

몚범 사례:

  • 데읎터 몚덞 변겜 시마닀 새 마읎귞레읎션 생성 (새 엔티티, 속성 또는 ꎀ계 변겜 포핚);
  • 프로덕션에 적용하Ʞ 전에 생성된 SQL 슀크늜튞 검토;
  • 데읎터베읎슀 버전 ꎀ늬륌 애플늬쌀읎션 버전곌 동Ʞ화하여 충돌 및 동Ʞ화 묞제 방지.

읎 곌정을 따륎멎 데읎터베읎슀가 항상 Lino CLI에서 정의된 도메읞 몚덞곌 음치하도록 유지되얎 였류륌 쀄읎고 유지 ꎀ늬륌 닚순화할 수 있습니닀.

Docker 읎믞지 생성

특정 버전의 윔드 생성을 완료하고 테슀튞륌 수행하며 필요한 몚든 비슈니슀 규칙을 구현한 후, 프로젝튞의 서비슀와 웹 애플늬쌀읎션에 대한 Docker 읎믞지륌 생성하여 컚테읎너 레지슀튞늬에 게시할 수 있습니닀.

Lino CLI는 닀음 명령윌로 읎 곌정을 간소화합니닀:

lino build

싀행하멎 프로젝튞에서 사용 가능한 몚든 서비슀와 웹 애플늬쌀읎션 목록곌 현재 버전을 확읞할 수 있습니닀:

Select the services or web applications you want to include in the build:

> [ ] Services
    [ ] Catalog |0.1.0|
    [ ] Sales |0.1.0|
    [ ] Security |0.1.0|
    [ ] Stock |0.1.0|
  [ ] Web applications
    [ ] Backoffice |0.1.0|

하나 읎상의 서비슀와 웹 애플늬쌀읎션을 선택하여 동시에 읎믞지륌 생성할 수 있습니닀. 원하는 항목을 첎크하섞요.

닀음윌로 생성된 읎믞지의 버전을 얎떻게 업데읎튞할지 선택핎알 합니닀. 사용 가능한 옵션은 닀음곌 같습니닀:

  • 현재 버전 유지 – Ʞ졎 버전을 변겜하지 않음;
  • Patch – 팚치 버전 슝가 (예: 0.1.0 → 0.1.1);
  • Minor – 마읎너 버전 슝가 (예: 0.1.0 → 0.2.0);
  • Major – 메읎저 버전 슝가 (예: 0.1.0 → 1.0.0).

서비슀 선택곌 버전 슝가 방법을 지정하멎, Lino CLI는 닀음을 수행합니닀:

  • 각 서비슀와 웹 애플늬쌀읎션 윔드 빌드;
  • 핎당 Docker 읎믞지 생성;
  • 지정된 버전윌로 태귞 적용;
  • 컚테읎너 레지슀튞늬에 게시할 수 있도록 읎믞지 제공.

곌정읎 끝나멎, 몚든 서비슀와 웹 애플늬쌀읎션읎 선택된 겜우, 생성된 읎믞지는 닀음곌 같은 구조륌 갖습니닀:

  • my-app/services/catalog-host - tag: 0.1.0
  • my-app/services/sales-api - tag: 0.1.0
  • my-app/services/security-api - tag: 0.1.0
  • my-app/services/stock-api - tag: 0.1.0
  • my-app/webapps/backoffice - tag: 0.1.0

ì°žê³ : 읎 곌정은 윔드와 Docker 읎믞지 버전 간의 음ꎀ성을 볎장하여 여러 환겜의 배포와 유지 ꎀ늬륌 용읎하게 하며, 각 서비슀가 독늜적읞 컚테읎너에서 격늬되얎 싀행될 수 있도록 합니닀.

애플늬쌀읎션에서 버전 생성

서비슀 또는 웹 애플늬쌀읎션의 새 버전을 슝가시킀는 것은 Lino CLI에서 간닚하고 쀑앙 집쀑화된 곌정입니닀. 닀음 명령을 싀행하멎 됩니닀:

lino version bump

Docker 읎믞지 생성곌 마찬가지로 읎 명령을 싀행하멎 프로젝튞의 몚든 서비슀와 웹 애플늬쌀읎션읎 전첎 목록윌로 표시됩니닀. 선택한 항목만 버전읎 슝가하며, 나뚞지는 변겜되지 않습니닀.

Select the services or web applications that will have version changes:

> [ ] Services
    [ ] Catalog |0.1.0|
    [ ] Sales |0.1.0|
    [ ] Security |0.1.0|
    [ ] Stock |0.1.0|
  [ ] Web applications
    [ ] Backoffice |0.1.0|

원하는 항목을 선택한 후, 버전 슝가 유형을 선택하띌는 요청읎 표시됩니닀. 사용 가능한 옵션은 닀음곌 같습니닀:

  • Patch – Ʞ능에 영향을 죌지 않는 작은 수정;
  • Minor – 읎전 버전곌 혾환되는 새로욎 Ʞ능 추가;
  • Major – 읎전 버전곌의 혞환성을 깚뜚늎 수 있는 변겜.

서비슀와 웹 애플늬쌀읎션의 버전은 닀음에 직접적읞 영향을 믞칩니닀:

  • Docker 읎믞지 태귞;
  • 데읎터베읎슀 마읎귞레읎션윌로 생성된 슀크늜튞륌 저장하는 폮더;
  • 늎늬슈 ꎀ늬 및 프로젝튞 히슀토늬.

읎륌 통핎 Lino CLI륌 사용하여 웹 프로젝튞륌 구축하는 데 필요한 몚든 핵심 명령에 대한 닚계별 가읎드륌 마칩니닀. 섀치, 서비슀, 엔티티, 읎벀튞 및 페읎지 생성부터 Docker 읎믞지 생성 및 버전 ꎀ늬까지 포핚됩니닀.

YouTube 채널을 구독하여, 상섞한 튜토늬얌, 싀습 데몚 및 도구 사용 팁을 확읞하섞요. Ʞ볞 작업부터 고꞉ Ʞ능까지 몚두 닀룹니닀.

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