본문으로 건너뛰기

디지털 스레드 — 시스템을 건너도 끊기지 않는 «같은 이름»

디지털 스레드는 데이터를 한곳에 모으는 일이 아닙니다. 흩어진 시스템들이 같은 대상을 같은 이름으로 부르고, 그 대상들 사이의 관계와 시간을 따라갈 수 있게 만드는 일입니다. 모으기만 하면 데이터 늪이 되고, 이름이 이어지면 흩어져 있어도 스레드가 됩니다.

이 글은 스레드를 식별 · 관계 · 시간 세 가닥으로 나눠, 각각이 어디서 끊기고 어떻게 잇는지를 기술적으로 정리합니다. 예시는 PlantPulse 플랫폼의 실제 구현에서 가져왔지만, 논지는 어느 공장의 어느 스택에도 해당합니다.

대상 독자

MES · ERP · 히스토리안 · CMMS 를 잇는 일을 맡은 엔지니어, 공장 데이터 모델을 설계하는 사람, 그리고 「데이터는 다 있는데 왜 답이 안 나오나」를 겪어 본 분. 함께 읽으면 좋은 글은 제조 AI — 공장 데이터가 모델에게 요구하는 것 입니다.

1. 무엇이고, 무엇이 아닌가​

제품 하나가 설계되고, 공정이 정해지고, 작업지시로 만들어지고, 검사를 받고, 설비가 고장 나 정비를 받습니다. 각 단계는 다른 시스템이 기록합니다. 디지털 스레드는 그 기록들을 거꾸로 따라갈 수 있는 실입니다.

「이 로트의 불량률이 왜 올랐나」라는 질문을 스레드로 풀면 이렇게 됩니다.

불량 로트 ─(어느 작업지시?)─▶ 워크오더 ─(어느 설비, 언제?)─▶ 설비 · 시간 구간
─(그때 그 설비의 신호는?)─▶ 태그 시계열 ─(상류는?)─▶ 공급 설비 · 유틸리티
─(그 설비의 정비 이력 · 절차서는?)─▶ 문서

각 화살표가 시스템 경계를 넘는 한 번의 조인입니다. 하나라도 끊기면 질문은 거기서 멈추고, 사람이 엑셀을 여러 개 열어 눈으로 맞추기 시작합니다.

자주 섞이는 말차이
디지털 트윈트윈은 한 대상의 상태 모델이다(이 펌프는 지금 어떤가). 스레드는 대상들 사이와 시간을 잇는 참조다(이 펌프는 무엇을 먹이고, 어떤 작업지시에 쓰였고, 그때 무엇이 있었나). 트윈이 여럿 있어도 스레드가 없으면 서로 모르는 섬이다
데이터 레이크레이크는 저장이다. 모든 데이터를 한곳에 부어도 ID 가 서로 다르면 조인할 수 없다
통합 플랫폼한 제품이 모든 기능을 하는 것과, 여러 시스템이 같은 이름을 쓰는 것은 다르다. 스레드는 뒤쪽이다

2. 어디서 끊기나​

현장에서 스레드가 끊기는 형태는 대부분 넷 중 하나입니다.

끊기는 형태예
이름이 다르다같은 펌프를 SCADA 는 P-101A, CMMS 는 PUMP_101_A, ERP 는 자산번호 400123 으로 부른다
관계가 없다계층(어느 라인에 속하나)은 있는데, 흐름(무엇을 먹이나)과 의존(어느 유틸리티에 기대나)이 어디에도 적혀 있지 않다
시간이 어긋난다설비 시계 · 서버 시계 · 기록한 시각이 다르고, 회선이 끊겼다 이어지면 지각 데이터가 한꺼번에 몰려온다
사본이 갈라진다설비 마스터를 시스템마다 복사해 두었더니, 한쪽에서 설비를 옮기고 다른 쪽은 모른다

넷째가 가장 교묘합니다. 복사본은 처음에는 똑같아서 문제가 안 보이고, 갈라진 뒤에는 어느 쪽이 맞는지 판정할 근거가 없습니다.

3. 첫째 가닥 — 식별: 정본은 하나, 나머지는 파생​

원칙은 하나입니다 — 마스터 데이터의 정본(SSOT)을 한 곳에 두고, 다른 모든 표현은 거기서 파생한다. 파생물은 언제든 다시 만들 수 있으므로 갈라져도 판정이 됩니다 — 정본이 이깁니다.

PlantPulse 에서는 PostgreSQL 메타스토어가 그 정본입니다. 엔터프라이즈 · 사이트 · 자산 트리 · 태그 · 알람 설정 · 명령 정의가 여기 있고, 아래에서 볼 그래프 · 토픽 경로 · AI 가 보는 구조는 전부 이것을 읽어 만든 파생물입니다.

