# Docker 랩 둘러보기

> 데이터소스 어댑터 통합 테스트를 위해 Xisom 스택과 함께 산업 프로토콜 랩(OPC UA + MQTT 시뮬레이터)을 구동합니다.

이 둘러보기는 이 저장소에 포함된 로컬 OPC UA + MQTT 시뮬레이터 샌드박스인
**`docker-industrial-lab`**을 Xisom 스택 옆에 구동하여, 실제 공장 네트워크 없이도
MQTT와 OPC UA 데이터소스 어댑터를 엔드투엔드로 실습할 수 있게 합니다.

**이 랩이 있는 위치**

이 랩은 이 저장소의 `docker-industrial-lab/`에 있는 일부입니다 — 별도로 클론해야 하는
저장소가 아닙니다. 자체 `docker-compose.yml`, 생성된 `.env`, 그리고 `up` / `down` /
`smoke` 타깃을 가진 `Makefile`을 갖추고 있습니다.

## 무엇을 구축하나요

- **OPC UA 시뮬레이터** (`lab-opcua`) — 공장 태그, 쓰기 가능한 설정값(AIBOARD 출력
  쓰기 테스트용), 그리고 규모 테스트용 샘플 태그를 노출하는 보안 서버입니다.
- **MQTT 브로커** (`lab-mosquitto`, Eclipse Mosquitto) — 기본적으로 보안됩니다(TLS +
  사용자 이름/비밀번호, 또는 상호(mutual) TLS), 익명 폴백 프로파일도 있습니다.
- **MQTT 퍼블리셔 + 스니퍼** — 공장 데이터를 발행하는 장치를 시뮬레이션하고, AIBOARD의
  출력 싱크가 실제로 무엇을 쓰는지 확인합니다.
- **여러분의 Xisom 스택** (추론 + 백엔드 + 프런트엔드) — 저장소 루트의 선택적
  `docker-compose.lab.yml` 오버레이를 통해 랩의 Docker 네트워크에 연결하거나, 오버레이
  없이 호스트 루프백을 통해 접근할 수 있습니다.

## 단계

1. **시크릿을 부트스트랩하고 랩을 기동합니다.** 스택은 기본적으로 보안됩니다; 최초
   실행 시 일회성 스크립트가 프라이빗 CA, 클라이언트 인증서, 브로커/OPC UA 자격 증명을
   생성합니다:

   ```bash
   cd docker-industrial-lab
   ./scripts/bootstrap-secrets.sh   # or: make certs
   docker compose up -d             # or: make up
   docker compose ps                # expect every service "healthy" within ~30s
   ```

   
**.env.example을 손으로 복사하지 마세요**

   `bootstrap-secrets.sh`는 실제 `.env`(랜덤 비밀번호 + `COMPOSE_PROFILES=secure`)를
   생성합니다. `.env.example`을 직접 `.env`로 복사하면 PKI 생성 과정을 건너뛰게 되어 —
   `certs-guard` 서비스가 스크립트를 실행할 때까지 즉시 실패합니다.
   

2. 보안된 스택을 엔드투엔드로 확인하기 위해 **스모크 테스트를 실행합니다**:

   ```bash
   ./scripts/smoke-test.sh   # or: make smoke
   ```

3. **Xisom 스택을 랩 네트워크에 연결합니다** (저장소 루트에서, 한 단계 위):

   ```bash
   cd ..
   docker compose -f docker-compose.yml -f docker-compose.lab.yml up -d
   ```

   이렇게 하면 `backend` 서비스가 랩의 `industrial-lab` Docker 네트워크에 연결되어
   컨테이너 DNS(`opcua`, `mosquitto`)로 시뮬레이터에 도달합니다 — 호스트 포트가
   필요 없습니다. 호스트 루프백 URL(`host.docker.internal:...`)도 이 오버레이 없이
   동작합니다.

4. **Xisom 대시보드에 데이터소스를 추가합니다** — `opc.tcp://opcua:4840/factory/line1`
   (오버레이 없이는 `host.docker.internal`)의 OPC UA 입력, 그리고/또는
   `mqtt://mosquitto:8884`(TLS + 사용자 이름/비밀번호)의 MQTT 입력. 자격 증명은 생성된
   `docker-industrial-lab/.env`에 있습니다.

