다른 앱의 데이터 사용
모든 IronFlock 앱은 프라이빗하고 격리된 데이터 백엔드를 갖습니다: 자체 테이블, 자체 라이브 스트림, 자체 렐름. 이 격리가 앱을 안전하게 설치할 수 있게 하는 핵심입니다 — 하지만 격리만으로는 모든 앱이 사일로가 되어 버립니다. 수집기 앱이 기계에서 모은 데이터의 가치는 그 앱 하나를 훨씬 넘어섭니다: 대시보드, 분석, 머신러닝 모델, 리포트의 원재료이기 때문입니다.
크로스 앱 데이터 액세스는 설치된 앱을 빌딩 블록으로 바꿉니다. 앱은 같은 프로젝트에 있는 다른 앱의 데이터 — 라이브 이벤트 스트림과 기록된 이력 — 를 읽고 싶다고 선언할 수 있습니다. 프로젝트를 소유한 사용자가 앱별로, 언제든 전환할 수 있는 스위치로 허용 여부를 결정합니다. 나머지는 플랫폼이 강제합니다: 액세스는 엄격히 읽기 전용이며, 제공 앱이 실제로 공유하는 테이블로 범위가 제한되고, 프로젝트 경계를 절대 넘지 않습니다.
무엇이 가능해지는가
- 수집기 위의 기성 분석. 기계에 데이터 수집기를 설치한 다음, 수집기의 측정값을 사용하는 OEE 대시보드 앱을 설치하세요 — 통합 프로젝트도, 데이터 내보내기도, 글루 코드도 필요 없습니다.
- 배관 작업 없는 머신러닝. 예지보전 앱은 다른 앱이 이미 수집한 수개월치 진동·온도 이력으로 학습하고, 스트리밍되어 들어오는 라이브 측정값을 실시간으로 스코어링할 수 있습니다.
- 모놀리스 대신 전문화된 앱. 수집, 변환, 시각화, 리포팅을 각각 한 가지 일을 잘하는 별도의 앱으로 나누고, 레고 블록처럼 프로젝트별로 조합하세요.
- 사일로가 아닌 에코시스템. 다른 앱의 데이터로 무엇을 하는지가 곧 가치인 앱을 게시하세요. App Store 목록 페이지는 앱이 어떤 데이터를 공유하고 어떤 데이터를 요청하는지 사용자에게 보여줍니다.
작동 방식
세 당사자가 관여하며, 각자 자신의 것을 계속 통제합니다:
- 제공 앱(“앱 B”)은 모든 앱과 마찬가지로 자신의
data-template.yml에 테이블과 변환을 정의합니다. 기본적으로 모든 것이 공유 가능하며, 개별 테이블은private로 표시할 수 있습니다. - 소비 앱(“앱 A”)은 자신의
data-template.yml에 어떤 앱에서 읽고 싶은지, 그리고 그 이유를 선언합니다. - 사용자는 두 앱을 프로젝트에 설치하고 액세스를 승인합니다 — 설치 시점에, 또는 나중에 프로젝트 앱 설정의 앱별 스위치로. 승인이 없으면 액세스도 없습니다: 선언만으로는 아무것도 부여되지 않습니다.
데이터는 프로젝트를 절대 벗어나지 않습니다. 제공 앱의 개발자는 여전히 사용자의 데이터에 접근할 수 없습니다 — 이 권한 부여는 프로젝트 소유자의 통제 아래 한 프로젝트 안에 설치된 앱들 사이에서 이루어집니다.
하나의 표준화된 프로젝트 데이터베이스, 여러 개의 격리된 백엔드
내부적으로 모든 IronFlock 프로젝트는 동일한 표준화된 시계열 데이터베이스를 프로비저닝합니다. 그 안에서 설치된 각 앱은 프라이빗하고 분리된 백엔드 공간을 소유합니다: 앱의 테이블은 자체 데이터베이스 스키마에 존재하며, 사용자가 읽기 액세스를 부여하지 않는 한 다른 어떤 앱에서도 보이지 않습니다. 프로젝트당 하나의 데이터베이스라는 이 설계가 전체 모델을 작동하게 만듭니다:
- 프로젝트 간 재현 가능. 앱의 데이터 백엔드는 설치되는 모든 프로젝트에서 동일하게 프로비저닝됩니다 — 같은 테이블, 같은 타입, 같은 쿼리 동작. 프로젝트가 관리형 클라우드에서 실행되든 온프레미스 어플라이언스에서 실행되든 마찬가지입니다. 한 번 만들어 두면 어디서나 동일하게 동작합니다.
- 중앙 수집·점검 지점. 프로젝트 소유자는 모든 앱의 데이터를 한 곳에서 봅니다 — 앱별로 흩어진 저장소가 아니라, 점검하고 쿼리하고 소유할 수 있는 하나의 데이터베이스입니다.
- 기본은 격리, 공유는 권한 부여로. 스키마 격리가 각 앱의 공간을 프라이빗하게 유지합니다. 크로스 앱 권한 부여는 다른 앱의 스키마로 향하는 읽기 전용 창을 엽니다 — 같은 데이터베이스 안에서 이루어지므로 아무것도 복사되거나 내보내지거나 동기화되지 않습니다. 데이터의 집은 하나이며, 바뀌는 것은 액세스뿐입니다.
의존성 선언
소비 앱은 읽으려는 앱을 자신의 .ironflock/data-template.yml에 표명합니다:
consumes:
- app: machine-monitor
reason: "모니터의 기계 상태 및 카운터 스트림에서 OEE를 계산합니다"
data:
tables:
- tablename: oee_results
columns:
# ... your app's own tables, as usualapp 필드는 제공 앱의 기술적 앱 이름입니다(해당 앱의 App Store 페이지에 표시됩니다). reason은 동의 대화 상자에서 사용자에게 표시됩니다 — 당신의 앱을 신뢰할지 결정하는 사람을 위해 작성하세요.
데이터 읽기
런타임에 SDK가 제공 앱의 데이터 백엔드에 연결하며, 자신의 테이블에 이미 사용하는 것과 동일한 읽기 API를 제공합니다:
Python
from ironflock import IronFlock
flock = IronFlock()
# Connect to the providing app's data backend (requires the user's grant)
monitor = await flock.connect_to_app("machine-monitor")
# Discover what it shares
print(monitor.tables) # shared tables with their columns
print(monitor.transforms) # shared transforms (views)
# Query history
rows = await monitor.get_history("machinestate", {"limit": 1000})
# Down-sampled series for charts and models
series = await monitor.get_series_history("measurements", {
"metrics": ["temperature"],
"method": "AVG",
"timeRange": ["2026-07-01T00:00:00Z", "2026-07-04T00:00:00Z"],
})
# Subscribe to live rows as they are collected
async def on_row(row):
print("live reading:", row)
await monitor.subscribe_to_table("measurements", on_row)사용자가 액세스를 부여하지 않았거나 나중에 철회한 경우, connectToApp은 명확한 타입의 오류와 함께 실패합니다 — 앱은 이 데이터 소스를 선택 사항으로 취급하고 우아하게 축소된 상태로 동작해야 합니다.
프로젝트의 모든 데이터 사용 (와일드카드)
일부 앱은 범용 데이터 워크벤치입니다 — Node-RED 런타임, 노트북, 리포팅 도구 — 이들의 전체 가치는 사용자가 프로젝트에 있는 무엇이든 그 데이터로 작업할 수 있게 하는 데 있습니다. 이런 앱은 제공 앱을 미리 지목할 수 없습니다. 사용자가 어떤 수집기나 분석 앱을 설치할지 알 수 없기 때문입니다. 이런 앱을 위해서는 와일드카드를 선언하세요: 프로젝트에 있는 모든 앱의 데이터에 대한 읽기 액세스입니다.
consumes:
- app: "*" # the quotes are REQUIRED — a bare * is a YAML alias
reason: "이 프로젝트에 있는 모든 앱의 라이브 및 이력 데이터 위에 플로우를 구축할 수 있습니다""*" 와일드카드는 프로젝트의 모든 앱에 대한 읽기 액세스를 부여합니다 — 사용자가 나중에 설치하는 앱까지 포함하며, 재동의가 필요 없습니다. 모델의 나머지는 모두 그대로입니다: 여전히 읽기 전용이고, 프라이빗 테이블과 변환은 여전히 절대 공유되지 않으며, 플랫폼 앱은 범위 밖입니다. 사용자는 (앱별 목록 대신) 하나의 전부-아니면-전무 스위치로 와일드카드를 승인하며, 언제든 철회할 수 있습니다.
와일드카드 소비 앱은 제공 앱의 이름을 미리 알지 못하므로, 런타임에 이를 검색합니다:
Python
from ironflock import IronFlock
flock = IronFlock()
# Discover every app whose data you may read (name + shared-table catalog)
providers = await flock.list_consumable_apps()
for p in providers:
print(p["app"], p["stages"]) # e.g. "energy-monitor", {"prod": {"tables": [...]}}
# Open one by name (works because you hold the wildcard grant)
energy = await flock.connect_to_app("energy-monitor")
rows = await energy.get_history("meterdata", {"limit": 1000})
# ...or open them all at once
all_apps = await flock.connect_to_all_apps()
for app in all_apps:
await app.subscribe_to_table(app.tables[0]["tablename"], on_row)listConsumableApps()는 기본 요소입니다 — 한 번의 호출로, 연결은 전혀 열지 않고, 각 제공 앱의 비공개가 아닌 카탈로그를 반환하므로 선택기를 렌더링할 수 있습니다. connectToAllApps()는 이들을 모두 여는 편리한 일괄 방식입니다. 새로 설치된 앱은 다음 listConsumableApps() 호출에서 자동으로 나타납니다. 사용자가 와일드카드를 부여하지 않았다면, 둘 다 타입이 지정된 NO_GRANT 오류로 실패합니다.
구조적으로 읽기 전용
이 권한 부여는 관례가 아니라 플랫폼의 메시징 계층이 강제합니다. 소비 앱이 할 수 있는 것과 할 수 없는 것:
| 가능 | 불가능 |
|---|---|
| 제공 앱의 라이브 데이터 스트림 구독 | 제공 앱 데이터의 쓰기, 수정, 삭제 |
| 제공 앱의 기록된 이력 쿼리 | 제공 앱의 커스텀 프로시저나 명령 호출 |
| 공유된 변환(뷰) 읽기 | private로 표시된 테이블이나 변환 조회 |
| 공유 테이블 카탈로그 검색 | 다른 프로젝트에 있는 앱의 데이터 접근 |
앱 데이터 공유하기 — 일부는 남겨 두면서
가치 있는 데이터를 수집하는 앱을 만든다면, 그 데이터를 공유하는 것이 당신의 앱을 다른 이들이 그 위에 구축하는 기반으로 만듭니다. 모든 것을 공유할 필요는 없습니다: 내부용 테이블이나 변환을 private로 표시하면 공유 카탈로그에서 완전히 사라집니다 — 목록에 나타나지 않고, 쿼리할 수 없으며, 스트리밍되지 않습니다.
data:
tables:
- tablename: measurements # shared (default)
columns: [ ... ]
- tablename: calibration_state # internal — never visible to other apps
private: true
columns: [ ... ]
transforms:
- tablename: hourly_aggregates # shared views work like shared tables
sql: "SELECT ..."사용자가 계속 통제합니다
- 설치 시점에 사용자는 새 앱이 어떤 설치된 앱에서 읽으려 하는지, 그리고 그 이유를 정확히 확인하고, 그중 어느 것이든 거부할 수 있습니다. 거부해도 설치가 차단되지 않습니다. 앱이 단지 그 데이터를 받지 못할 뿐입니다.
- 부여된 모든 액세스는 프로젝트 앱 설정의 스위치로 나타나며, 언제든 철회할 수 있습니다(또는 제공 앱을 설치한 후 등 나중에 부여할 수도 있습니다).
- 권한 부여는 프로젝트 단위입니다. 같은 앱 쌍을 다른 프로젝트에 설치하면 처음부터 다시 시작합니다.
전형적인 구성
이 모델을 구체화하는 패턴 — 수집, 분석, 시각화를 별도의 조합 가능한 앱으로 나누는 것 — 은 공장 데이터 추출에서 엔드투엔드로 설명합니다: 프로토콜 수집기가 기계 데이터를 추출하고, OEE 대시보드, 예지보전 모델, 에너지 분석이 이를 소비하며, 각각 독립적으로 설치되고 독립적으로 권한이 부여됩니다.