가상 태그
개요
가상 태그는 센서나 PLC 에서 읽어 오는 태그가 아닙니다. 다른 태그 여러 개의 값을 계산해 만드는 새 태그입니다. 두 압력의 차(차압), 라인 전력의 합, 센서 여러 개의 평균처럼 현장에는 «측정은 안 하지만 보고 싶은 값» 이 많습니다. 가상 태그로 만들어 두면 그 값이 일반 태그처럼 저장되고, 화면에 그려지고, 알람을 걸 수 있습니다.
가상 태그 하나는 두 가지로 이루어집니다.
| 무엇 | 어디서 | 하는 일 |
|---|---|---|
| 태그 자체 | 연결 수정 화면 → 연결된 태그 목록 → [가상 태그] | 태그 ID · 이름 · 데이터 타입을 등록합니다 |
| 계산식 | 태그 설정 양식 → 계산 탭 | 원본 태그를 읽어 값을 만드는 EQL 문장입니다 |
계산식이 없으면 가상 태그에는 값이 생기지 않습니다(손으로 넣는 가상 포인트만 예외입니다).
어디에 쓰나
| 용도 | 예 | 계산식의 핵심 |
|---|---|---|
| 두 태그의 차 | 차압 = 입구 압력 − 출구 압력, 편차 = 설정값 − 실측값 | to_double(a.value) - to_double(b.value) |
| 합 | 라인 전력 합 = 설비 전력의 합 | to_double(a.value) + to_double(b.value) + to_double(c.value) |
| 평균 | 센서 여러 개의 평균 온도 | (to_double(a.value) + to_double(b.value)) / 2 |
| 최대 · 최소 | 여러 센서 중 가장 높은 온도 | CASE WHEN to_double(a.value) >= to_double(b.value) THEN a.value ELSE b.value END |
| 비율 | 원료 투입량 대비 생산량 | to_double(a.value) / to_double(b.value) |
| 한 태그의 시간 평균 | 최근 10초 평균 | AVG(TO_DOUBLE(value)) 와 시간 창 — 계산 탭 도움말의 예 |
여러 태그 중 큰 값을 고르는 전용 함수(greatest 같은)는 EQL 함수 목록에 없습니다.
최대 · 최소는 위처럼 CASE 로 씁니다.
어떻게 동작하나
계산 탭에 넣은 EQL 은 저장하는 순간 CEP 에 문장으로 배포됩니다. 원본 태그에 새 값이 들어오면 문장이 결과 한 행을 내고, 그 행이 가상 태그의 값(포인트) 이 되어 수집된 값과 같은 파이프라인으로 들어갑니다. 그래서 가상 태그의 값은 일반 태그와 똑같이 저장되고, 스트림 · 트렌드 화면과 API 로 읽히고, 알람과 다른 계산식이 다시 읽을 수 있습니다.
| 항목 | 가상 태그에서는 |
|---|---|
| 저장 | 일반 태그와 같은 경로로 저장됩니다. 트렌드 · 스트림 · API 에서 같은 방법으로 봅니다 |
| 데이터 타입 | 등록할 때 고른 데이터 타입을 따릅니다 |
| 단위 | 등록 대화상자에는 칸이 없어 비어 있습니다. 태그 설정 양식의 태그 속성 탭에서 넣습니다 |
| 갱신 시점 | 원본에 새 값이 들어올 때입니다. 일정 주기로 도는 계산이 아닙니다 |
| 갱신 빈도 | 문장이 정합니다. OUTPUT LAST EVERY 1 SEC 를 붙이면 1초에 많아야 한 번 나옵니다 |
| 품질(quality) | 원본의 품질이 자동으로 넘어오지 않습니다. 문장이 quality 칸에 쓴 값이 그대로 들어갑니다(예에서는 192 = GOOD) |
| 원본이 끊기면 | 새 값이 생기지 않습니다. «0» 으로 채워지지 않습니다 — 마지막 값 이후로 비어 있습니다 |
| 결과 값이 비면 | 그 결과는 버려지고 포인트가 만들어지지 않습니다 |
| 알람 | 일반 태그와 똑같이 알람밴드 · EQL 알람의 대상이 됩니다 |
a.quality · b.quality 는 정수 칸이라 문장에서 그대로 읽을 수 있습니다. 원본 품질에 따라
quality 를 다르게 쓰려면 그 식을 문장에 직접 넣어야 합니다 — 플랫폼이 대신 계산해 주지 않습니다.
만들기
1. 가상 태그를 등록한다
가상 태그는 연결 하나에 속합니다. 그래서 등록 버튼이 연결 화면에 있습니다.
- 연결 관리에서 가상 태그를 둘 연결을 열어 수정 화면으로 들어갑니다. 원본 태그가 들어오는 연결에 두는 것이 자연스럽습니다.
- 폼 아래 연결된 태그 목록 패널 헤더의 [가상 태그] 버튼(툴팁 «가상 태그 추가»)을 누릅니다.