## 검증

- (`docker-industrial-lab/` 안에서) `docker compose ps`가 모든 서비스를 `healthy`로
  표시합니다.
- Xisom 대시보드에서 데이터소스를 활성화하고 **Start**한 뒤 [추론 통계](/ko/operate/monitoring/)를
  열면 — 시뮬레이션된 태그로부터 실시간 처리량이 보여야 합니다.
- AIBOARD 출력 쓰기가 실제로 어떻게 도착하는지 확인합니다: `docker logs lab-opcua | grep WRITE`
  또는 `docker logs lab-mqtt-sniffer`.

## 샘플 env 조절값 (부하/규모 테스트)

*(v1.28.0, 랩 전용 — 제품 런타임에는 영향 없음.)* 두 시뮬레이터 모두 기본 공장 데모보다
더 높은 태그 수와 속도를 구동하기 위한 추가 env 조절값을 `docker-industrial-lab/.env`에
노출합니다. AIBOARD의 어댑터를 부하 상태에서 실습하는 데 유용합니다:

| Env 변수 | 기본값 | 목적 |
|---|---|---|
| `SAMPLE_TAG_COUNT` | `100` | 두 프로토콜 모두에 대한 추가 샘플 태그 — MQTT `aiboard/sample_mqtt/topic_1..N`, OPC UA `ns=2;s=SampleOpcua_Tag_1..N`. `0`은 비활성화합니다. |
| `SAMPLE_RATE_HZ` | 설정 안 됨(기존 속도) | 두 시뮬레이터 모두에 대한 전체 루프 샘플링 속도(Hz), 예: `10`/`20`/`50`. MQTT의 `PUBLISH_INTERVAL`과 OPC UA의 기본값 1 Hz를 재정의합니다. |
| `SAMPLE_WALK_STEP` | `4.0` | 평균 회귀 랜덤 워크의 샘플당 가우시안 스텝 크기(클수록 더 요동침). |
| `SAMPLE_WALK_CENTER` | `50.0` | 워크가 회귀하는 목표 값. |
| `SAMPLE_WALK_REVERSION` | `0.05` | 중심을 향한 당김 강도, `0`–`1`(0 = 순수 랜덤 워크). |
| `SAMPLE_MQTT_QOS` | `0` | 샘플 MQTT 토픽 전용 QoS — 어댑터를 `0`/`1`/`2`에서 테스트합니다. 공장 토픽은 항상 QoS 0을 유지합니다. |
| `SAMPLE_MQTT_RETAIN` | `false` | 샘플 MQTT 토픽 전용 retain 플래그. |

높은 `SAMPLE_RATE_HZ`와 큰 `SAMPLE_TAG_COUNT`가 결합되면(예: 프로토콜당 초당 약 5천
쓰기에 해당하는 50 Hz × 100태그), 시뮬레이터 루프가 예산을 초과하여 실제 속도가
목표보다 낮아질 수 있습니다 — 확실한 처리량 보장이 필요하다면 조절값 중 하나를
낮추세요.

## 정리

```bash
cd docker-industrial-lab
make down   # docker compose --profile secure --profile insecure --profile dashboard down -v
```

이렇게 하면 컨테이너와 볼륨이 제거되지만 생성된 PKI(`certs/`, `mosquitto/secrets/`)는
유지되므로 이후 `up`을 실행할 때 다시 부트스트랩할 필요가 없습니다. 자격 증명을
교체하려면 `./scripts/bootstrap-secrets.sh --force`를 사용하세요.

## 문제가 발생하면

서비스가 `healthy`에 도달하지 못하거나 대시보드에 트래픽이 없다면 —
[문제 해결](/ko/troubleshooting/) 런북을, 브로커 측 원인에 대해서는 특히
[MQTT 입력 중지 또는 결함](/ko/troubleshooting/mqtt-input-stops/)을 참조하세요.
