> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/deployment/ko/self-hosted/enterprise/deployment-manager/services/opc-ua-server.md).

# OPC UA 서버

OPC UA (Open Platform Communications Unified Architecture)는 장치, PLC, SCADA 시스템 간에 데이터를 교환하기 위한 산업용 통신 프로토콜입니다. OPC UA Server는 장치에 태그를 게시하여 산업용 클라이언트가 추론 결과를 읽고 값을 다시 쓸 수 있게 하는 엣지 컨테이너 서비스입니다.

Deployment Manager의 Configuration 탭에서 태그, 폴더, 서버 설정을 정의한 다음 OPC UA 클라이언트를 장치에 연결하세요.

{% hint style="info" %}
OPC UA Server는 Enterprise 고객에게만 제공됩니다. [Roboflow 영업팀에 문의하여](https://roboflow.com/sales) 자세한 내용을 알아보세요.
{% endhint %}

## 연결 세부 정보

바꾸세요 `<device-ip>` 를 Deployment Manager의 장치 페이지에 표시된 IP 주소로

<table data-search="false"><thead><tr><th>목적</th><th>주소</th></tr></thead><tbody><tr><td>OPC UA 엔드포인트</td><td><code>opc.tcp://&#x3C;device-ip>:4840/opcua/server</code></td></tr><tr><td>웹 UI 및 REST API</td><td><code>http://&#x3C;device-ip>:8092</code></td></tr></tbody></table>

<table data-search="false"><thead><tr><th>포트</th><th>프로토콜</th><th>목적</th></tr></thead><tbody><tr><td>4840</td><td>OPC UA 바이너리</td><td>산업용 클라이언트 연결(PLC, SCADA)</td></tr><tr><td>8092</td><td>HTTP</td><td>웹 UI, REST API, 문서</td></tr></tbody></table>

## 구성 소스

Configure 모달 상단의 "구성 소스" 토글은 태그 및 폴더 구성이 어디에서 오는지 제어합니다. 장치에서는 한 번에 하나의 소스만 활성화됩니다.

<table data-search="false"><thead><tr><th>소스</th><th>저장 위치</th><th>다음 경우에 사용</th></tr></thead><tbody><tr><td>"웹 UI"</td><td><code>OPCUA_CONFIG</code></td><td>모달에서 태그, 폴더, 서버 설정을 인라인으로 정의하려는 경우 사용합니다. 기본값입니다.</td></tr><tr><td>"파일"</td><td><code>OPCUA_CONFIG_FILE</code></td><td>구성 파일이 너무 커서 수천 개의 태그가 있는 배포처럼 환경 변수에 담을 수 없는 경우입니다. 서버에 장치의 경로를 지정하세요(예: <code>/data/opcua-config.json</code>).</td></tr></tbody></table>

"File" 모드에서는 서버가 시작 시 파일이 존재하고 읽을 수 있으며 비어 있지 않은지 검증하고, 하나라도 사실이 아니면 명시적인 로그 항목과 함께 시작에 실패합니다. `OPCUA_CONFIG_FILE` 보다 우선합니다 `OPCUA_CONFIG`.

소스를 전환해도 모달이 열려 있는 동안에는 인라인 값과 파일 경로가 모두 유지됩니다. 저장하면 선택하지 않은 소스는 지워져 정확히 둘 중 하나의 변수만 설정됩니다. "File" 모드에서는 서비스 카드가 인라인 태그 목록 대신 구성된 파일 경로를 표시합니다.

## 서버 설정

<table data-search="false"><thead><tr><th>설정</th><th>설명</th></tr></thead><tbody><tr><td>"서버 이름"</td><td>네트워크를 탐색하는 클라이언트에 표시되는 서버 인스턴스의 사람이 읽을 수 있는 이름입니다.</td></tr><tr><td>"네임스페이스 URI"</td><td>태그가 등록되는 서버 네임스페이스를 식별하는 고유 URI입니다. 기본값은 <code>http://opcua.roboflow.run</code>.</td></tr><tr><td>"최대 세션 수"</td><td>한 번에 연결될 수 있는 OPC UA 클라이언트 수입니다. 기본값은 <code>200</code>.</td></tr></tbody></table>

각 클라이언트는 하나의 세션을 차지하며, 태그를 쓰는 각 추론 pod와 각 SCADA 연결도 마찬가지입니다. 충돌한 클라이언트의 세션은 서버가 시간 초과 처리할 때만 해제되므로, 바쁜 사이트는 실제 클라이언트 수보다 더 많은 세션을 점유할 수 있습니다. 상한에 도달하면 이후 클라이언트는 BadTooManySessions로 거부되며 `BadTooManySessions` 태그 업데이트가 중지됩니다. 사이트의 동시 클라이언트 수가 기본값보다 많으면 이 값을 올리세요. 모달에서 설정하면 서버 구성에 기록되며, `OPCUA_MAX_SESSIONS` 는 수동으로 관리되는 배포에서 장치별로 이를 재정의할 수 있습니다.

## 폴더와 태그

폴더는 태그를 계층 구조로 정리합니다. 각 폴더에는 이름과 선택적 설명이 있으며, OPC UA 주소 공간에서 노드로 표시되어 클라이언트가 태그를 탐색하고 찾을 수 있습니다. 태그는 폴더에 속하거나 루트 수준에 둘 수 있습니다.

태그는 서버가 노출하는 데이터 포인트를 정의합니다. 각 태그에는 다음 필드가 있습니다:

<table data-search="false"><thead><tr><th>필드</th><th>설명</th></tr></thead><tbody><tr><td>"표시 이름"</td><td>OPC UA 클라이언트에 표시되는 사람이 읽을 수 있는 이름입니다.</td></tr><tr><td>"탐색 이름"</td><td>주소 공간에서 사용되는 프로그래밍용 식별자입니다. 표시 이름에서 생성됩니다.</td></tr><tr><td>"데이터 유형"</td><td>태그가 보유하는 값의 유형입니다.</td></tr><tr><td>"접근 수준"</td><td>태그가 <code>ReadWrite</code> 또는 <code>ReadOnly</code>.</td></tr><tr><td>"폴더"</td><td>태그가 속한 폴더입니다. 지정되지 않은 경우 Root입니다.</td></tr><tr><td>"초기 값"</td><td>서버가 시작될 때의 시작 값입니다. 데이터 유형에 맞게 검증됩니다.</td></tr><tr><td>"설명"</td><td>태그의 용도를 설명하는 선택적 레이블입니다.</td></tr></tbody></table>

### 데이터 유형

<table data-search="false"><thead><tr><th>유형</th><th>설명</th><th>예시</th></tr></thead><tbody><tr><td><code>Boolean</code></td><td>참 또는 거짓</td><td><code>true</code></td></tr><tr><td><code>Int32</code></td><td>32비트 부호 있는 정수</td><td><code>42</code></td></tr><tr><td><code>Float</code></td><td>32비트 부동소수점</td><td><code>3.14</code></td></tr><tr><td><code>Double</code></td><td>64비트 부동소수점</td><td><code>3.14159265359</code></td></tr><tr><td><code>String</code></td><td>UTF-8 텍스트</td><td><code>실행 중</code></td></tr><tr><td><code>DateTime</code></td><td>ISO 8601 타임스탬프</td><td><code>2024-01-15T10:30:00Z</code></td></tr></tbody></table>

이러한 유형은 Configure 모달이 제공합니다. 수동으로 작성한 구성 파일에서는 서버가 허용하는 Int16, UInt16, 및 UInt32도 사용할 수 있습니다. `Int16`, `UInt16`그리고 `UInt32`를 서버가 허용합니다.

### 접근 수준

`ReadWrite` 태그는 OPC UA 클라이언트뿐 아니라 REST API, CLI, 웹 UI에서도 읽고 쓸 수 있습니다. 제어 출력, 설정값, 사용자 조정 값에 사용하세요.

`ReadOnly` 태그는 OPC UA 클라이언트의 쓰기를 다음으로 거부합니다 `BadNotWritable`. REST API, CLI, 웹 UI는 접근 수준과 관계없이 값을 계속 업데이트할 수 있으므로, `ReadOnly` 센서 값, 계산된 출력, 그리고 장치만 생성해야 하는 시스템 상태에 사용하세요.

### 선택적 제약 조건

숫자 유형은 허용 범위를 제한하는 "최소 값"과 "최대 값", 그리고 설명용 단위 레이블(ex: °C, PSI, RPM)을 위한 "공학 단위"를 지원합니다. 문자열 유형은 문자 수를 제한하는 "최대 길이"를 지원합니다.

## 인증

서버는 기본적으로 SecurityPolicy None을 사용하여 익명 연결을 허용합니다. 모든 클라이언트에 사용자 이름과 비밀번호를 요구하려면 Configure 모달에서 "인증 필요"를 켜세요.

토글이 켜져 있으면 사용자 이름과 비밀번호를 모두 입력해야 합니다. 비밀번호는 저장되기 전에 bcrypt로 해시되므로 원본은 절대 저장되지 않으며 나중에 복구할 수 없습니다. 기존 서버의 비밀번호를 변경하려면 Configure 모달에 새 비밀번호를 입력하고, 현재 비밀번호를 유지하려면 필드를 비워 두세요. 토글을 끄면 익명 액세스가 복원됩니다.

자격 증명은 두 개의 환경 변수로 저장되며, 둘 다 함께 설정되거나 둘 다 설정되지 않은 상태여야 합니다:

<table data-search="false"><thead><tr><th>변수</th><th>설명</th></tr></thead><tbody><tr><td><code>OPCUA_USERNAME</code></td><td>클라이언트 인증을 위한 일반 텍스트 사용자 이름입니다.</td></tr><tr><td><code>OPCUA_PASSWORD_HASH</code></td><td>salt 라운드 10으로 만든 비밀번호의 bcrypt 해시로, 다음으로 시작합니다 <code>$2b$10$</code>.</td></tr></tbody></table>

{% hint style="warning" %}
환경 변수를 편집하는 대신 Configure 모달을 통해 자격 증명을 설정하세요. 모달이 bcrypt 해시를 생성해 주며, `OPCUA_PASSWORD_HASH` 를 수동으로 설정하려면 외부에서 유효한 해시를 생성해야 합니다.
{% endhint %}

## 태그 보고

서버는 일정에 따라 태그를 Roboflow에 보고할 수 있으므로, 현장 방문 없이도 무엇을 제공하는지 볼 수 있습니다. Configure 모달의 "태그 보고" 섹션에서 설정하세요.

<table data-search="false"><thead><tr><th>설정</th><th>설명</th></tr></thead><tbody><tr><td>"주기적 태그 보고 전송"</td><td>보고를 켜거나 끕니다. 기본값은 켜짐입니다.</td></tr><tr><td>"태그 값 포함"</td><td>각 태그의 현재 값을 전송합니다. 태그 수만 보내려면 끄세요. 기본값은 켜짐입니다.</td></tr><tr><td>"보고 간격"</td><td>보고 사이의 초입니다. 기본값은 60입니다.</td></tr></tbody></table>

설정은 환경 변수로 저장되며, 서버는 시작 시 이를 읽습니다:

<table data-search="false"><thead><tr><th>변수</th><th>기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>OPCUA_SNAPSHOT_INTERVAL_SECONDS</code></td><td><code>60</code></td><td>보고 사이의 초 수. <code>0</code> 보고를 끕니다.</td></tr><tr><td><code>OPCUA_SNAPSHOT_INCLUDE_VALUES</code></td><td><code>true</code></td><td><code>false</code> 태그 수만 보냅니다.</td></tr><tr><td><code>OPCUA_SNAPSHOT_TTL_SECONDS</code></td><td>파생</td><td>보고가 최신 상태로 유지되는 시간입니다. 모달은 이를 간격에서 파생하며, 저장할 때마다 다시 씁니다.</td></tr></tbody></table>

서버가 허용하지 않는 값은 기본값으로 되돌아가는 대신 보고를 끄므로, 오타가 있으면 보고가 중지됩니다. 장치 페이지에서는 그런 장치를 보고하지 않음으로 표시합니다.

이러한 변수 중 하나라도 참조(`{$ref}`)로 설정되어 있으면, 모달은 보고를 편집할 수 없고 저장 시 현재 상태를 그대로 둡니다. 폼에서 보고를 관리하려면 참조를 리터럴 값으로 바꾸세요.

{% hint style="warning" %}
"태그 값 포함"은 주기적 보고에만 적용됩니다. 서버는 여전히 태그 값 변경을 컨테이너 로그에 기록하며, Roboflow가 이를 별도로 수집합니다.
{% endhint %}

## 모니터링

장치 페이지에는 연결된 클라이언트 수, "최대 세션 수" 대비 사용 중인 세션 수, 그리고 최신 태그 보고를 보여주는 실시간 OPC UA 상태 카드가 표시됩니다. 태그 보고보다 오래된 이미지를 사용하는 장치는 보고 대신 그렇게 표시됩니다.

서버가 세션 상한에 도달하여 새 클라이언트를 거부하면 카드에 세션 수, 상한, 그리고 거부된 클라이언트 수를 보여주는 배너가 표시됩니다. 이에 대한 이메일을 받으려면 장치의 "장치 경고" 탭에서 "OPC UA 클라이언트 거부" 경고를 추가하고, 먼저 허용할 거부 분 수를 설정하세요. 다음을 참조하세요 [장치 경고 설정](/deployment/ko/self-hosted/enterprise/deployment-manager/setting-up/set-up-device-alerts.md).

## 웹 인터페이스

서버는 다음 위치에 웹 인터페이스를 제공합니다 `http://<device-ip>:8092`.

<table data-search="false"><thead><tr><th>페이지</th><th>경로</th><th>내용</th></tr></thead><tbody><tr><td>대시보드</td><td><code>/</code></td><td>현재 값이 있는 모든 구성된 태그를 2초마다 새로 고칩니다. 접근 수준과 관계없이 편집 대화 상자를 통해 모든 태그 값을 수정할 수 있습니다.</td></tr><tr><td>문서</td><td><code>/docs.html</code></td><td>서버 가이드, 구성 형식 참조, 문제 해결 노트.</td></tr><tr><td>API 탐색기</td><td><code>/api/docs</code></td><td>엔드포인트를 테스트하고 요청 및 응답 스키마를 볼 수 있는 대화형 Swagger UI입니다.</td></tr></tbody></table>

## HTTP API

REST API는 태그 값과 서버 정보에 대한 프로그래밍 방식의 접근을 제공합니다. 모든 엔드포인트는 JSON을 반환합니다. 기본 URL은 `http://<device-ip>:8092/api`. 다음을 참조하세요 [서비스](/deployment/ko/self-hosted/enterprise/deployment-manager/services.md#using-the-apis) 모든 장치 내 서비스 API에 공통으로 적용되는 규칙은

{% hint style="warning" %}
HTTP API는 인증이 필요하지 않습니다. `OPCUA_USERNAME` 및 `OPCUA_PASSWORD_HASH` 포트 8092가 아니라 포트 4840의 OPC UA 바이너리 엔드포인트를 보호합니다. 포트 8092에 접근할 수 있는 것은 무엇이든 모든 태그를 쓸 수 있습니다.
{% endhint %}

태그 구조는 런타임에 변경할 수 없습니다. 태그와 폴더는 `OPCUA_CONFIG` 환경 변수에서 오거나, 대규모 구성의 경우 `OPCUA_CONFIG_FILE` 가 지정한 파일에서 오며, 이 API를 통해 생성, 변경, 삭제할 수 없습니다. 값만 쓸 수 있습니다.

### 태그 값 읽기 및 쓰기

`accessLevel` 는 OPC UA 프로토콜을 제어하며, 이 API가 아닙니다. 태그가 `ReadOnly` OPC UA 클라이언트의 쓰기를 다음으로 거부하지만 `BadNotWritable` 여기에서는 계속 쓸 수 있으며, 이것이 파이프라인이 산업용 클라이언트가 소비해야 하는 센서 값을 게시하는 방식입니다.

```bash
curl http://<device-ip>:8092/api/tags

curl -X PUT http://<device-ip>:8092/api/tags/tag_temperature/value \\
  -H "Content-Type: application/json" \\
  -d '{"value": 25.5}'
```

{% openapi src="/files/d85a2b579cf06b3c6e795585ec1fba2ec9bc1543" path="/tags" method="get" %}
[edge-opcua-server.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-21a215712d389ded373872b7a4e970e80be2c5fa%2Fedge-opcua-server.yaml?alt=media)
{% endopenapi %}

{% openapi src="/files/d85a2b579cf06b3c6e795585ec1fba2ec9bc1543" path="/tags/{id}" method="get" %}
[edge-opcua-server.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-21a215712d389ded373872b7a4e970e80be2c5fa%2Fedge-opcua-server.yaml?alt=media)
{% endopenapi %}

{% openapi src="/files/d85a2b579cf06b3c6e795585ec1fba2ec9bc1543" path="/tags/{id}/value" method="put" %}
[edge-opcua-server.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-21a215712d389ded373872b7a4e970e80be2c5fa%2Fedge-opcua-server.yaml?alt=media)
{% endopenapi %}

쓰기 작업은 다음 경우에 거부됩니다 `400` 값이 없거나, 유형이 태그의 `dataType`와 일치하지 않거나, 설정된 `minValue`, `maxValue` 또는 `maxLength`을 벗어날 때입니다. 존재하지 않는 태그에 쓰려고 해도 `400`를 반환하며,  `404`. `GET /tags/{id}` 는 `404`를 반환하므로, 알 수 없는 태그와 잘못된 값을 구분해야 할 때 사용하세요.

### 구성 엔드포인트

실행 중인 구성의 읽기 전용 보기로, 쓰기 전에 태그 ID와 해당 제약 조건을 찾는 데 유용합니다.

{% openapi src="/files/d85a2b579cf06b3c6e795585ec1fba2ec9bc1543" path="/config" method="get" %}
[edge-opcua-server.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-21a215712d389ded373872b7a4e970e80be2c5fa%2Fedge-opcua-server.yaml?alt=media)
{% endopenapi %}

{% openapi src="/files/d85a2b579cf06b3c6e795585ec1fba2ec9bc1543" path="/config/folders" method="get" %}
[edge-opcua-server.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-21a215712d389ded373872b7a4e970e80be2c5fa%2Fedge-opcua-server.yaml?alt=media)
{% endopenapi %}

### 세션 및 상태

일단 `maxSessions` 에 도달하면 추가 클라이언트는 다음으로 거부됩니다 `BadTooManySessions`, 따라서 `sessionCount` 와 비교하여 `maxSessions` 여유를 확인하세요.

하나의 `200` 에서 `/subscriptions` 세션 목록이 0으로 표시되고 `maxSessions` 생략되면 OPC UA 서버가 실행 중이 아님을 의미합니다. 이를 예열이 아니라 장애로 취급하세요. 엔드포인트가 응답하기만 하면 시작은 이미 끝났거나 실패한 것입니다. 다음으로 확인하세요 `/health`를 통해 `status: "unhealthy"` 및 `opcuaServer: "stopped"`.

`maxSessions` 는 이 경우 0이 아니라 생략되므로, `maxSessions - sessionCount` 를 계산하는 소비자가 알 수 없는 상한을 전체 상한으로 읽지 않습니다.

{% openapi src="/files/d85a2b579cf06b3c6e795585ec1fba2ec9bc1543" path="/subscriptions" method="get" %}
[edge-opcua-server.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-21a215712d389ded373872b7a4e970e80be2c5fa%2Fedge-opcua-server.yaml?alt=media)
{% endopenapi %}

{% hint style="info" %}
`/subscriptions` 사양에 누락되어 있더라도 장치는 다음에서 제공합니다 `/api/openapi.json`. 경로는 어쨌든 활성 상태이며, 여기에서 문서화되어 있습니다.
{% endhint %}

`/health` 반환합니다 `200` OPC UA 서버가 실행 중인지 여부와 관계없이. 다음을 확인하세요 `status` 및 `opcuaServer` 상태 코드 대신.

{% openapi src="/files/d85a2b579cf06b3c6e795585ec1fba2ec9bc1543" path="/health" method="get" %}
[edge-opcua-server.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-21a215712d389ded373872b7a4e970e80be2c5fa%2Fedge-opcua-server.yaml?alt=media)
{% endopenapi %}

## CLI

이 `opcua-cli` 도구는 웹 UI에 접근할 수 없을 때 디버깅, 스크립팅, 빠른 태그 작업을 위해 서버에 터미널로 접근할 수 있게 해줍니다.

```bash
docker exec -it opcua-server opcua-cli
```

```bash
docker exec opcua-server opcua-cli <command>
```

<table data-search="false"><thead><tr><th>명령</th><th>설명</th></tr></thead><tbody><tr><td><code>list</code>, <code>ls</code></td><td>현재 값과 함께 모든 태그를 나열</td></tr><tr><td><code>read &#x3C;tag></code></td><td>특정 태그 값을 읽기</td></tr><tr><td><code>write &#x3C;tag> &#x3C;value></code></td><td>태그에 값을 쓰기</td></tr><tr><td><code>status</code></td><td>서버 상태와 가동 시간을 표시</td></tr><tr><td><code>clients</code></td><td>연결된 OPC UA 클라이언트 나열</td></tr><tr><td><code>clients --detailed</code></td><td>구독 세부 정보와 함께 클라이언트 나열</td></tr><tr><td><code>export</code></td><td>구성을 JSON으로 내보내기</td></tr></tbody></table>

```bash
docker exec opcua-server opcua-cli read Temperature
docker exec opcua-server opcua-cli write Temperature 25.5
docker exec opcua-server opcua-cli clients --detailed
```

## 로깅

설정 `LOG_LEVEL` 를 서비스에 설정하여 상세 수준을 제어하세요. 서비스 환경 변수를 편집하는 위치는 [장치 구성 업데이트](/deployment/ko/self-hosted/enterprise/deployment-manager/making-changes/update-device-configuration.md) 를, 출력 내용을 읽는 방법은 [장치 로그 보기](/deployment/ko/self-hosted/enterprise/deployment-manager/monitoring/view-device-logs.md) 를 참조하세요.

<table data-search="false"><thead><tr><th>수준</th><th>설명</th></tr></thead><tbody><tr><td><code>DEBUG</code></td><td>상세한 진단 정보</td></tr><tr><td><code>INFO</code></td><td>일반적인 운영 메시지(기본값)</td></tr><tr><td><code>WARN</code></td><td>작동을 멈추지는 않지만 잠재적인 문제가 있음</td></tr><tr><td><code>ERROR</code></td><td>기능에 영향을 주는 오류</td></tr></tbody></table>

값은 대소문자를 구분하지 않으며, 인식되지 않은 값은 다음으로 되돌아갑니다 `INFO`.