| 번호 | 자리 | 하는 일 |
|---|---|---|
| ① | 패널 머리 | 연결된 태그 목록 — «현재 연결에 등록된 태그». 저장된 연결의 수정 화면에서만 채워집니다 |
| ② | 패널 머리 오른쪽 | [가상 태그] — 아래의 가상 태그 추가 대화상자를 엽니다 |
| ③ | 본문 | 이 연결에 속한 태그 목록 — 태그 ID · 태그명 · 데이터 타입 · 단위 · 설명 |
- 가상 태그 추가 대화상자에 아래를 넣고 저장합니다.

| 번호 | 칸 | 규칙 |
|---|---|---|
| ① | 안내 | «가상 태그를 등록합니다. 태그 ID는 반드시 TAG_ 로 시작해야 합니다. 데이터 타입을 선택하면 가상 포인트 입력 시 해당 형식으로 검증됩니다.» |
| ② | 태그 ID | 필수. TAG_ 로 시작하고 대문자 · 숫자 · _ 만, 5~30자. 가상 태그는 관례로 TAG_V_ 로 짓습니다 — ID 규칙 |
| ③ | 태그 명 | 필수. 자리표시자는 «설명 가능한 명칭» |
| ④ | 데이터 타입 | String · Short · Integer · Long · Float · Double · Boolean · Date. 기본값은 String |
| ⑤ | 설명 | 필수. 자리표시자는 «이 태그의 용도를 적으십시오» — 비우면 저장되지 않습니다 |
| ⑥ | 오른쪽 아래 | [저장] |
String 이다대화상자는 String 이 선택된 채로 열립니다. 숫자를 계산하는 가상 태그라면 Double 로
바꾸세요. 알람밴드는 숫자형과 불린 태그에만 걸 수 있어서, String 으로 두면 나중에
밴드 알람을 걸 수 없습니다.
연결된 태그 목록은 이미 저장된 연결의 수정 화면에서만 채워집니다 (연결 관리). 가상 태그는 그 연결의 ID 를 함께 저장하므로, 아직 저장하지 않은 연결에서는 등록이 거부됩니다.
연결을 삭제하면 그 연결에 속한 태그가 가상 태그까지 함께 지워지고, 거기 걸린 알람 설정과 계산식도 해제됩니다. 원본 태그와 다른 연결에 가상 태그를 두었다면 이 점을 기억해 두세요.
2. 계산식을 넣는다
- 태그 화면에서 방금 만든 태그의 설정 양식을 엽니다.
- 계산 탭의 EQL 칸에 문장을 넣습니다.
- 같은 탭 배포 영역의 적용 여부를 활성으로 바꿉니다.
- 그 탭의 저장을 누릅니다 — 탭마다 따로 저장됩니다(태그 등록/수정 양식).

