CSV 일괄 업로드 (/ui/connect/csv)
여러 OPC + 태그를 한 번에 등록하는 화면. 엑셀이나 외부 도구에서 정의한 태그 카탈로그를 그대로 import. 50+ 태그 사이트에서 가장 빠른 방법.
홈 → 프로토콜 연결 하기 → 우상단 📥 CSV 일괄 업로드, 또는 직접 /ui/connect/csv.
1. 화면 구성
📥 CSV 일괄 업로드 [← 뒤로] [💾 업로드]
⚠ 주의사항 패널 (빨강)
- CSV 형식 [,로 구분]
- 빈 공백 금지
- 1행 = 헤더 (절대 삭제 금지)
- OPC: 드라이버명/IP/포트 정확히
- TAG: PLC_ADDRESS 정확히 (잘못 입력 시 수집 실패)
- 이미 등록된 TAG_ID → 업데이트 안 함 (중복 무시)
📊 OPC
────────────────
[CodeMirror 에디터 — 150px]
헤더: OPC_ID,OPC_NAME,OPC_TYPE,OPC_AGENT_IP,OPC_AGENT_PORT,TIMECYCLE,ASYNC,AUTO_COLLECT,DESCRIPTION
🏷 TAG
────────────────
[CodeMirror 에디터 — 400px]
헤더: OPC_ID,TAG_ID,TAG_NAME,DATA_TYPE,PLC_ADDRESS,FORMAT,LINKED_ASSET_ID,ALIAS_NAME,DESCRIPTION
2. OPC CSV 컬럼 (9개)
| 순서 | 컬럼 | 의미 | 예 |
|---|---|---|---|
| 1 | OPC_ID | 고유 식별자 (영문/숫자/_) | OPC_LS_LINE1 |
| 2 | OPC_NAME | 사용자 표시명 | 라인1 LS PLC |
| 3 | OPC_TYPE | 게이트웨이 코드 (LS / MELSEC / S7 / MODBUS / OPCUA / EIP / LOGIX / HTTP 등) | LS |
| 4 | OPC_AGENT_IP | PLC 의 IP | 192.168.100.50 |
| 5 | OPC_AGENT_PORT | TCP 포트 | 2004 |
| 6 | TIMECYCLE | 수집 주기(ms) | 1000 |
| 7 | ASYNC | 비동기 read | true / false |
| 8 | AUTO_COLLECT | 부팅 후 자동 수집 시작 | true / false |
| 9 | DESCRIPTION | 자유 메모 | 라인1 메인 PLC |
OPC_TYPE 별 포트 / IP 표는 PLC 종류별 가이드 의 비교표 참조.
3. TAG CSV 컬럼 (9개)
| 순서 | 컬럼 | 의미 | 예 |
|---|---|---|---|
| 1 | OPC_ID | 위 OPC 표의 OPC_ID 와 매칭 | OPC_LS_LINE1 |
| 2 | TAG_ID | 고유 ID (영문/숫자/_) | TAG_LINE1_TEMP |
| 3 | TAG_NAME | 사용자 표시명 | 라인1 온도 |
| 4 | DATA_TYPE | Integer / Long / Float / Double / String / Boolean | Integer |
| 5 | PLC_ADDRESS | 드라이버 별 주소 (예: D00309 LS, DB1.DBW0 S7, holding-register:1 Modbus) | D00309 |
| 6 | FORMAT | 형식 보조 (DW / REAL / STR[10] / BIN[3] 등) | DW |
| 7 | LINKED_ASSET_ID | (선택) 자산 매핑 | ASSET_PUMP_01 |
| 8 | ALIAS_NAME | (선택) 외부 시스템용 별칭 | temp_01 |
| 9 | DESCRIPTION | 자유 메모 | 라인1 메인 펌프 온도(℃) |
PLC_ADDRESS 와 FORMAT 의 정확한 입력은 PLC 주소 입력 (44개 드라이버 완전 가이드) 참고.
4. 작성 예시 (실전)
4.1 OPC 2 개 + TAG 5 개
OPC 영역 (헤더 + 2 행):
OPC_ID,OPC_NAME,OPC_TYPE,OPC_AGENT_IP,OPC_AGENT_PORT,TIMECYCLE,ASYNC,AUTO_COLLECT,DESCRIPTION
OPC_LS_LINE1,라인1 LS PLC,LS,192.168.100.50,2004,1000,false,true,라인1 메인 PLC
OPC_S7_LINE2,라인2 S7 PLC,S7,192.168.100.60,102,1000,false,true,라인2 메인 PLC
TAG 영역 (헤더 + 5 행):
OPC_ID,TAG_ID,TAG_NAME,DATA_TYPE,PLC_ADDRESS,FORMAT,LINKED_ASSET_ID,ALIAS_NAME,DESCRIPTION
OPC_LS_LINE1,TAG_LINE1_TEMP,라인1 온도,Float,D00450,REAL,,,라인1 메인 펌프 온도(℃)
OPC_LS_LINE1,TAG_LINE1_QTY,라인1 누적생산량,Integer,D00600,DW,,,32-bit 누적
OPC_LS_LINE1,TAG_LINE1_RUN,라인1 가동상태,Boolean,M02704,,,,
OPC_S7_LINE2,TAG_LINE2_PRESS,라인2 압력,Float,DB1.DBD0,REAL,,,bar
OPC_S7_LINE2,TAG_LINE2_FAULT,라인2 알람,Boolean,DB1.DBX2.0,,,,
,,, 는 비어있는 컬럼 — LINKED_ASSET_ID, ALIAS_NAME 미사용.
4.2 엑셀에서 만들기
- 엑셀에 위 표를 그대로 붙여넣기 (헤더 1행 + 데이터)
- 다른 이름으로 저장 → CSV UTF-8 (쉼표로 분리) 형식 (default
cp949한글 깨짐 주의) - CSV 파일을 텍스트 에디터로 열어 셀 안의 쉼표가 자동 인용(
"...") 됐는지 확인 - CSV 본문 그대로 OPC 영역 또는 TAG 영역 에 붙여넣기
5. 업로드 흐름
| 단계 | 동작 |
|---|---|
| 1. 💾 업로드 클릭 | POST /connect/csv-upload (body: {opcs, tags} 두 텍스트) |
| 2. 서버 검증 | 헤더 / 컬럼 수 / 타입 / OPC_ID 매칭 검증 |
| 3. DB 등록 | pe.app_opc + pe.app_tag upsert (이미 있는 TAG_ID 는 업데이트 안 함 — skip) |
| 4. 토스트 | "서버를 재시작하시면, 등록하신 OPC 연결 및 태그 생성을 시작합니다." |
업로드 후 — 게이트웨이 캐시 (OPCAndTagsCache) 가 새 OPC/태그를 읽도록 재시작 권장 (bin/restart.sh, ~6초). 자동 시작 (AUTO_COLLECT=true) 으로 등록한 OPC 는 재시작 후 즉시 수집 시작.
6. 자주 빠지는 함정
| 증상 | 원인 / 해결 |
|---|---|
| 업로드 후 0 건 | 헤더 누락 / 컬럼 수 다름 / 인코딩 (UTF-8 BOM) |
| 한글 깨짐 | 엑셀 default cp949 저장. UTF-8 강제 — 이름으로 저장 → CSV UTF-8 |
| 같은 TAG_ID 가 갱신 안 됨 | 정상 동작 — 중복 TAG_ID 는 skip. 변경하려면 일단 태그 등록 화면 또는 REST PUT /api/v1/tag/{tagId} 로 |
| OPC 등록은 됐는데 TAG 가 안 보임 | TAG CSV 의 OPC_ID 가 OPC CSV 의 OPC_ID 와 정확히 일치 안 함. 대소문자 / 공백 |
ASYNC, AUTO_COLLECT 가 false 로 처리됨 | True / TRUE 다 OK 지만, 빈 셀이면 false. 명시적으로 true 입력 |
| PLC_ADDRESS 컬럼이 빈 채로 등록됨 | CSV 의 셀 안 쉼표 가 줄을 갈라놓음. 셀 안에 쉼표 있으면 "..." 로 인용 |
| 한 줄 끝에 빈 칸 (trailing space) → 컬럼 mismatch | 엑셀 → CSV 변환 시 trailing space 가 추가될 수 있음. 텍스트 에디터에서 일괄 trim |
| 업로드는 성공인데 차트에 값 안 들어옴 | OPC AUTO_COLLECT=false 로 등록했는데 재시작 후 시작 안 누름. /ui/connect/list 의 ▶ 시작 |
7. 더 알아보기
- 단건 등록 (대화형): 태그 등록
- 주소 표기: PLC 주소 입력 (44개 드라이버 완전 가이드)
- 등록 후 실시간 모니터링: 연결 목록 / 태그 목록
- 일괄 변경 (REST): REST API 의
PUT /api/v1/tag/{tagId}반복