외부 ID 는 «매핑 열» 로 받는다​

다른 시스템의 ID 를 내 ID 로 바꿔 쓰면 안 됩니다. 두 시스템이 서로 다른 규칙으로 ID 를 만들기 때문입니다. 대신 내 ID 는 내 규칙대로 두고, 상대의 ID 를 따로 적어 두는 열을 둡니다.

엔티티내 ID상대 시스템 ID
고객customer_id — 영문 · 숫자 · _ 만external_customer_id (MES · ERP)
제품제품 ID외부 제품 ID

이렇게 하면 ERP 가 코드 체계를 바꿔도 내 쪽 조인은 하나도 깨지지 않고, 매핑 열만 고치면 됩니다.

사람의 말도 ID 로 바꾼다​

「3라인 압축기」는 ID 가 아닙니다. 사람이 쓰는 이름을 정본의 ID 로 해소하는 단계가 따로 있어야 합니다. PlantPulse AI 가 질문을 받으면 가장 먼저 하는 일이 이것입니다(search_domains) — 이 단계가 틀리면 뒤의 분석이 아무리 정확해도 엉뚱한 설비의 정확한 답이 나옵니다.

4. 둘째 가닥 — 관계: 계층만으로는 부족하다​

계층은 «어디에 있나» 에 답한다​

ISA-95 계층은 스레드의 뼈대입니다.

Enterprise ─ Site ─ Area ─ Line ─ Equipment ─ Tag ─ 값

이 나무가 있으면 「3라인의 설비 전부」, 「사이트 단위 OEE 롤업」 같은 질문이 풀립니다. PlantPulse 의 KPI 롤업이 라인 · 구역 · 사이트 · 엔터프라이즈 단위로 묶이는 것도 이 나무를 따라서입니다.

그리고 메시징 주소도 이 나무에서 나옵니다. UNS(Unified Namespace) MQTT 토픽은 계층 경로를 그대로 씁니다.

pp/{site_id}/{area_id}/{line_id}/{equipment_id}/{tag_id}/point

토픽 이름만 보고도 값이 어디서 왔는지 압니다. 구독하는 쪽이 따로 조회하지 않아도 문맥이 붙어 옵니다 — 스레드가 메시지 안에 들어가 있는 셈입니다.

계층이 주소가 되면, 계층을 옮기는 것이 곧 주소 변경이다

태그를 다른 설비로 옮기면 그 태그의 MQTT 토픽이 바뀝니다. 옛 토픽을 구독하던 외부 시스템은 에러 없이 조용히 값을 못 받게 됩니다. 계층을 고치기 전에 그 경로를 구독하는 쪽이 있는지 봐야 하고, 이 때문에 계층은 처음에 신중하게, 나중엔 드물게 고칩니다. PlantPulse 는 토픽 경로를 UNS 화면에서 미리 보고 복사할 수 있게 해 둡니다.

방향이 있는 관계는 «무엇에 영향을 주나» 에 답한다​

「이 설비가 멈추면 어디까지 서나」는 계층으로 풀리지 않습니다. 같은 라인에 있다고 서로 먹이는 것은 아니고, 다른 구역의 공기압축기가 라인 전체를 세울 수도 있습니다. 그래서 계층과 별도로 방향이 있는 관계를 둡니다.

관계뜻따라가면
FEEDS상류가 하류로 흐른다하류로: 정지 영향 범위 · 상류로: 품질 이상의 원인 후보
DEPENDS_ON전력 · 에어 · 냉각 같은 유틸리티에 기댄다유틸리티 하나가 서면 어느 설비들이 같이 서나
PRODUCES무엇을 생산한다설비에서 제품으로

제품 쪽에서도 같은 사슬을 겁니다. 제품 경로(제품이 거치는 단위 공정의 순서) → 단위 공정(공정의 정의와 소속 설비) → 연결도(설비끼리의 흐름과 의존). 공정 화면의 「이 공정을 쓰는 제품」이 읽기 전용인 것은, 그것이 제품 경로에서 유도한 값이기 때문입니다 — 두 곳에서 따로 적게 하면 사본이 갈라집니다(2절의 넷째).

그래프는 파생물이다​

관계를 따라가는 질문에는 그래프가 편합니다. 그렇다고 그래프 DB 를 두 번째 정본으로 세우면 3절의 원칙이 깨집니다 — 이제 설비 마스터가 두 곳에 있고, 동기화 파이프라인이 스레드의 가장 약한 고리가 됩니다.