| 번호 | 자리 | 하는 일 |
|---|---|---|
| ① | EQL 계산 도움말 | «EQL 을 통해 태그에 계산된 데이터 포인트를 자동으로 생성합니다.» 와 예시 문장 |
| ② | EQL | 계산식 편집기. 저장이 거부되면 원인이 이 칸 바로 아래 상자에 나옵니다 — 아래 |
| ③ | 배포 → 적용 여부 | 활성이어야 배포됩니다 |
| ④ | 오른쪽 아래 | [저장] — 이 탭만 저장합니다 |
계산식 문장은 아래 규칙을 지켜야 합니다.
| 규칙 | 이유 |
|---|---|
결과에 timestamp · value · quality · error_code 네 칸을 냅니다 | 넷 중 하나라도 없거나 value 가 비면 그 결과는 버려집니다 |
원본 값은 to_double(…) 로 바꿔서 계산합니다 | 태그 값(value)은 문자열로 흐릅니다. 바로 더하거나 빼면 안 됩니다 |
원본 태그마다 Point(tag_id = '…').win:length(1) 에 별칭(a, b …)을 붙여 나열합니다 | 태그마다 최신 값 하나씩을 짝지어 계산합니다 |
식 한 줄이 아니라 SELECT 문 전체를 씁니다 | 저장할 때 CEP 가 문장을 컴파일해 봅니다 |
저장이 거부되면
저장할 때 문장을 컴파일해 보고, 틀리면 저장하지 않습니다(HTTP 422). 원인은 화면에 그대로 나옵니다.
② EQL 칸 바로 아래에 빨간 안내 상자 «EQL 을 읽을 수 없습니다» 가 나옵니다. 이 거부는 토스트로 따로 뜨지 않습니다.
| 상자 안 | 무엇이 |
|---|---|
| 위치 칩 | «N줄 M칸». 커서가 그 자리로 옮겨 가고, 칩을 누르면 다시 갑니다. 편집기 안 그 자리에도 표시가 생깁니다 |
| 본문 | 컴파일러의 문장(원인)과 고치는 힌트 |
| 엔진 원문 보기 | 접혀 있는 엔진의 원래 문장 |
컴파일러가 위치를 말하지 않으면 칩 없이 문장만 나옵니다. 문장을 고치면 표시가 지워집니다.
CEP 가 떠 있지 않아 검사할 수 없을 때도 저장하지 않습니다 — 검사하지 않은 문장은 저장되지 않습니다. 이때는 문장의 잘못이 아니므로 편집기에는 아무것도 표시되지 않고 토스트에 «CEP 엔진에 연결할 수 없어 EQL 을 검증하지 못했습니다.» 가 뜹니다(HTTP 503). CEP 가 뜬 뒤 다시 저장하세요. 스테이트먼트 · 알람 설정 · 쿼리 실행처럼 EQL 을 저장하거나 검사하는 다른 곳도 같은 모양(원인 문장과 줄 · 칸)으로 거부합니다(가상 태그 운영).
문법 전반은 EQL 과 CEP — EQL 언어에 있습니다.
3. 값이 나오는지 본다
스트림 화면에서 가상 태그를 골라 값이 흐르는지 확인합니다. 원본 태그에 값이 들어오고 있어야 가상 태그에도 값이 생깁니다.
계산식 없이 값을 넣으려면 — 가상 포인트
스트림 화면의 [가상 포인트] 버튼은 태그 하나에 시각과 값을 손으로 넣는 대화상자를
엽니다. 시간은 ISO 8601 형식(2024-01-15T17:10:15.123Z)으로 넣습니다. 계산식이 아직 없을
때 화면이나 알람을 시험해 보는 용도로 씁니다.
예 — 필터 차압
필터 앞뒤 압력 태그 둘로 차압을 만드는 예입니다. 아래 태그 ID 는 설명을 위한 예시입니다.
| 태그 | ID (예) | 비고 |
|---|---|---|
| 필터 입구 압력 | TAG_PT_FILTER_IN | 원본 |
| 필터 출구 압력 | TAG_PT_FILTER_OUT | 원본 |
| 필터 차압 | TAG_V_FILTER_DP | 가상 태그 · 데이터 타입 Double · 단위 bar |
계산 탭의 EQL:
SELECT current_timestamp() AS timestamp,
to_double(a.value) - to_double(b.value) AS value,
192 AS quality,
0 AS error_code
FROM Point(tag_id = 'TAG_PT_FILTER_IN').win:length(1) a,
Point(tag_id = 'TAG_PT_FILTER_OUT').win:length(1) b
OUTPUT LAST EVERY 1 SEC
| 부분 | 뜻 |
|---|---|
win:length(1) a, win:length(1) b | 입구 · 출구 각각의 최신 값 하나를 짝짓습니다 |
to_double(a.value) - to_double(b.value) | 차압 = 입구 − 출구 |
192 AS quality | 결과의 품질을 GOOD 으로 선언합니다(원본 품질은 넘어오지 않습니다) |
OUTPUT LAST EVERY 1 SEC | 둘 중 어느 쪽에 값이 와도 다시 계산하되, 1초에 한 번만 내보냅니다 |
같은 모양으로 - 를 + 로 바꾸면 합, / 로 바꾸면 비율이 됩니다. 원본이 셋 이상이면
c, d … 를 같은 방식으로 이어 붙입니다.
알람은 «설정 하나 = 태그 하나»
알람 설정은 밴드 알람이든 EQL 알람이든 태그 하나에 걸립니다.
| 알람 | 어떻게 태그 하나에 걸리나 |
|---|---|
| 밴드 알람 | 태그 설정 양식의 알람밴드 탭 — 그 태그 자신의 값에 임계치를 겁니다. 태그당 하나입니다 |
| EQL 알람 | 알람 설정 양식의 대상 태그가 필수입니다 — 알람은 그 태그의 알람으로 기록됩니다 |
여러 태그를 조합한 조건으로 알람을 걸려면, 먼저 그 조합을 가상 태그로 만들고 알람은 가상 태그에 겁니다. 「입구 − 출구 > 0.5」를 EQL 알람 안에서 두 태그를 읽어 계산하지 말고, 차압 가상 태그를 만들어 그 태그에 「> 0.5」를 거는 식입니다. 그러면 조합한 값 자체가 저장되어 트렌드로 볼 수 있고, 알람이 어느 값 때문에 울렸는지가 그 태그 하나에 남습니다.
EQL 알람의 문장이 대상 태그가 아닌 태그를 읽거나, 여러 태그를 섞거나, 태그 조건이 없으면 저장이 거부됩니다(오류 코드 alarm.eql.one_tag, HTTP 422).
양식의 [EQL 실행] 도 저장과 같은 규칙으로 검사하므로 그 자리에서 거부합니다.
위치가 없는 규칙 위반이라 EQL 편집기 아래 주황 상자에 이렇게 나옵니다.
EQL 알람은 태그 하나 - 알람의 태그만 읽습니다. 태그 여럿, 태그 조건 없음, 다른 태그와의 조인은 거절됩니다. 태그마다 알람을 하나씩 두거나, 태그 비교(차압·편차)는 가상 태그로 계산한 뒤 그 태그에 알람을 거세요.
이미 저장돼 있던 알람이 다른 태그의 행을 내더라도, 판정할 때 대상 태그가 아닌 행은 무시되고 진단 diagnostic.tag.alarm_foreign_tag_rows 가 남습니다. 그런 알람은 가상 태그로 옮겨 두세요.
예 — 차압 0.5 bar 초과가 5분 지속
위의 TAG_V_FILTER_DP 에 EQL 알람을 겁니다.
고급 알람 화면에서
알람 설정 추가 → 대상 태그는 TAG_V_FILTER_DP, 컨디션 (EQL) 의 EQL 은 아래와 같습니다.
SELECT timestamp, tag_id, tag_name, value, quality, error_code,
CASE WHEN to_double(value) > 0.5 THEN 'HIGH' ELSE 'NORMAL' END AS band
FROM Point(tag_id = 'TAG_V_FILTER_DP').win:length(1)
| 부분 | 뜻 |
|---|---|
CASE … END AS band | 값마다 band 칸을 냅니다. 'HIGH' 가 나오면 알람이 켜지고 'NORMAL' 이 나오면 꺼집니다 — band 칸과 'NORMAL' 이 없으면 저장이 거부됩니다 |
Point(tag_id = 'TAG_V_FILTER_DP') | 대상 태그 하나만 읽습니다. 두 압력을 조합하는 일은 가상 태그가 이미 했습니다 |
5분 지속은 문장이 아니라 양식의 감지 설정 (ISA-18.2) → 켜짐 지연 에 300000(ms)을 넣어
겁니다 — 화면 도움말 «조건이 이 시간(ms) 동안 이어져야 알람이 울립니다. 0 이면 끄고, 최대 3,600,000 ms(1시간)입니다.»
- 알림(푸시)이 거듭 가는 것은 알람 설정 양식의 중복 알람 억제 → 억제 시간 (분) 으로 줄입니다.
- 저장하기 전에 양식의 [EQL 실행] 으로 검사하세요. 저장과 같은 규칙(태그 하나 ·
band칸 · 컴파일)으로 봅니다 — 알람 설정 양식. - 지속 조건 없이 넘는 즉시 알리면 되는 경우는 EQL 알람이 필요 없습니다 — 차압 태그의 알람밴드 탭에 임계치를 넣으면 됩니다.
한계와 주의
| 항목 | 내용 |
|---|---|
| 원본 태그 수 | 제품에 정해진 상한은 없습니다. 다만 원본마다 창 하나가 붙으므로 win:length(1) 처럼 창을 작게 둡니다 — 시간 창을 크게 잡으면 짝지을 조합이 폭발합니다 |
| 가상 태그의 가상 태그 | 됩니다. 계산 결과가 일반 태그 값처럼 다시 들어오므로 다른 계산식이 원본으로 읽을 수 있습니다 |
| 자기 자신을 읽는 계산 | 저장할 때 검사하지 않습니다. 자기 자신이나 순환(A 가 B 를, B 가 A 를 읽는)을 만들지 마세요 |
| 계산식 길이 | V5 API 로 넣을 때 4,000자까지입니다 |
| CEP 백엔드 | 위 예는 기본 백엔드(Aster CEP) 기준입니다. 다른 백엔드로 띄운 설치는 CEP — 백엔드의 표를 확인하세요 |
| 원본 품질 | 자동으로 전파되지 않습니다 — 어떻게 동작하나 |
API 와 MCP
| 경로 | 가상 태그에서는 |
|---|---|
| V5 API — 등록 | POST /api/v5/tag — 일반 태그 등록과 같습니다. opc_id 가 필수이고 tag_id 는 TAG_V_… 로 짓습니다 |
| V5 API — 계산식 | PATCH /api/v5/tag/{tag_id}/calculation — calculation_eql 과 use_calculation(true/false). 저장한 뒤 계산식을 다시 배포합니다 |
| V5 API — 읽기 | GET /api/v5/tag/{tag_id}/config 가 calculation_eql · use_calculation 을 돌려줍니다 |
| MCP | 가상 태그 전용 도구는 없습니다. MCP 도구는 태그 ID 로 값을 읽으므로 가상 태그도 list_latest_tag_values · get_tag_history 로 일반 태그처럼 읽습니다. 계산식을 만들거나 바꾸는 MCP 도구는 없습니다 |
SDK 메서드는 태그 서비스에 있습니다.