> For the complete documentation index, see [llms.txt](https://kopens.gitbook.io/plantpulse-platform/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kopens.gitbook.io/plantpulse-platform/developer/configuration.md).

# 설정 및 배포 가이드

## 통합 설정 모델

PlantPulse 의 모든 설정은 **단일 소스(env.sh) → 템플릿 치환 → 모듈 설정 파일** 의 3 단계로 관리됩니다.

```mermaid
flowchart LR
  ENV[plantpulse-startup/env.sh<br/>전역 단일 소스]
  TPL[template/*.template<br/>placeholder 포함]
  CFG[모듈별 .properties · .xml · .yml<br/>실제 설정]
  RUN[모듈 런타임]

  ENV -->|configure.sh<br/>= startup.jar CONFIGURE| TPL
  TPL --> CFG
  CFG --> RUN
```

* **운영 환경에서는 `env.sh` 만 편집**하고 `configure.sh` 를 실행해 모든 모듈 설정을 일괄 생성하세요.
* 모듈 설정을 직접 편집하면 다음 `configure.sh` 실행 시 덮어쓰여집니다.
* 단일 노드 / 클러스터 / 컨테이너 환경 모두 동일한 패턴을 사용합니다.

| 환경            | env.sh 위치                                                   |
| ------------- | ----------------------------------------------------------- |
| 바이너리 (dev 서버) | `/opt/kopens/plantpulse-platform/plantpulse-startup/env.sh` |
| Docker 컨테이너   | 호스트 `/home/kopens/plantpulse-platform-docker/bin/env.sh`    |

env.sh 전체 변수 인덱스 → [프로퍼티 레퍼런스](/plantpulse-platform/admin/properties-reference.md) 참고.

### 변경 표준 절차

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-startup

vi env.sh              # 1. 편집
./env-validate.sh      # 2. 검증
./configure.sh         # 3. 템플릿 적용
./restart.sh           # 4. 재시작
./status.sh            # 5. 검증
```

## 설정 파일 구조

이 문서에서는 PlantPulse 서버의 설정 파일 구조와 각 설정 항목에 대해 안내합니다. 모든 설정 파일은 `plantpulse-server/app/plantpulse-server-web/WEB-INF/classes/` 디렉토리에 위치하고 있습니다.

처음 설정 파일을 살펴보시는 분이라면, 가장 자주 수정하게 되는 `storage.properties`(DB 연결)와 `engine.properties`(엔진 성능)를 먼저 확인해 보시는 것을 권장합니다.

```
WEB-INF/classes/
├── application.properties    # 앱 기본 설정 (테마, 알람, 스냅샷, 진단)
├── engine.properties         # 엔진 파이프라인 성능 설정
├── storage.properties        # DB 연결 및 스토리지 정책 설정
├── mq.properties             # 메시지 브로커 (Kafka/MQTT) 설정
├── websocket.properties      # WebSocket 실시간 푸시 설정
├── mail.properties           # SMTP 이메일 / SMS 알림 설정
├── quartz.properties         # Quartz 잡 스케줄러 설정
├── log4j.xml                 # 로그 설정
├── resources/
│   ├── db-config.xml         # DB 연결 풀 설정
│   ├── jms-spring.xml        # JMS 스프링 설정
│   └── i18n/                 # 다국어 메시지 (ko, en)
└── META-INF/spring/
    ├── spring-context.xml    # Root Spring 컨텍스트
    ├── servlet-context.xml   # DispatcherServlet 설정
    └── controllers.xml       # @Controller 컴포넌트 스캔
```

보안 규칙 파일은 아래 경로에 별도로 위치하고 있습니다.

```
WEB-INF/config/
└── security-rule.xml         # URL 패턴별 접근 제어 규칙
```

***

## application.properties

애플리케이션의 기본 동작을 설정하는 파일입니다. 테마, 알람, 스냅샷, 진단 등 다양한 기능의 동작 방식을 이곳에서 정의합니다.

```properties
# === 테마 ===
application.theme=gray                    # 웹 콘솔 테마

# === 홈 페이지 ===
home.page.user=/dashboard/                # 일반 사용자 기본 페이지
home.page.admin=/map/                     # 관리자 기본 페이지

# === 알람 ===
alarm.list.page.index.limit=100           # 알람 목록 페이지 크기
alarm.list.page.advsearch.limit=1000      # 고급 검색 최대 건수
alarm.duplicate.check.minutes=10          # 알람 중복 체크 간격 (분)
alarm.read.check.interval.ms=60000        # 알람 읽기 체크 간격 (ms)
alarm.new.audio.play=true                 # 새 알람 사운드 재생

# === EQL 기본 쿼리 ===
base.eql=SELECT * FROM Point.win:length(1) WHERE tag_id = '...'

# === 쿼리 ===
query.default.display.count=50            # 기본 표시 건수
query.default.expire.time.sec=3600        # 쿼리 만료 시간 (초)

# === 스냅샷 ===
snapshot.tagmap.timer.period.ms=1000      # 태그맵 스냅샷 주기 (ms)
snapshot.asset.event.timer.period.ms=1000 # 에셋 이벤트 스냅샷 주기 (ms)
pointmap.timer.period.ms=2000             # 포인트맵 갱신 주기 (ms)

# === 에셋 ===
asset.point.insert.schedule.cron=0 */1 * * * ?  # 에셋 포인트 집계 크론
asset.point.timer.period.ms=1000          # 에셋 포인트 타이머 주기 (ms)

# === OPC 에이전트 ===
opc.agent.protocol=http                   # 에이전트 프로토콜
opc.agent.port=60000                      # 에이전트 포트

# === 진단 Webhook ===
diagnostic.webhook.enable=false           # Webhook 알림 활성화
diagnostic.webhook.level=ERROR,WARN       # 알림 레벨
diagnostic.webhook.url=                   # Webhook URL

# === API ===
api.key=GED1-PPLA-TAXD-PTL1-14DF-3FXF    # REST API 인증 키
```

## engine.properties

데이터 처리 엔진의 성능 튜닝 설정 파일입니다. 파이프라인 스레드 수, 처리율 제한 등 엔진의 핵심 성능 파라미터를 이곳에서 조정하실 수 있습니다.

```properties
# === 파이프라인 ===
engine.pipeline.threads=36                # 워커 스레드 수
engine.pipeline.ratelimit=40000           # 초당 최대 메시지 수 (MPS)
engine.pipeline.queue.size=1200000        # 인제스트 버퍼 큐 크기
engine.pipeline.queue.o3.delay=50         # Out-of-Order 지연 (ms)
engine.pipeline.task.mode=SINGLE          # 태스크 모드 (SINGLE/MULTI)

# === 비동기 처리 ===
engine.async.parallelism=256              # 비동기 실행기 병렬 수

# === CEP ===
engine.cep.server.ip=127.0.0.1            # CEP 서버 IP
engine.cep.server.port=7400               # CEP 서버 포트

# === 스트리밍 ===
engine.stream.processor=DIRECT            # 스트림 처리 모드
engine.streaming.messaging.warning.ms=5000    # 메시지 지연 경고 기준 (ms)
engine.streaming.messaging.timeout.ms=10000   # 메시지 타임아웃 (ms)
engine.streaming.messaging.timeout.store.type=FILE_QUEUE  # 타임아웃 저장 방식
engine.streaming.messaging.timeout.recovery.type=DB       # 타임아웃 복구 방식

# === 작업 스레드 ===
engine.job.thread.asset=8                 # 에셋 작업 스레드 수
engine.job.thread.point=8                 # 포인트 작업 스레드 수

# === DDS (Data Distribution Service) ===
engine.dds.enabled=false                  # DDS 활성화
engine.dds.data.tag.enabled=false         # 태그 DDS 활성화
engine.dds.data.asset.enabled=false       # 에셋 DDS 활성화

# === NTP ===
engine.ntpdate.server.ip=127.0.0.1       # NTP 서버 IP
engine.ntpdate.sync=false                 # NTP 동기화 활성화

# === 데이터 플로우 ===
engine.dataflow.class=plantpulse.core.engine.pipeline.dataflow.BaseDataFlow
engine.dataflow.server-timestamp.override=false   # 서버 타임스탬프 덮어쓰기
engine.dataflow.negative-timestamp.override=true  # 음수 타임스탬프 보정

# === 이상 감지 ===
engine.data.anomaly.enabled=false         # 이상 감지 활성화
engine.data.anomaly.url=http://127.0.0.1:8970  # 이상 감지 서버 URL
```

### 환경별 권장값

아래 표는 서버 사양에 따른 권장 설정값입니다. 운영 환경에 맞게 조정해 주세요.

| 항목                  | 개발 (8코어) | 스테이징 (16코어) | 운영 (16코어) | 대규모 (32코어) |
| ------------------- | -------- | ----------- | --------- | ---------- |
| pipeline.threads    | 8        | 16          | 36        | 64         |
| pipeline.ratelimit  | 5,000    | 20,000      | 40,000    | 100,000    |
| pipeline.queue.size | 100,000  | 500,000     | 1,200,000 | 5,000,000  |
| async.parallelism   | 32       | 128         | 256       | 512        |

## storage.properties

데이터베이스 연결 및 스토리지 정책을 설정하는 파일입니다. PostgreSQL, Cassandra, Redis 등 각 저장소의 연결 정보와 데이터 보관 정책을 이곳에서 관리합니다.

```properties
# === PostgreSQL (메타스토어) ===
metastore.driver=org.postgresql.Driver
metastore.url=jdbc:postgresql://HOST:5432/pp?characterEncoding=UTF-8&reWriteBatchedInserts=true
metastore.user=plantpulse
metastore.password=plantpulse123!

# === Redis (캐시) ===
cache.host=HOST
cache.port=6379
cache.password=redis123!

# === TSE (시계열 엔진) ===
tse.protocol=http
tse.host=HOST
tse.port=7800
tse.user=tse
tse.password=tse123!

# === Data Gateway ===
data.gateway.protocol=https
data.gateway.host=127.0.0.1
data.gateway.port=5501
data.gateway.api.key=GED1-PPLA-TAXD-PTL1-14DF-3FXF

# === Cassandra ===
storage.db_type=CASSANDRA
storage.db_version=5.0
storage.host=HOST
storage.port=9042
storage.keyspace=pp
storage.user=cassandra
storage.password=cassandra
storage.durable_writes=true
storage.replication={ 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 1 }

# === TTL (데이터 보관 기간, 일) ===
storage.tag.point.ttl=62                          # 태그 포인트 원본
storage.tag.point.map.ttl=1                       # 포인트 맵
storage.tag.point.sampling.ttl=93                 # 샘플링
storage.tag.point.snapshot.ttl=93                 # 스냅샷
storage.tag.point.aggregation.ttl=93              # 집계
storage.tag.point.archive.ttl=365                 # 아카이브
storage.tag.blob.ttl=93                           # BLOB
storage.asset.data.ttl=10                         # 에셋 데이터
storage.asset.data.sampling.ttl=31                # 에셋 샘플링
storage.asset.data.snapshot.interval=1 SECONDS    # 스냅샷 간격

# === 컴팩션 전략 (UCS/TWCS) ===
storage.table.compaction.strategy=UCS
storage.table.compaction.strategy.ucs.scailing_parameter=T8
storage.table.compaction.strategy.ucs.min_sstable_size=128MiB
storage.table.compaction.strategy.ucs.target_sstable_size=512MiB
storage.table.compaction.strategy.ucs.base_shard_count=8
storage.table.compaction.strategy.ucs.max_sstables_to_compact=6
storage.table.compaction.strategy.ucs.sstable_growth=0.7

# === 압축 (ZStandard) ===
storage.compression.zstd.type=org.apache.cassandra.io.compress.ZstdDictionaryCompressor
storage.compression.zstd.level=3

# === 쿼리 제한 ===
storage.tag.point.select.limit.size=1000000       # 포인트 조회 최대 건수

# === 캐시 ===
storage.asset.data.row.cache.size=NONE
storage.tag.point.row.cache.size=NONE

# === 메타스토어 동기화 ===
storage.internal.metastore.enabled=false
storage.internal.metastore.thread.count=4
storage.internal.metastore.queue.size=1200000
storage.internal.metastore.point.retention.days=10

# === 메타데이터 백업 ===
storage.domain.model.changed.to.metastore.backup=true
```

## mq.properties

메시지 브로커 및 DDS(Data Distribution Service) 토픽을 설정하는 파일입니다. Kafka와 MQTT의 토픽 이름을 이곳에서 관리합니다.

```properties
# === 메시지 브로커 연결 ===
mq.host=HOST
mq.user=admin
mq.password=plantpulse

# === DDS Kafka 토픽 ===
mq.dds.kafka.topic.tag.point=pp-tag-point
mq.dds.kafka.topic.tag.alarm=pp-tag-alarm
mq.dds.kafka.topic.asset.data=pp-asset-data
mq.dds.kafka.topic.asset.alarm=pp-asset-alarm
mq.dds.kafka.topic.asset.event=pp-asset-event
mq.dds.kafka.topic.asset.aggregation=pp-asset-aggregation
mq.dds.kafka.topic.asset.context=pp-asset-context
mq.dds.kafka.topic.domain.changed.event=pp-domain-changed-event

# === DDS MQTT 토픽 ===
mq.dds.mqtt.topic.tag.point=tag/point/{tag_id}
mq.dds.mqtt.topic.tag.alarm=tag/alarm/{tag_id}
mq.dds.mqtt.topic.asset.data=asset/data/{asset_id}
mq.dds.mqtt.topic.asset.alarm=asset/alarm/{asset_id}
mq.dds.mqtt.topic.asset.event=asset/event/{asset_id}
mq.dds.mqtt.topic.asset.aggregation=asset/aggregation/{asset_id}
mq.dds.mqtt.topic.asset.context=asset/context/{asset_id}
mq.dds.mqtt.topic.asset.command=asset/command/{asset_id}
mq.dds.mqtt.topic.domain.changed.event=domain-changed-event
```

## websocket.properties

실시간 데이터 푸시용 WebSocket 설정 파일입니다.

```properties
websocket.server.user=ws
websocket.server.password=<비밀번호>
websocket.server.host=HOST
websocket.server.port=8000
websocket.server.port_ssl=8004
websocket.server.proxy=
```

## mail.properties

알람 알림 이메일 및 SMS 발송 설정 파일입니다. 알람 발생 시 이메일이나 SMS로 알림을 받으시려면 이 파일을 운영 환경에 맞게 설정해 주세요.

```properties
# === SMTP ===
mail.smtp.host=HOST
mail.smtp.port=25
mail.smtp.auth=false
mail.smtp.user=webmaster@kopens.com
mail.smtp.password=<비밀번호>
mail.smtp.starttls.enable=false

# === SMS ===
sms.sender.class=plantpulse.cep.listener.alarm.sms.DefaultSMSSender

# === 진단 로그 이메일 ===
diagnostic.log.email=diag@kopens.com
```

## quartz.properties

Quartz 잡 스케줄러 설정 파일입니다. 주기적으로 실행되는 백그라운드 작업들의 실행 환경을 이곳에서 설정합니다.

```properties
# === 스케줄러 ===
org.quartz.scheduler.instanceName=PP_SCHEDULER
org.quartz.scheduler.instanceId=PLATFORM
org.quartz.scheduler.threadName=QUARTZ_THREAD
org.quartz.scheduler.makeSchedulerThreadDaemon=true

# === 스레드 풀 ===
org.quartz.threadPool.class=plantpulse.core.engine.scheduling.thread.JobThreadPool
org.quartz.threadPool.threadCount=8
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadNamePrefix=QUARTZ_SCHEDULER_JOB
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
```

***

## 보안 규칙 설정

### security-rule.xml

URL 패턴별 접근 제어 규칙을 정의하는 파일입니다. `WEB-INF/config/security-rule.xml`에 위치하고 있으며, 사용자의 역할에 따라 접근 가능한 URL을 제어합니다.

```xml
<security-rule>
  <!-- 전체 허용 (로그인 필요) -->
  <rule url="/env*" role="ALL"/>
  <rule url="/connect*" role="ALL"/>
  <rule url="/monitoring/*" role="ALL"/>
  <rule url="/map/*" role="ALL"/>
  <rule url="/dashboard/*" role="ALL"/>
  <rule url="/alarm/*" role="ALL"/>
  <rule url="/data*" role="ALL"/>
  <rule url="/storage*" role="ALL"/>
  <rule url="/scada*" role="ALL"/>
  <rule url="/tag*" role="ALL"/>
  <rule url="/asset*" role="ALL"/>
  <rule url="/equipment*" role="ALL"/>
  <rule url="/graph*" role="ALL"/>
  <rule url="/query*" role="ALL"/>
  <rule url="/stream*" role="ALL"/>
  <rule url="/opc*" role="ALL"/>
  <rule url="/plc*" role="ALL"/>
  <rule url="/modbus*" role="ALL"/>
  <rule url="/database*" role="ALL"/>
  <rule url="/file*" role="ALL"/>
  <rule url="/trigger*" role="ALL"/>
  <rule url="/user*" role="ALL"/>
  <rule url="/security*" role="ALL"/>
  <rule url="/enginemanager*" role="ALL"/>
  <rule url="/admin*" role="ALL"/>
  <rule url="/config*" role="ALL"/>
  <rule url="/log*" role="ALL"/>
  <rule url="/token*" role="ALL"/>
  ...
</security-rule>
```

총 43개 이상의 URL 패턴이 정의되어 있습니다. 각 역할의 의미는 다음과 같습니다.

| 역할        | 설명                |
| --------- | ----------------- |
| `ALL`     | 로그인한 모든 사용자 접근 가능 |
| `ADMIN`   | 관리자만 접근 가능        |
| `MANAGER` | 매니저 이상 접근 가능      |
| `USER`    | 일반 사용자 이상 접근 가능   |

***

## 배포 가이드

### 배포 체크리스트

운영 환경에 배포하시기 전에 아래 항목들을 확인해 주세요.

1. **설정 파일 확인**: 각 properties 파일의 HOST, 비밀번호를 운영 환경에 맞게 변경해 주세요.
2. **DB 연결 테스트**: PostgreSQL, Cassandra, Redis 접속이 정상인지 확인해 주세요.
3. **포트 확인**: 필수 포트가 개방되어 있는지 확인해 주세요 ([포트 및 서비스 관리](/plantpulse-platform/admin/ports.md) 참조).
4. **JVM 메모리**: 각 모듈의 `bin/start.sh`에서 운영 환경에 맞게 메모리를 설정해 주세요.
5. **로그 디렉토리**: 로그 디렉토리에 쓰기 권한이 있는지 확인해 주세요.
6. **SSL 인증서**: HTTPS를 사용하시는 경우 키스토어 파일을 배치해 주세요.
7. **env.sh 확인**: `plantpulse-startup/env.sh` 환경 변수가 올바르게 설정되어 있는지 확인해 주세요.

### 설정 변경 시 안내사항

| 설정 파일                  | 재시작 필요 | 재시작 명령                            |
| ---------------------- | ------ | --------------------------------- |
| application.properties | O      | `restart-server.sh`               |
| engine.properties      | O      | `restart-server.sh` (엔진 재초기화)     |
| storage.properties     | O      | `restart-server.sh` (DB 연결 재수립)   |
| mq.properties          | O      | `restart-server.sh` (메시지 리스너 재시작) |
| websocket.properties   | O      | `restart-server.sh`               |
| mail.properties        | O      | `restart-server.sh`               |
| quartz.properties      | O      | `restart-server.sh`               |
| security-rule.xml      | O      | `restart-server.sh` (보안 규칙 재로드)   |

> **안내**: 모든 설정 파일 변경은 `plantpulse-server` 재시작이 필요합니다. 운영 중 변경 시 서비스 중단이 발생하므로, 점검 시간에 수행해 주세요.

***

## 기술 지원

설정 관련 문의: <webmaster@kopens.com>