PlantPulse 는 반대로 했습니다.

  • 그래프는 플랫폼 안의 인메모리 RDF 모델(Apache Jena)이고, 메타스토어를 읽어 통째로 다시 만듭니다. 동기화 저장소가 없습니다
  • 다시 만드는 시점은 조회가 들어왔을 때 TTL(기본 10분)이 지났으면입니다(semantic.graph.refresh.minutes). 동시에 여럿이 조회해도 다시 만드는 것은 하나뿐이고, 나머지는 직전 모델을 받습니다
  • 대가는 명확합니다 — 방금 등록한 설비는 다음 갱신까지 그래프에 없을 수 있습니다. 그 대신 그래프가 정본과 갈라진 채 굳는 일은 구조적으로 일어나지 않습니다
파생물의 신선도는 «틀림» 이 아니라 «늦음» 이다

동기화 방식의 사본이 틀리면 언제까지 틀린지 모릅니다. 주기적으로 다시 만드는 파생물은 틀려도 최대 한 주기입니다. 스레드 설계에서 이 차이가 큽니다 — 늦음은 기다리면 풀리지만, 갈라짐은 사람이 찾아내야 풀립니다.

5. 셋째 가닥 — 시간: 조인 키로서의 작업지시​

식별과 관계는 무엇과 어디를 잇습니다. 그런데 공장의 질문은 거의 항상 언제를 포함합니다 — 「그 로트를 만들 때」, 「고장 전 2주」.

워크오더가 시간 축의 조인 키다​

작업지시(워크오더)는 스레드에서 특별한 자리에 있습니다. 한 건이 설비 · 제품 · 고객 · 담당자를 동시에 가리키고, 여기에 계획 시작 · 종료 시각과 목표 수량이 붙습니다. 즉 워크오더 하나가 곧

「이 설비의, 이 시간 구간의 시계열은 이 제품 · 이 고객의 것이다」

라는 조인 조건입니다. 워크오더 단위 OEE 가 계산되는 것도, 설비 화면에서 「이 설비의 워크오더만」으로 좁혀 들어가는 것도 이 조인 덕입니다. 반대로 워크오더 없이 시계열만 있으면, 값은 넘치는데 그 값이 무엇을 만들 때의 값인지를 모릅니다.

저장된 상태와 유도된 상태를 가른다​

시간이 들어가면 상태에 두 종류가 생깁니다.

예어디에 있나
저장된 상태대기 · 진행중 · 일시중지 · 완료 · 비정상종료데이터베이스
유도된 상태지연(시작 예정이 지났는데 시작 안 함) · 취소(시작 없이 종료 예정이 지남)화면이 지금 시각으로 계산 — 데이터에 없다

유도된 상태를 저장하지 않는 데는 이유가 있습니다. 「지연」을 저장하면 누가 언제 그것을 풀어 줄지가 새 문제가 되고, 그 갱신이 한 번 밀리면 데이터가 거짓말을 합니다. 대가는 API 나 DB 에서 DELAY 를 찾아도 없다는 것 — 스레드를 따라 외부 시스템으로 상태를 넘길 때는 유도 규칙까지 함께 넘겨야 합니다.

발생 시각과 도착 시각은 다르다​

엣지는 회선이 끊기면 값을 자기 안에 쌓았다가 복구 뒤 한꺼번에 올립니다. 값이 비지 않는 대신, 몇 시간 전의 값이 지금 도착합니다. 스레드에서 시간으로 조인할 때는 항상 발생 시각(event time) 을 씁니다. 도착 시각으로 조인하면 복구 직후의 워크오더에 엉뚱한 값이 붙고, 끊겼던 시간의 워크오더는 빈 채로 남습니다.

6. 값은 그래프에 넣지 않는다 — 포인터를 넣는다​

스레드를 그래프로 표현하다 보면 시계열 값까지 그래프에 넣고 싶어집니다. 넣지 않습니다. 시계열은 끝없이 쌓이고 「한 태그의 한 기간」으로만 읽히는 데이터라, 그것에 맞게 만든 저장소(시계열 DB)에 있어야 합니다.

대신 그래프의 태그 노드는 자기 값이 어디 있고 어떻게 읽는지를 가리킵니다.

속성뜻예
seriesKey시계열 조회 키태그 ID
seriesStore어느 저장소의 어느 테이블시계열 저장소 식별자
seriesTool무슨 도구로 읽나get_tag_history
lastValue · lastTimestamp최신 값 스냅샷조회 없이 «지금» 을 볼 수 있게

