컴포넌트 구축
컴포넌트는 Hub에 publish되어 host application에 mount되는 reusable Wippy module입니다. component는 host의 entry ID를 알지 못해도 database, process host 또는 router에 의존할 수 있습니다. 이러한 dependency를 requirement interface로 선언하고 host가 값을 제공합니다.
이 guide는 author side, 즉 interface 선언과 value가 entry에 주입되는 방식을 다룹니다. consumer side(lock file, version constraint, wippy add/update)는 의존성 관리, component internal structure는 애플리케이션 아키텍처를 참조하십시오.
세 가지 종류
| 종류 | 측 | 역할 |
|---|---|---|
ns.definition |
컴포넌트 | 모듈 메타데이터; 게시에 필수. |
ns.requirement |
컴포넌트 | 호스트가 채워야 하는 구멍과 값을 주입할 위치. |
ns.dependency |
호스트 | 컴포넌트를 마운트하고 그 요구사항에 값을 공급. |
ns.definition
publish되는 각 module에는 정확히 하나의 definition이 있어야 합니다. definition은 module metadata, README reference, wiki page reference를 담을 수 있습니다.
- name: definition
kind: ns.definition
module: jobs # optional module metadata
readme: file://README.md # path to the module's documentation
meta:
title: Durable Jobs
description: Leased job queue with retry and dead-lettering.
module, readme, wiki는 모두 optional definition data입니다. meta는 management UI용 ordinary entry metadata입니다. release note는 여기서가 아니라 publish 시 제공합니다.
ns.requirement
요구사항은 주입 타겟 목록을 가진 이름 있는 구멍입니다. 호스트가 값을 공급하면, 런타임이 그 값을 각 타겟 엔트리의 지정된 경로에 씁니다.
- name: target_db
kind: ns.requirement
meta:
description: SQL database backing every table in this module.
default: app:db
targets:
- entry: app.jobs.migrations:schema
path: .meta.target_db
- entry: app.jobs.persist:lifecycle
path: .db
default — 필수 vs 선택
default 필드가 호스트가 값을 반드시 공급해야 하는지를 결정합니다:
default가 non-null value로 있음 (빈 문자열 포함) → 요구사항은 선택 사항입니다. host가 아무것도 제공하지 않으면 default를 사용합니다.default가 없음 → 요구사항은 필수입니다. 아무것도 공급되지 않으면 strict 모드에서 링크가 실패합니다 (그 외에는 경고).
default: "")는 absent 또는 null default와 다릅니다. empty string은 "optional, falls back to nothing"을 뜻하고 absent와 default: null은 둘 다 "host가 반드시 제공"해야 함을 뜻합니다. 합리적인 in-app convention(app:db, app:processes)이 있는 infrastructure에는 non-null default를 사용하고 host만 아는 value에는 생략하십시오.
targets — 값이 도착하는 곳
각 타겟은 {entry, path} 쌍입니다:
entry— 값이 주입되는 엔트리. 단독 이름(schema)은 요구사항 자신의 네임스페이스 안에서 해석됩니다; 완전히 한정된 id(app.jobs.migrations:schema)는 네임스페이스를 가로질러 정확히 그 엔트리를 가리킵니다.path— 타겟 엔트리로의 점 경로, 예:.meta.target_db,.host,.database.url. 선행 점은 관례입니다.
requirement는 target을 하나 이상 선언해야 합니다.
경로에 += 접미사를 붙이면 설정 대신 추가합니다 — 여러 요구사항이 하나의 리스트에 기여할 때(예: 미들웨어) 유용합니다:
targets:
- entry: app.api:router
path: .middleware+= # appends the value to the list at .middleware
하나의 요구사항, 여러 타겟
같은 값이 필요한 모든 것을 하나의 요구사항 아래에 묶으세요. 이것이 관용적 패턴입니다: target_db 요구사항이 모든 마이그레이션의 .meta.target_db와 모든 영속성 라이브러리의 .db에 주입하고, process_host가 감독되는 각 service의 .host에 주입하고, api_router가 각 엔드포인트의 .meta.router에 주입합니다:
- name: process_host
kind: ns.requirement
default: app:processes
targets:
- { entry: app.jobs.service:worker.service, path: .host }
- { entry: app.jobs.service:sweeper.service, path: .host }
host는 value 하나를 제공하고 runtime은 이를 모든 declared target에 씁니다. requirement entry가 이 wiring을 직접 포함합니다.
컴포넌트 소비하기
호스트는 ns.dependency로 컴포넌트를 마운트하고 parameters를 통해 그 요구사항을 채웁니다:
version: "1.0"
namespace: app
entries:
- name: dep.jobs
kind: ns.dependency
component: acme/jobs
version: "^1.0.0"
parameters:
- name: target_db
value: app:db
- name: process_host
value: app:processes
- name: api_router
value: app:api
각 parameter.name은 요구사항과 매칭됩니다; 그 value가 해당 요구사항의 타겟에 주입되는 값입니다. 기본값이 있는 요구사항은 생략할 수 있습니다; 필수 요구사항은 반드시 공급해야 합니다.
파라미터 이름 매칭
파라미터 이름이 요구사항에 바인딩되는 방식:
- 단독 이름 (
target_db)은 마운트되는 컴포넌트에 속한 그 이름의 요구사항과 매칭됩니다. 다른 모듈의 요구사항으로 넘어가지 않습니다. - 한정된 이름 (
acme.jobs:target_db)은 그 요구사항 id와 정확히 매칭됩니다. 전이적 의존성을 배선할 때 구분이 필요하면 이를 사용하세요.
두 의존성이 같은 요구사항에 서로 다른 값을 공급하면 충돌이며 보고됩니다 (동일한 값은 괜찮습니다).
값이 해석되는 시점
주입은 빌드 파이프라인의 Link 단계에서 일어납니다 — 게시 시, 의존성 확장 중, 그리고 부트 시 — 런타임이 아닙니다. 이 단계는:
- 모든
ns.requirement와 파라미터를 가진 모든ns.dependency를 수집합니다. - 각 요구사항에 대해 값을 해석합니다: 매칭되는 파라미터가 이깁니다; 없으면 기본값; 없으면(기본값도 없으면) 미해석 상태입니다.
- 해석된 값을 각 타겟 엔트리의 경로에 씁니다 (설정, 또는
+=이면 추가).
strict requirements 아래에서는 미해석된 필수 요구사항이 빌드를 실패시킵니다; 그 외에는 경고를 기록하고 진행합니다. 엔트리가 런타임에 도달할 때쯤에는 채워진 모든 요구사항이 이미 타겟에 구워져 있습니다.
Mount Test로 통합 검증
unit test는 assembled module의 registry relationship을 검증하지 않습니다. requirement-injected registry를 대상으로 packaging 또는 mount test를 추가해 다음을 확인하십시오.
- 감독되는 모든
service가 존재하는 프로세스 엔트리를 가리키는지, - 스폰되거나 스케줄되는 모든 id가 실제 엔트리로 해석되는지,
- 모든
env.variable의 스토리지가 등록되어 있는지.
이 검사는 supervisor가 등록되지 않은 worker를 참조하거나 test fixture가 harness-only storage ID를 사용하는 것과 같은 unresolved relationship을 찾습니다. 슈퍼비전과 테스트를 참조하십시오.
참고
- 애플리케이션 아키텍처 — component internal structure
- 의존성 관리 — lock file, version, consumer workflow
- 모듈 게시 — component를 Hub에 publish
- 엔트리 종류 가이드 —
ns.definition,ns.requirement,ns.dependencyreference