7.8 KiB
pvC UA EnumValueType 메타데이터 저장 최적화 제안서
작성일: 2026-05-07 상태: 분석 중 목적: xv, p-xxxxx 등 디지털 장비 태그의 pv 값 (i=7594) 저장 방식 최적화
1. 현재 pv 값 저장 방식 분석
1.1 pvC UA EnumValueType (i=7594) 데이터 흐름
디지털 장비(xv 밸브, p-xxxxx 펌프 등)의 pv(Output) 값은 pvC UA 표준 데이터 타입인 EnumValueType (i=7594)를 사용한다. 이 값은 pvC UA 서버에서 읽을 때 {정수 | DisplayName | } 형식의 문자열로 반환된다.
1.2 실제 DB 저장 예시
realtime_table에 pv 값이 저장되는 실제 데이터:
| tagname | livevalue | node_id |
|---|---|---|
| xv-3202.pv | {0 | L-MID | } |
ns=1;s=sinamserver:xv-3202.pv |
| xv-3202_hs.pv | {0 | CLOSE | } |
ns=1;s=sinamserver:xv-3202_hs.pv |
| xv-360.pv | {0 | MID | } |
ns=1;s=sinamserver:xv-360.pv |
| p-10602a.pv | {0 | L-STpv | } |
ns=1;s=sinamserver:p-10602a.pv |
| p-2816a.pv | {0 | L-STpv | } |
ns=1;s=sinamserver:p-2816a.pv |
| p-203_hs.pv | {0 | STpv | } |
ns=1;s=sinamserver:p-203_hs.pv |
1.3 pv 값의 구조
pv 값 {0 \| L-STpv \| }는 다음 3가지 정보를 포함:
- 정수 코드 (0): 실제 상태 코드 (0~7 범위)
- DisplayName (L-STpv): 화면에 표시될 상태 이름
- 빈 설명 영역: 현재 사용되지 않음
1.4 각 태그당 존재하는 속성 수
node_map_master에서 한 태그(예: p-10214)당 426개 속성이 존재한다. 주요 속성:
- 핵심 데이터: pv, pv, sp, md
- 상태 플래그: instate0~instate7
- 상태 설명: state0descriptor~state7descriptor
- 메타데이터: desc, area
- 품질/시간: pvquality, pvlastscannedtime 등
- 설정값: state0ondelay, alarmpriority 등
- 기타: equipprpverties, templateid, guid 등
2. tag_metadata 테이블 분석
2.1 현재 tag_metadata 테이블 스키마
CREATE TABLE tag_metadata (
id SERIAL PRIMARY KEY,
base_tag TEXT NOT NULL,
attribute TEXT NOT NULL,
value TEXT,
node_id TEXT,
loaded_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(base_tag, attribute)
)
2.2 MetadataLoaderService가 로드하는 속성
| 속성 | 데이터 타입 | 설명 |
|---|---|---|
| desc | String | 태그 설명 |
| area | i=7594 | 소속 플랜트/Asset (EnumValueType) |
| state0descriptor | String | 상태 0 설명 |
| state1descriptor | String | 상태 1 설명 |
| state2descriptor | String | 상태 2 설명 |
| state3descriptor | String | 상태 3 설명 |
| state4descriptor | String | 상태 4 설명 |
| state5descriptor | String | 상태 5 설명 |
| state6descriptor | String | 상태 6 설명 |
| state7descriptor | String | 상태 7 설명 |
2.3 현재 tag_metadata 테이블 상태
테이블이 비어 있음 — 메타데이터 로드가 아직 실행되지 않았거나 실패한 상태.
2.4 문제점: pv 값과 state descriptor의 중복
pv 값 {0 | L-STpv | } 자체가 상태 코드 + DisplayName을 포함하고 있다.
즉, state0descriptor 등의 값을 별도로 저장할 필요 없이 pv 값에서 파싱하면 된다.
| 데이터 소스 | 포함 정보 |
|---|---|
realtime_table의 pv livevalue |
{0 | L-STpv | } → 코드=0, 이름=L-STpv |
tag_metadata의 state0descriptor |
"L-STpv" (pv 값과 동일한 정보) |
결론: pv 값에 이미 state descriptor 정보가 포함되어 있으므로 중복 저장.
3. 메타데이터 컬럼 유지 여부 제안
3.1 컬럼 분류
tag_metadata 테이블에서 각 속성을 3가지 카테고리로 분류:
| 카테고리 | 속성 | 필요성 | 이유 |
|---|---|---|---|
| 필수 유지 | desc | ⭐ 필수 | 태그 설명은 pv 값에 포함되지 않음 |
| 필수 유지 | area | ⭐ 필수 | 소속 플랜트 정보는 pv 값에 포함되지 않음 |
| 불필요 | state0~7descriptor | ❌ 중복 | pv 값 {코드 | 이름 | }에 이미 포함 |
3.2 제안: desc, area만 저장
tag_metadata 테이블에는 desc와 area만 저장하고, state0~7descriptor는 저장하지 말 것.
근거
- 정보 중복 제거: pv 값
{0 | L-STpv | }에서 상태 이름 "L-STpv"을 파싱 가능 - 저장소 절감: 태그당 8개 state descriptor 행 제거 (10개 → 2개 속성)
- 로드 시간 단축: pvC UA에서 읽어야 할 속성 10개 → 2개로 감소
- 데이터 일관성: state descriptor는 pvC 서버 설정에 따라 변경될 수 있음. pv 값이 실시간 상태이므로 더 신뢰할 수 있음
pv 값 파싱 방법
pv 값: "{0 | L-STpv | }"
파싱: 코드=0, 상태이름="L-STpv"
pv 값: "{0 | MID | }"
파싱: 코드=0, 상태이름="MID"
프론트엔드에서 pv 값 표시 시 {와 |를 파싱하여 상태 이름만 표시하면 됨.
3.3 수정이 필요한 코드
| 파일 | 수정 내용 |
|---|---|
MetadataLoaderService.cs |
MetaAttributes 배열에서 state0~7descriptor 제거 |
ExperionDbContext.cs |
v_tag_summary 뷰에서 state descriptor JOIN 제거 |
app.js |
pv 값 표시 시 파싱 로직 추가 |
3.4 tag_metadata 테이블의 node_id, loaded_at 컬럼 유지 여부
| 컬럼 | 유지 제안 | 이유 |
|---|---|---|
| node_id | 유지 | pvC UA 노드 ID는 재로드 시 변경될 수 있으므로 추적 필요 |
| loaded_at | 유지 | 메타데이터 갱신 시점 확인에 유용 |
결론: node_id와 loaded_at은 유지하는 것이 좋음.
4. 요약 및 다음 단계
4.1 핵심 발견
- pv 값 저장 방식:
realtime_table의livevalue에{코드 | DisplayName | }형식으로 저장됨 - 정보 중복: pv 값에 state descriptor 정보가 이미 포함되어 있음
- tag_metadata 비어있음: 메타데이터 로드가 아직 실행되지 않은 상태
- 속성 과다: 각 태그당 426개 속성 중 실제로 필요한 것은 desc, area 2개뿐
4.2 최종 제안
| 항목 | 결정 |
|---|---|
| tag_metadata 저장 속성 | desc, area 만 |
| state0~7descriptor | 저장하지 않음 (pv 값에서 파싱) |
| node_id 컬럼 | 유지 (추적용) |
| loaded_at 컬럼 | 유지 (갱신 시점 확인) |
4.3 기대 효과
- pvC UA 읽기 요청 80% 감소: 10개 속성 → 2개 속성
- tag_metadata 행 80% 감소: 태그당 10행 → 2행
- 메타데이터 로드 시간 단축: 네트워크 트래픽과 DB 삽입량 대폭 감소
- 데이터 일관성 향상: pv 값이 실시간 상태이므로 더 신뢰할 수 있음
4.4 다음 단계
MetadataLoaderService.cs수정: state descriptor 제거ExperionDbContext.cs수정: v_tag_summary 뷰 단순화- 프론트엔드 pv 값 파싱 로직 추가
- 메타데이터 로드 테스트 실행
- P-XXXXX, XV-XXXXX.pv 등의 상태변화를 감지하여 EVENT TABLE에 기록하여 LLM의 플랜트 상태보고에 활용하게 하고, NL2SQL에서도 언제부터 언제까지의 이벤트 정보를 표시 할 수있게 하자(UI 'Event 조회' 별도 페이지 만들어서 )
EVENT TABLE은 컬럼 TimeStamp, Tagname, Value, StateText 를 p-xxxxx, xv-xxxxx등의 pv 값{ 값 | 상태 텍스트 | }에서 가져오고 값의 변경이 일어났을때만 , event history 테이블에 기록.
event 테이블을 아날로그값에도 적용할지는 나중에 생각하고 일단 Brain Storming 기록만
- ficq-6113 : pid controller 류 들의 Manual : pv 기준, Auto : sp 기준으로 값이 변경되면 event 히스토리에 변경값 기록 이전값->변경값 두개다 기록
- Auto <-> Manual 전환도 기록 : ficq-6113.md 기준 -> 실시간 테이블 스키마 변경
- user 전환 (근무교대 시프트 기록) ---> 이건 아직 파악 못했슴 (node_map_master 에 정보 없슴)