seriesTool 이 흥미로운 자리입니다. 그래프가 데이터가 아니라 «읽는 법» 까지 들고 있으므로, 그래프를 따라온 쪽(사람이든 AI 에이전트든)이 다음에 부를 도구를 그래프에서 바로 얻습니다. 설비의 타임라인도 같은 방식(timelineKey · timelineStore)으로 가리킵니다.

이것이 스레드의 일반 원칙이기도 합니다 — 스레드는 데이터를 옮기지 않고, 데이터로 가는 길을 잇는다.

7. 표준은 «경계» 에서 쓴다​

UNS · Sparkplug B · OPC-UA · AAS(Asset Administration Shell) 같은 표준은 스레드를 시스템 밖으로 내보낼 때의 말입니다.

표준무엇을 표준화하나PlantPulse 에서
UNS (MQTT)계층 경로를 토픽 주소로계층에서 토픽을 생성 · 미리보기
Sparkplug BMQTT 페이로드와 상태(birth · death)엣지에서 켜서 쓴다(기본 꺼짐)
OPC-UA설비 정보 모델과 접근드라이버 · 표준 UI(:12780)
AAS V3자산의 «디지털 명판» — 서브모델로 기술 정보를 묶는다표준 UI(:8091)

표준을 내부 모델로 쓰려 하면 대개 손해를 봅니다. 표준은 여러 회사가 합의한 최대공약수라 내 공장의 관계(무엇이 무엇을 먹이나)를 다 담지 못하고, 표준이 개정될 때마다 내부가 흔들립니다. 안에서는 내 정본으로, 밖으로는 표준으로 — 경계에서 번역하는 편이 스레드를 덜 끊습니다.

8. AI 는 스레드 위에서만 정확하다​

언어모델에게 「3라인 압축기 요즘 어때?」를 물으면, 모델이 하는 일은 결국 스레드를 따라가는 것입니다.

① 「3라인 압축기」 → 설비 ID 식별
② 이 설비의 상류 · 하류 · 의존 관계 (그래프)
③ 태그 노드의 seriesTool 로 이력 조회 시간 (포인터)
④ 해당 기간의 워크오더 · 알람 · 문서 시간 + 식별

스레드가 끊겨 있으면 모델은 끊긴 자리를 그럴듯한 말로 메웁니다. 이름이 해소되지 않으면 비슷한 설비를 고르고, 관계가 없으면 같은 라인에 있다는 이유로 영향을 추측합니다. 그래서 제조 AI 의 정확도는 모델 크기보다 스레드의 완결성에 먼저 묶입니다. 그래프 조회 도구가 깊이 제한에 걸리면 truncated 를 표시하고, 셀 수 없는 합계는 total_tag_count_unknown 으로 «모름» 을 알리는 것도 같은 이유입니다 — 끊긴 자리를 끊겼다고 말해야 모델이 메우지 않습니다. 도구 목록은 온톨로지에 있습니다.

설계 체크리스트​

스레드를 세우거나 점검할 때, 스택과 무관하게 물어볼 것들입니다.

질문좋은 답의 모양
설비 마스터의 정본은 어디인가한 곳. 나머지는 거기서 파생되고, 다시 만들 수 있다
외부 시스템의 ID 는 어떻게 받나내 ID 를 바꾸지 않고 매핑 열로 받는다
사람의 말을 ID 로 바꾸는 단계가 있나있다. 그리고 그것이 분석보다 먼저 온다
계층 말고 방향이 있는 관계가 있나흐름(FEEDS) · 의존(DEPENDS_ON)을 따로 적는다
그래프는 정본인가 파생물인가파생물. 동기화 저장소 없이 다시 만든다. 신선도의 상한을 안다
시계열 값이 그래프에 복사되나복사하지 않는다. 포인터와 읽는 법만 둔다
시간 조인에 무엇을 쓰나발생 시각. 워크오더의 시작 · 종료가 조인 조건이 된다
유도된 상태를 저장하나저장하지 않는다. 외부로 넘길 때는 유도 규칙을 함께 넘긴다
계층을 바꾸면 무엇이 깨지나토픽 주소가 바뀐다는 것을 알고, 구독자를 먼저 확인한다
표준은 어디서 쓰나경계에서. 안은 내 정본, 밖은 표준

함께 보기​

제조 AI — 공장 데이터가 모델에게 요구하는 것 · 값 하나가 화면까지 가는 길 — 엣지에서 화면까지 · UNS — 계층에서 만들어지는 토픽 · 온톨로지 — 관계를 따라가는 도구 · 데이터베이스 모델 — 정본의 테이블 · 전체 구조