Overview
이 문서는 source-repo를 처음 보는 팀원이 전체 구조를 빠르게 이해하기 위한 시작점입니다.
source-repo는 하나의 SaMD patient monitoring/risk assessment 예제 제품을 여러 언어와 배포 단위로 나누어 구현합니다. 각 언어는 독립적인 샘플이 아니라, 같은 monitoring/risk workflow를 서로 다른 책임으로 나누어 보여줍니다.
1. 이 Repo가 보여주는 것
이 source repo는 app, reusable package, 문서, CI, container build를 함께 보여줍니다. 목표는 “한 언어에서만 통하는 샘플”이 아니라, 여러 생태계가 섞인 실제 제품 repo에서 공통으로 지켜야 할 경계와 운영 기준을 보여주는 것입니다.
Source repo가 만드는 산출물은 크게 세 종류입니다. 첫째는 reusable package입니다. 여러 app이나 service가 같은 domain rule과 usecase를 재사용할 수 있도록 language-Rust Python package 형태로 배포합니다. 둘째는 deployable app입니다. API server, web app, operator, firmware처럼 실제 실행 단위가 여기에 해당합니다. 셋째는 release evidence입니다. Container image, SBOM/provenance, firmware .elf/.hex/.bin/.map, package version은 어떤 source revision이 어떤 산출물로 나갔는지 추적하는 증거입니다.
- app과 shared package를 하나의 monorepo에서 함께 개발합니다.
- 각 package는 Clean Architecture, DDD, TDD의 최소 골격을 가집니다.
- app은 package를 조립하는 얇은 executable wrapper로 둡니다.
- package test/build/publish와 app container build/push를 CI에서 분리합니다.
- Nexus를 package download/publish 지점으로 사용합니다.
- container image와 firmware artifact를 release evidence로 추적합니다.
이 repo를 읽을 때는 packages/를 먼저 보고, 그 다음 apps/, 마지막으로 .github/workflows/를 보면 흐름이 잘 보입니다. Package가 제품 언어와 business rule을 담고, app은 runtime에 맞게 조립하며, workflow는 이 둘을 검증하고 배포 가능한 형태로 고정합니다.
2. 이 Repo가 하지 않는 것
Kubernetes manifest와 실제 environment promotion은 CD repo 책임입니다. Source repo는 deployable artifact를 만들고, CD repo가 사용할 image tag, package version, runtime contract를 넘깁니다.
이 분리는 작지만 중요합니다. Source repo가 Kubernetes overlay까지 소유하면 application code 변경, package release, cluster policy 변경이 한 PR에 섞이기 쉽습니다. 반대로 CD repo가 deployment manifest를 소유하면 environment별 차이, approval, rollback, promotion history를 한 곳에서 관리할 수 있습니다. Source repo는 “무엇을 만들었는가”를 책임지고, CD repo는 “어디에 어떤 정책으로 배포했는가”를 책임집니다.
Source repo에는 아래를 두지 않습니다.
- Kubernetes Deployment, Service, Ingress, CronJob manifest
- environment별 overlay
- cluster secret
- promotion policy
3. Repository Layout
3-1. Directory Map
source-repo/
├── apps/
│ ├── signal-device-simulator/ synthetic SignalPacket generator
│ ├── patient-risk-web/ React/Vite clinical monitoring web app
│ ├── patient-risk-python-api/ Python API
│ ├── risk-monitor-operator/ Go RiskMonitor operator-style app
│ ├── wearable-firmware/ bare-metal C firmware app
│ └── wearable-zephyr-firmware/ Zephyr RTOS firmware app
├── contracts/ cross-language JSON Schema contracts
├── fixtures/ PHI-free synthetic signal fixtures
├── manifests/ Go operator demo manifests
├── packages/
│ ├── patient-monitor-ui-core/ framework-independent monitoring UI core
│ ├── patient-monitor-react-components/
│ ├── patient-risk-python-core/
│ ├── patient-signal-rust-core/
│ ├── patient-risk-go-core/
│ └── patient-signal-c-core/
├── docs/ MkDocs source documents
├── scripts/ repo-local helper scripts
├── Makefile local/CI-like command entrypoint
├── package.json TypeScript workspace entrypoint
├── pyproject.toml Python workspace/tooling entrypoint
├── Cargo.toml Rust workspace entrypoint
├── go.work Go workspace entrypoint
└── mkdocs.yml documentation site config
3-2. README 위치
사람이 처음 들어오는 경계마다 README를 둡니다. Root README가 모든 세부사항을 대신하지 않습니다. Root README는 큰 그림과 공통 기준을 설명하고, package/app README는 해당 단위의 사용법과 계약을 설명합니다.
| Location | Reader | Should explain |
|---|---|---|
source-repo/README.md |
새 팀원, reviewer, platform engineer | repo 책임, 빠른 시작, 주요 문서 링크 |
cd-repo/README.md |
배포 담당자, reviewer | promotion, environment overlay, rollback 기준 |
apps/*/README.md |
app owner, SRE, CD repo maintainer | runtime contract, health endpoint, required env, container image |
packages/*/README.md |
package consumer, library maintainer | public API, architecture boundary, test, package publish 기준 |
README는 “코드를 읽기 전의 지도”입니다. 특히 polyglot repo에서는 파일 이름만으로는 어떤 도구가 source of truth인지 알기 어렵기 때문에, README가 의사결정 배경을 남겨야 합니다.
4. Contract와 Fixture
언어별 구현이 서로 다른 방향으로 새지 않도록 공통 contract와 fixture를 source repo 안에 둡니다. contracts/hospital-at-home/에는 app/package 사이를 연결하는 JSON Schema가 있고, fixtures/signals/에는 firmware, Rust, Python, TypeScript가 함께 읽을 synthetic signal CSV가 있습니다. apps/signal-device-simulator/는 이 fixture를 실제 SignalPacket payload로 변환하는 첫 demo app입니다.
이 파일들은 문서 부록이 아니라 test input입니다. Contract, fixture, RiskMonitor manifest를 바꾸면 make contract/test가 먼저 통과해야 하고, 이후 각 언어별 test가 같은 fixture를 소비하도록 연결합니다.
make contract/test
make demo/signal
make demo/check
make demo/check는 Rust/PyO3 Python package를 현재 uv environment에 설치한 뒤 patient-risk-python-api를 임시 포트로 실행합니다. signal-device-simulator가 low-spo2-trend fixture를 POST /signal-packets로 전송한 뒤 GET /monitoring-snapshot과 GET /review-queue에 UI가 소비할 상태가 생성되는지 확인합니다. 이어서 patient-monitor-ui-core의 monitoring/review mapper가 live API 응답을 clinical dashboard view model로 바꾸는지, patient-monitor-react-components와 patient-risk-web이 waveform, numeric, risk, alarm state, clinician review queue를 화면 markup으로 렌더하는지도 확인합니다. 마지막으로 alarm acknowledge/mute API를 호출해 임상 workflow action이 snapshot state로 되돌아오는지 검증합니다.
5. 읽는 순서
처음 보는 경우에는 아래 순서가 가장 빠릅니다.
- Product Scenario로 예제 제품 맥락을 봅니다.
- Architecture Overview로 app/package/usecase/adapter 경계를 봅니다.
- Demo Flow로 실제 연결 흐름을 봅니다.
- 관심 언어의 Languages 문서를 봅니다.
- 각 app/package README에서 실행과 package 사용법을 확인합니다.