프로퍼티 레퍼런스
이 문서는 배포되는 실물 설정 템플릿(
*.properties)에서 재생성됨 (2026-07-28) — 템플릿의 현재 위치는plantpulse-datalake-cli/config/templates이고, 호스트의/etc/kopens/conf가 그 자리로 바인드 마운트됩니다 배포 경로 매핑 정본은plantpulse-startup/src/plantpulse/startup/config/ConfigTemplates.java, 로딩 우선순위 정본은plantpulse-core/src/plantpulse/core/engine/utils/PropertiesUtils.java다.키를 추가/삭제/개명했다면 이 문서가 아니라 템플릿이 정본이다. 문서를 손으로 채우지 말고 템플릿에서 다시 뽑아라. 각 표의 "기본값" 은 템플릿에 적힌 그대로이며,
${PP_XXX}는configure.sh가env.sh값으로 치환하는 자리다.
설정 3단 모델
| 단계 | 위치 | 변경 방법 |
|---|---|---|
| 전역 설정 | plantpulse-startup/env.sh | 직접 편집 후 ./configure.sh → 해당 모듈 재시작 |
| 사이트 오버라이드 | plantpulse-startup/env.local.sh | env.sh 는 전부 ${PP_VAR:-default} 형태라 이미 export 된 값이 이긴다 |
| 모듈 설정 | 각 모듈의 config/ | 직접 편집 가능하나 다음 configure.sh 실행 시 덮어쓰여진다 |
권장: 운영 환경에서는
env.sh(또는env.local.sh)만 편집하고configure.sh가 모든 모듈 설정을 생성하게 하라.
env.sh 변경 표준 절차
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
vi env.sh # 1. 편집
./env-validate.sh # 2. 검증 (선택)
./configure.sh # 3. 템플릿 치환 + 각 모듈 config/ 로 배포
./restart.sh # 4. 재시작 (또는 ./restart-<module>.sh)
./status.sh # 5. 확인
configure.sh는 설정 파일을 다시 렌더할 뿐 서비스를 재시작하지 않는다. 재시작 전까지는 새 설정이 디스크에만 있고 구 프로세스가 살아 있는 상태다.
설정 파일 로딩 우선순위
웹 애플리케이션(server / batch / cep / sql / data-gateway)은 다음 순서로 설정 파일을 찾는다. 구현은 PropertiesUtils.readExternalFirst() 다.
-Dpp.conf.dir시스템 프로퍼티로 지정한 디렉토리 (상수PropertiesUtils.CONF_DIR_SYSTEM_PROPERTY = "pp.conf.dir")${catalina.base}/../config— 모듈의config/디렉토리- 웹앱 클래스패스 (WAR 에 포함된 기본값) — fallback
외부 파일은 UTF-8 로 읽는다. 외부 설정이 정상 로드되면 기동 로그에 다음이 출력된다.
Properties loaded from external conf: <절대경로>
외부 파일 읽기에 실패하면 error 로그를 남기고 클래스패스로 fallback 한다.
로깅 설정(log4j2.xml)도 같은 체인으로 외부화되어 있다(자가 시딩 — 외부 파일이 없으면 WAR 기본값을 모듈 config/log4j2.xml 로 1회 복사 후 사용). 적용 시 기동 로그에 Logging reconfigured from external conf: <절대경로> 가 출력된다. 로그 레벨 변경은 모듈 config/log4j2.xml 수정 후 재시작으로 적용하며 WAR 재배포에도 보존된다. 상세는 설정 및 배포 가이드 참고.
주의: 웹앱 내부 파일(
server/webapps/ROOT/WEB-INF/classes/등)은 직접 수정하지 마라 — WAR 재배포 시 사라진다.
${ENV:기본값} 치환은 두 번 일어난다
템플릿의 ${PP_XXX} / ${PP_XXX:기본값} 표기는 두 시점에서 해석된다.
| 시점 | 주체 | 동작 |
|---|---|---|
| 배포 시 | configure.sh → TemplateProcessor.resolvePlaceholders | env.sh 로 치환. 순서는 replacements map → 환경변수 → :기본값 → 원본 유지. 중첩 placeholder 미지원 |
| 런타임 | PropertiesUtils.resolveEnvPlaceholders | 로드한 Properties 의 모든 값에 대해 ${ENV_VAR[:default]} 를 다시 해석 |
즉 배포 후 남아 있는 ${...} 도 프로세스의 환경변수로 채워질 수 있다. Docker -e VAR=... 주입이 템플릿 기본값보다 우선하는 이유다.
env.sh 에 없는 PP_* 변수 (템플릿 기본값이 그대로 적용됨)
아래 변수들은 템플릿이 ${PP_XXX:기본값} 으로 참조하지만 env.sh 가 export 하지 않는다. 따라서 별도 주입이 없으면 항상 템플릿 기본값이 쓰인다.
PP_STORAGE_PASSWORD · PP_METASTORE_PASSWORD · PP_EXTERNAL_DB_PASSWORD · PP_MAIL_SMTP_HOST · PP_MAIL_SMTP_PORT · PP_MAIL_SMTP_AUTH · PP_MAIL_SMTP_USER · PP_MAIL_SMTP_PASSWORD · PP_MAIL_SMTP_STARTTLS · PP_DIAGNOSTIC_EMAIL · PP_AI_OPENAI_CHAT_PATH · PP_AI_OPENAI_RESPONSES_PATH · PP_AI_MCP_ENABLED · PP_AI_MCP_ALLOWED_ORIGINS · PP_AI_CHAT_ENABLED
PP_MAIL_SMTP_* 는 의도적으로 export 하지 않는다. env.sh 주석이 밝히듯, export 된 환경변수가 템플릿 기본값(Brevo 릴레이 SSOT)을 덮어써 SMTP 로그인 조합이 조용히 깨진 사고가 있었다(2026-07-22, stale 25/no-auth 값이 Brevo 587/auth 값을 가림). 사이트별 오버라이드는 env.local.sh 에 둔다.
서버 관리 설정 5종
ConfigTemplates.SERVER_CONFIGS 배열이 정의하는, plantpulse-server/config/ 로 배포되는 설정 파일은 5개다.
| # | 템플릿 | 배포 경로 |
|---|---|---|
| 1 | plantpulse-engine.properties | /plantpulse-server/config/plantpulse-engine.properties |
| 2 | plantpulse-storage.properties | /plantpulse-server/config/plantpulse-storage.properties |
| 3 | plantpulse-mq.properties | /plantpulse-server/config/plantpulse-mq.properties |
| 4 | plantpulse-mail.properties | /plantpulse-server/config/plantpulse-mail.properties |
| 5 | plantpulse-ai.properties | /plantpulse-server/config/plantpulse-ai.properties |
이 중 1~4 는 PropertiesLoader.load() 가 한꺼번에 읽고(engine/mail/mq/storage), 타입드 설정 빈 EngineConfig · StorageConfig · MqConfig 를 재구성한다. 5(plantpulse-ai.properties)는 AIConfig 가 같은 외부 체인으로 따로 읽는다.
plantpulse-startup/sh/server-managed-webapp-files.list는 현재 비어 있다(주석만). 2026-06 설정 외부화 완료로 WAR 내부에 서버 관리 설정이 남아 있지 않기 때문이다.
application.properties (제거됨)
application.properties 는 2026.06 에 제거됐다. 이 파일을 읽는 코드가 없으며(전 리포 사용처 0건), 기존 항목은 다음으로 이관됐다.
- 테마 / 홈페이지 등 콘솔 동작 설정 → 콘솔 시스템 > 설정 관리 (PostgreSQL
mm_config테이블) alarm.duplicate.check.minutes→plantpulse-engine.properties계열 (EngineConfig가 읽는다)
plantpulse-engine.properties
경로: plantpulse-server/config/plantpulse-engine.properties · 템플릿: template/plantpulse-engine.properties
데이터 처리 엔진의 핵심 동작을 제어한다.
비동기 / 파이프라인
| 프로퍼티 | 기본값 | 치환 | 설명 (템플릿 주석) |
|---|---|---|---|
engine.async.parallelism | 256 | — | Async worker pool parallelism (total cores ~= 256) |
engine.pipeline.threads | 36 | — | 파이프라인 스레드 수 |
engine.pipeline.ratelimit | 40000 | — | 파이프라인 초당 처리 상한 (rate limit) |
engine.pipeline.queue.size | 1200000 | — | 파이프라인 큐 크기 (백프레셔 한계) |
engine.pipeline.queue.o3.delay | 50 | — | 순서 어긋난(out-of-order) 데이터 허용 지연 (ms) |
engine.pipeline.task.mode | SINGLE | — | 태스크 실행 모드 (SINGLE / PARALLEL) |
NTP
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
engine.ntpdate.server.ip | 127.0.0.1 | — | NTP 서버 IP |
engine.ntpdate.sync | false | — | 부팅 시 NTP 동기화 수행 여부 |
스트림 / CEP
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
engine.stream.processor | DIRECT | — | 스트림 처리 모드 (DIRECT/BUFFERED) |
engine.cep.server.ip | 127.0.0.1 | ${PP_CEP_HOST:127.0.0.1} | CEP 서버 IP |
engine.cep.server.port | 7400 | ${PP_CEP_CONNECT_PORT:7400} | CEP 서버 포트 (protocol 에 자동 정렬: http→7400, https→7401) |
engine.cep.server.protocol | http | ${PP_CEP_PROTOCOL:http} | CEP 프로토콜. 내부 통신 기본 http, 분산/컨테이너는 https |
engine.cep.server.api.key | (없음) | ${PP_CEP_API_KEY} | CEPClient X-API-Key 헤더용. CEP 서버 cep.api.key 와 일치해야 함 |
스트리밍 메시지 전달
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
engine.streaming.messaging.warning.ms | 5000 | — | 메시지 전달 지연 경고 (ms) |
engine.streaming.messaging.timeout.ms | 10000 | — | 메시지 전달 타임아웃 (ms) |
engine.streaming.messaging.timeout.store.type | FILE_QUEUE | — | 타임아웃 메시지 저장 방식 (FILE_QUEUE/MEMORY) |
engine.streaming.messaging.timeout.recovery.type | DB | — | 타임아웃 메시지 복구 소스 (DB/FILE) |
잡 워커 스레드
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
engine.job.thread.asset | 8 | — | 에셋 잡 스레드 수 |
engine.job.thread.point | 8 | — | 포인트 잡 스레드 수 |
DDS
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
engine.dds.enabled | true | — | DDS 전역 활성화 |
engine.dds.data.tag.enabled | true | — | 태그 데이터 DDS 발행 |
engine.dds.data.asset.enabled | true | — | 에셋 데이터 DDS 발행 |
이상 탐지 / 데이터플로우
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
engine.data.anomaly.enabled | false | — | 이상 탐지 활성화 (외부 서비스 연동) |
engine.data.anomaly.url | https://127.0.0.1:8970 | — | 이상 탐지 서비스 URL |
engine.dataflow.class | plantpulse.core.engine.pipeline.dataflow.BaseDataFlow | — | 데이터플로우 구현 클래스 |
engine.dataflow.server-timestamp.override | false | — | 서버 타임스탬프 강제 여부 (true: 수집 시각, false: 원본) |
engine.dataflow.negative-timestamp.override | true | — | 음수 타임스탬프 보정 여부 |
engine.factory.model.updater.class | plantpulse.core.engine.model.impl.DefaultFactoryMetaModelUpdater | — | 팩토리 메타모델 업데이터 |
engine.event.handler.class | plantpulse.core.engine.event.DefaultEventHanlder | — | 이벤트 핸들러 구현 (클래스명 오타 Hanlder 는 실제 클래스명 그대로) |
engine.javagc.enabled | false | — | 명시적 System.gc() 호출 허용 여부 |
Flow 엔진
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
flow.debug.execution.log | false | — | 노드 실행 INFO 로그. 디버깅 세션에만 true |
flow.stats.prune.interval.ms | 86400000 | — | 카운터 정리 실행 주기 (ms, 24시간). Cassandra 카운터 테이블은 default_time_to_live 를 못 쓰므로 애플리케이션 레벨로 정리 |
flow.stats.prune.hourly.days | 30 | — | tm_flow_stats_hourly 의 hour_bucket 보관 일수 |
flow.stats.prune.daily.days | 90 | — | tm_flow_stats_daily 의 day_bucket 보관 일수 |
flow.health.check.interval.ms | 600000 | — | Flow 헬스체크 주기 (ms, 10분). 현재 시각 버킷 errors > 0 이면 ERROR, 아니면 NORMAL (KST 기준) |
flow.webhook.api.key | dev-webhook-19ba7a54-1132-49f2-967e-3c6f5cd989a0 | ${PP_FLOW_WEBHOOK_API_KEY:...} | Flow 엔진 외부 웹훅 인증 |
Flow 헬스체크가 쓰는 Cassandra 테이블: tm_flow_health_status(flow_id, hour_bucket — 현재 시각 누적기), tm_flow_health_status_10m(flow_id, min10_bucket — 10분 단위 시계열).
엣지 헬스체크
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
edge.health.check.interval.ms | 600000 | — | 엣지 헬스체크 주기 (ms, 10분) |
판정 소스는 Cassandra tm_edge_status payload 의 _ON / _NORMAL 플래그다. RT REST 호출이 없어 부하가 0이고 1초 안에 끝난다. 테이블은 tm_edge_health_status(edge_id, hour_bucket), tm_edge_health_status_10m(edge_id, min10_bucket).
인증 / 보안
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
api.key | (없음) | ${PP_API_KEY} | 플랫폼 내부 API 키 (서버 ↔ 엣지 에이전트 인증) |
engine.api.v5.auth.bruteforce.enabled | true | — | V5 API 인증 브루트포스 방어 |
engine.api.v5.auth.bruteforce.ip_limit | 30 | — | IP 당 시도 한도 |
engine.api.v5.auth.bruteforce.user_limit | 10 | — | 사용자 당 시도 한도 |
engine.api.v5.auth.bruteforce.window.seconds | 60 | — | 카운팅 윈도우 (초) |
engine.api.v5.trusted_proxies | (빈 값) | — | 신뢰 프록시 IP 화이트리스트. 설정 시에만 remoteAddr 이 목록에 있을 때 X-Forwarded-For 첫 IP 를 client IP 로 사용. 비어 있으면 getRemoteAddr() 만 사용(fail-safe) |
engine.session.bruteforce.enabled | true | — | /login/login 브라우저 세션 브루트포스 방어 |
engine.session.bruteforce.ip_limit | 30 | — | IP 당 시도 한도 |
engine.session.bruteforce.user_limit | 10 | — | 사용자 당 시도 한도 |
engine.session.bruteforce.window.seconds | 300 | — | 카운팅 윈도우 (초) |
세션 브루트포스 카운터는 Caffeine 인메모리다 — 다중 노드 공유(Redis)는 미구현.
API 토큰
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
engine.api.token.cleanup.enabled | true | — | 만료(expires_at < now)/회수(revoked_at IS NOT NULL) 토큰 정리 |
engine.api.token.cleanup.retention_days | 30 | — | 이 기간 경과 후 mm_token 에서 hard delete. 매 24시간 1회(부팅 60초 후 첫 실행) |
engine.api.token.default_ttl_days | 90 | — | 신규 토큰 발급 시 기본 만료(일). 0 = 영구 토큰. 발급 요청이 ttl_days 를 주면 그 값이 우선한다 → API 토큰 발급 |
기존 expires_at 이 NULL 인 토큰은 영구 활성으로 유지된다(하위 호환).
plantpulse-storage.properties
경로: plantpulse-server/config/plantpulse-storage.properties · 템플릿: template/plantpulse-storage.properties
메타스토어(PostgreSQL) · 캐시(Valkey) · 시계열(Cassandra) · TSE · Data Gateway 접속과 스토리지 정책을 관리한다.
⚠️ 이 파일에는 오타 키가 실재한다. 3개 키가 코드가 읽는 철자와 다르다 — 오타 키 경고 절을 반드시 읽어라.
PostgreSQL 메타스토어
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
metastore.driver | org.postgresql.Driver | — | JDBC 드라이버 클래스 |
metastore.url | jdbc:postgresql://... | ${PP_POSTGRES_HOST} · ${PP_POSTGRES_PORT} · ${PP_DB_NAME} | 메타스토어 JDBC URL. 쿼리스트링 ?characterEncoding=UTF-8&reWriteBatchedInserts=true 포함 |
metastore.user | — | ${PP_PG_USER} | 메타스토어 계정 |
metastore.password | — | ${PP_PG_PASSWORD} | 메타스토어 비밀번호 |
캐시 (Valkey / Redis 호환)
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
cache.host | — | ${PP_REDIS_HOST} | 캐시 호스트 |
cache.port | — | ${PP_REDIS_PORT} | 캐시 포트 (내부 plaintext Valkey backend) |
cache.password | — | ${PP_REDIS_PASSWORD} | 캐시 비밀번호 |
cache.ssl.enabled | false | — | 캐시 TLS. 내부 클라이언트는 redis:// 기본 |
cache.ssl.truststore.location | /var/security/plantpulse/master/master.truststore.p12 | — | 트러스트스토어 경로 |
cache.ssl.truststore.password | kopens123! | ${PP_TLS_TRUSTSTORE_PASSWORD:kopens123!} | 트러스트스토어 비밀번호 |
cache.ssl.truststore.type | PKCS12 | — | 트러스트스토어 타입 |
cache.ssl.endpoint.identification.enabled | false | — | 엔드포인트 식별 검증 |
키 상수 정본은 plantpulse-inmemory 의 InMemoryConfigKeys 다.
TSE (TimeSeries Engine)
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
tse.protocol | http | ${PP_TSE_PROTOCOL:http} | TSE 프로토콜. 내부 통신이라 평문 http 기본 (2026-08) |
tse.host | — | ${PP_TSE_HOST} | TSE 호스트 |
tse.port | 7800 | ${PP_TSE_CONNECT_PORT:7800} | TSE 포트. 평문 리스너 7800 기본 |
tse.user | tse | ${PP_TSE_USER:tse} | TSE 계정 |
tse.password | tse123! | ${PP_TSE_PASSWORD:tse123!} | TSE 비밀번호 |
Cassandra 시계열 저장소
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
storage.db_type | CASSANDRA | — | DB 종류 (템플릿 주석은 CASSANDRA/DSE/SCYLLADB 로 남아 있으나 현재 Cassandra 5.0 전용) |
storage.db_version | 5.0 | — | DB 버전 (드라이버/기능 호환 결정) |
storage.host | — | ${PP_CASSANDRA_HOST} | contact point 호스트 |
storage.port | 9042 | ${PP_STORAGE_PORT:9042} | native 프로토콜 포트 |
storage.keyspace | — | ${PP_KEYSPACE} | 사용 keyspace |
storage.user | — | ${PP_CASSANDRA_USER} | 접속 계정 |
storage.password | cassandra | ${PP_STORAGE_PASSWORD:cassandra} | 비밀번호. PP_STORAGE_PASSWORD 는 env.sh 미export → 기본값 적용 |
storage.durable_writes | true | — | commit log 사용 여부 (⚠️ 읽는 코드 없음 — 아래 참고) |
storage.append_columns | [] | — | 사용자 정의 컬럼 자동 추가 |
storage.replication | { 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 1 } | — | 복제 전략 (단일 노드 기본) |
storage.data.disk.name | — | ${PP_DATA_DISK_NAME} | 데이터 디스크 이름 |
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 | 10 SECONDS | 매 사이클 전 자산의 태그맵(data_map)을 asset_data 계열(data/second/timestamp + 분/시/일 경계)에 기록 |
템플릿 주석이 근거를 밝히고 있다: 1 SECONDS 는 자산 121 기준 분당 약 22K 쓰기(Cassandra 전체의 약 4%)로 과밀했다. 태그 원본(초 단위)은 tm_tag_point/TSE 에 완전 보존되므로 자산 뷰 스냅샷은 10s(코드 기본값과 일치)로 낮췄다 — 쓰기 −90%, 기록 완전성 유지.
이 값은 스케줄러의
ASSET_DATA_JOB주기가 된다."<수> <단위>"2토큰 형식이어야 하며 규칙은 스케줄러 아키텍처 참고.
내부 메타스토어 동기화 (실험적)
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
storage.internal.metastore.enabled | false | 내부 메타스토어 동기화 활성화 |
storage.internal.metastore.thread.count | 4 | 동기화 워커 스레드 수 |
storage.internal.metastore.queue.size | 12000000 | 동기화 큐 크기 |
storage.internal.metastore.point.retation.days | 10 | 포인트 보관 일수 (⚠️ 오타 키 — 아래 참고) |
행 캐시
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
storage.asset.data.row.cache.size | NONE | 에셋 데이터 행 캐시 (NONE/ROWS_ONLY/ALL) — ⚠️ 읽는 코드 없음 |
storage.tag.point.row.cache.size | NONE | 태그 포인트 행 캐시 — ⚠️ 읽는 코드 없음 |
Compaction
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
storage.table.compaction.strategy | UCS | 기본 전략 (TWCS: TimeWindow, UCS: Unified). CassandraCreateDAO 가 읽는다(코드 fallback 은 TWCS) |
storage.table.compaction.strategy.twcs.window_size | 1 | TWCS 윈도우 크기 — ⚠️ 읽는 코드 없음 |
storage.table.compaction.strategy.twcs.window_unit | DAYS | TWCS 윈도우 단위 — ⚠️ 읽는 코드 없음 |
storage.table.compaction.strategy.ucs.scailing_parameter | T8 | UCS 스케일링 파라미터 (T8 = tiered 8 levels). 키 철자 scailing 은 코드와 일치 |
storage.table.compaction.strategy.ucs.min_sstable_size | 128MiB | UCS 최소 sstable 크기 (코드 fallback 100MiB) |
storage.table.compaction.strategy.ucs.target_sstable_size | 512MiB | UCS 목표 sstable 크기 |
storage.table.compaction.strategy.ucs.base_shard_count | 8 | UCS base shard 수 |
storage.table.compaction.strategy.ucs.max_sstables_to_compact | 6 | 한 번에 compaction 할 최대 sstable 수 |
storage.table.compaction.strategy.ucs.sstable_growth | 0.7 | UCS sstable 증가 비율 |
압축 / 쿼리 한도 / 백업 / Data Gateway
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
storage.compresion.zstd.level | 3 | — | zstd 압축 레벨 (1~22) — ⚠️ 오타 키, 아래 참고 |
storage.tag.point.select.limit.size | 1000000 | — | 단일 태그 포인트 select 최대 행 수 |
storage.doamin.model.changed.to.metastore.backup | true | — | 도메인 모델 변경 시 메타스토어 백업 — ⚠️ 오타 키 + 읽는 코드 없음 |
data.gateway.protocol | http | ${PP_DATA_GATEWAY_PROTOCOL:http} | Data Gateway 프로토콜 |
data.gateway.host | 127.0.0.1 | ${PP_DATA_GATEWAY_HOST:127.0.0.1} | Data Gateway 호스트 (로컬 동거 전제) |
data.gateway.port | 5500 | ${PP_DATA_GATEWAY_CONNECT_PORT:5500} | Data Gateway 포트 (코드 fallback 5501) |
data.gateway.api.key | — | ${PP_DATA_GATEWAY_API_KEY} | Data Gateway API 키 |
⚠️ 오타 키 — 편집해도 무시된다
템플릿에 실제로 존재하는 아래 3개 키는 코드가 읽는 철자와 다르다. 관리자가 이 줄의 값을 바꿔도 조용히 무시되고 코드 기본값이 적용된다.
| 템플릿의 키 (오타) | 코드가 실제로 읽는 키 | 코드 기본값 | 읽는 위치 |
|---|---|---|---|
storage.compresion.zstd.level | storage.compression.zstd.level | 3 | StorageConfig → CassandraCreateDAO |
storage.internal.metastore.point.retation.days | storage.internal.metastore.point.retention.days | 10 | StorageConfig → PointDAO |
storage.doamin.model.changed.to.metastore.backup | 없음 (올바른 철자로도 읽는 코드가 없다) | — | — |
값을 실제로 바꾸려면 코드 철자의 키를 같은 파일에 추가하라. 예를 들어 zstd 레벨을 6으로 올리려면
storage.compression.zstd.level=6을 넣어야 한다(오타 키를 고쳐 쓰는 것이 아니라 올바른 철자 줄을 추가). 오타 줄은 남겨 두어도 무해하지만, 템플릿 자체를 고치는 편이 근본 해법이다.
storage.doamin.model.changed.to.metastore.backup은 어느 철자로도 읽는 코드가 없다. 도메인 모델 변경 시 백업은 이 키가 아니라MetastoreBackupDeployer(cron0 0 12 1 1/1 ? *, 매월 1일 12:00)가 담당한다 — 스케줄러 아키텍처 참고.
템플릿에는 없지만 코드가 읽는 storage 키
| 프로퍼티 | 코드 기본값 | 설명 |
|---|---|---|
storage.compression.zstd.type | ZstdCompressor | 압축기 클래스명 |
읽는 코드가 없는 storage 템플릿 키 (편집해도 무효)
storage.durable_writes · storage.asset.data.row.cache.size · storage.tag.point.row.cache.size · storage.table.compaction.strategy.twcs.window_size · storage.table.compaction.strategy.twcs.window_unit (+ 위 오타 키 3개)
TWCS 관련 두 키는 storage.table.compaction.strategy=TWCS 로 바꾸더라도 윈도우 크기/단위를 제어하지 못한다.
plantpulse-mq.properties
경로: plantpulse-server/config/plantpulse-mq.properties · 템플릿: template/plantpulse-mq.properties
Kafka / MQTT 브로커 접속과 DDS 발행 토픽을 관리한다. 코드 측 SSOT 는 MqConfig(접속) 와 UNSTopicDefaults(토픽)다.
브로커 접속
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
mq.host | — | ${PP_KAFKA_HOST} | 브로커 호스트 (Kafka/MQTT 공용) |
mq.user | — | ${PP_MQ_USER} | 브로커 관리 계정 |
mq.password | — | ${PP_MQ_PASSWORD} | 브로커 비밀번호 |
mq.kafka.port | 9092 | ${PP_KAFKA_PORT:9092} | Kafka 포트 |
mq.kafka.security.protocol | SASL_PLAINTEXT | — | Kafka 보안 프로토콜 |
mq.ssl.truststore.location | /var/security/plantpulse/master/master.truststore.p12 | — | 메시징 TLS 트러스트스토어 (MQTT + 선택적 Kafka TLS) |
mq.ssl.truststore.password | kopens123! | ${PP_TLS_TRUSTSTORE_PASSWORD:kopens123!} | 트러스트스토어 비밀번호 |
mq.ssl.truststore.type | PKCS12 | — | 트러스트스토어 타입 |
mq.ssl.endpoint.identification.algorithm | (빈 값) | — | 호스트명 검증 알고리즘 (빈 값 = 검증 안 함) |
mq.mqtt.port | — | ${PP_MQTT_TLS_PORT} | MQTT 접속 포트 |
mq.mqtt.ssl.enabled | true | — | MQTT TLS 사용 |
MqConfig 는 위 키 외에 Kafka 전용 트러스트스토어 오버라이드 mq.kafka.ssl.truststore.location / .password / .type 과 mq.kafka.ssl.endpoint.identification.algorithm 도 읽는다(템플릿에는 없고, 없으면 mq.ssl.* 를 쓴다).
DDS 토픽
Kafka 14종(mq.dds.kafka.topic.*) + MQTT UNS 14종(mq.dds.mqtt.topic.*) + SparkplugB 2종(mq.dds.mqtt.sparkplugb.*).
키·기본값 전량은 메시징 아키텍처 → DDS 발행 토픽 에 정리돼 있다. 토픽 값은 Kafka/MQTT 와이어 계약이고 UNSTopicDefaultsContractTest 가 리터럴을 동결하므로 임의 변경 금지.
${PP_TOPIC_PREFIX} 가 Kafka 토픽의 접두(pp-)와 MQTT UNS 경로의 루트(pp/), SparkplugB 그룹 ID 를 동시에 결정한다.
plantpulse-mail.properties
경로: plantpulse-server/config/plantpulse-mail.properties · 템플릿: template/plantpulse-mail.properties
알람/리포트 발송용 SMTP·SMS 설정이다.
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
mail.send.enabled | false | ${PP_MAIL_SEND_ENABLED:false} | 마스터 발송 게이트. true 가 아니면 모든 메일 발송이 WARN 로그만 남기고 skip 된다(SMTP 시도 자체를 안 한다). 사이트별 opt-in |
mail.smtp.host | smtp-relay.brevo.com | ${PP_MAIL_SMTP_HOST:...} | SMTP 호스트 |
mail.smtp.port | 587 | ${PP_MAIL_SMTP_PORT:587} | SMTP 포트 (25:plain, 465:SSL, 587:STARTTLS) |
mail.smtp.auth | true | ${PP_MAIL_SMTP_AUTH:true} | SMTP 인증 사용 여부 |
mail.smtp.user | b2df89001@smtp-brevo.com | ${PP_MAIL_SMTP_USER:...} | SMTP 발신 계정 |
mail.smtp.password | bskHIVJqcFQaFtb | ${PP_MAIL_SMTP_PASSWORD:...} | SMTP 비밀번호 (dev 기본값 — 납품 시 교체) |
mail.smtp.starttls.enable | true | ${PP_MAIL_SMTP_STARTTLS:true} | STARTTLS 사용 여부 |
sms.sender.class | plantpulse.cep.listener.alarm.sms.DefaultSMSSender | — | SMS 발송 구현 클래스 (CEP 리스너) |
diagnostic.log.email | diag@kopens.com | ${PP_DIAGNOSTIC_EMAIL:diag@kopens.com} | 진단 알림 수신 메일 — ⚠️ 읽는 코드 없음 |
PP_MAIL_SMTP_*는env.sh가 export 하지 않는다. 이 템플릿(Brevo 릴레이)이 SSOT 이고, 환경변수로 덮어쓰면 로그인 조합이 조용히 깨진다. 사이트 오버라이드는env.local.sh에 둔다. 자세한 배경은 치환 절 참고.
plantpulse-ai.properties
경로: plantpulse-server/config/plantpulse-ai.properties · 템플릿: template/plantpulse-ai.properties
OpenAI 호환 AI 게이트웨이와 AI 기능 플래그를 관리한다. 코드 측은 plantpulse.core.service.ai.AIConfig 가 같은 외부 설정 체인으로 읽는다.
게이트웨이
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
ai.openai.enabled | false | ${PP_AI_OPENAI_ENABLED:false} | 마스터 기능 플래그. false 면 AI UI·엔드포인트가 숨겨지고 비활성화된다 |
ai.openai.base.url | https://api.openai.com | ${PP_AI_OPENAI_BASE_URL:...} | OpenAI 호환 게이트웨이. 끝 슬래시 금지 |
ai.openai.chat.path | /v1/chat/completions | ${PP_AI_OPENAI_CHAT_PATH:...} | chat completions 경로 |
ai.openai.responses.path | /v1/responses | ${PP_AI_OPENAI_RESPONSES_PATH:...} | responses 경로 |
ai.openai.api.key | (빈 값) | ${PP_AI_OPENAI_API_KEY:} | LiteLLM 가상 키 / 프록시 키. 리포지토리 기본값 없음 |
ai.openai.model | gpt-5-mini | ${PP_AI_OPENAI_MODEL:gpt-5-mini} | LiteLLM config.yaml 이 노출하는 모델명 |
ai.openai.timeout.ms | 15000 | — | 요청 타임아웃 (ms) |
ai.openai.max.output.tokens | 1200 | — | 최대 출력 토큰 |
ai.openai.temperature | -1 | — | 샘플링 temperature. 음수면 요청 body 에서 파라미터를 아예 생략한다 |
⚠️
ai.openai.temperature함정. gpt-5 계열(gpt-5-mini,gpt-5.5등)은 temperature 를 지원하지 않아 기본값 1 외의 값을 보내면400 Unsupported value가 난다. 그래서 음수(생략 sentinel)로 두어야 한다. 템플릿 주석의 "기본값 0.1" 언급은 LiteLLM/vLLM 게이트웨이(gpt-4o 등) 기준이고, 현재 템플릿의 실제 값은-1이다.
운영 어시스턴트
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
ai.alarm.rca.enabled | true | 알람 근본원인 분석 |
ai.alarm.eql.enabled | true | 알람 EQL 보조 |
ai.uns.topic.enabled | true | UNS 토픽 어시스트 |
ai.result.audit.enabled | true | AI 결과 감사 |
ai.similar.incident.enabled | true | 유사 장애 사례 추천 |
ai.similar.incident.max.items | 5 | 추천 최대 건수 |
ai.similar.incident.min.score | 40 | 추천 최소 점수 |
ai.diagnostic.summary.* 3개(진단 로그 AI 요약)와 ai.operations.report.* 3개(AI 운영
리포트)는 2026-08-25 제품에서 제거되었습니다. 화면·JS·컨트롤러까지 함께 걷어냈으므로
값을 되돌려도 기능이 살아나지 않습니다.
업그레이드 전 설정 파일에 이 키들이 남아 있어도 해가 되지는 않습니다 — 읽는 코드가 없어 그냥 무시됩니다. 정리하고 싶으면 지우셔도 됩니다.
MCP / 채팅
| 프로퍼티 | 기본값 | 치환 | 설명 |
|---|---|---|---|
ai.mcp.enabled | true | ${PP_AI_MCP_ENABLED:true} | MCP (AI chat-ops 엔드포인트) |
ai.mcp.allowed.origins | (빈 값) | ${PP_AI_MCP_ALLOWED_ORIGINS:} | MCP 허용 Origin 목록 |
ai.chat.enabled | false | ${PP_AI_CHAT_ENABLED:false} | server-web 콘솔 AI 채팅 drawer. ai.openai.* 게이트웨이가 켜져 있어야 동작 |
그 외 템플릿
template/ 에는 위 5종 외에도 애플리케이션·인프라 설정 템플릿이 있다. 배포 경로 매핑 정본은 ConfigTemplates.java 다.
| 템플릿 | 배포 경로 | 용도 |
|---|---|---|
plantpulse-batch.properties | /plantpulse-batch/config/ | 배치(시계열 동기/집계) |
plantpulse-cep.properties | /plantpulse-cep/config/ | CEP 엔진 |
plantpulse-jdbc.properties | /plantpulse-data-gateway/config/ 및 /plantpulse-sql/config/ | JDBC 통합 설정 (두 모듈이 같은 템플릿을 공유) |
plantpulse-data-gateway.properties | /plantpulse-data-gateway/config/ | Data Gateway 동작 |
plantpulse-warehouse.properties | /plantpulse-warehouse/config/ | Cassandra → Iceberg(S3) 아카이브 |
plantpulse-monitor.properties | /plantpulse-monitor/config/ | 모니터(JMX 수집) |
plantpulse-plugin-opcua.properties | /plantpulse-plugin/opc-ua/config/ | OPC UA 서버 플러그인 |
plantpulse-plugin-aas.properties | /plantpulse-plugin/aasx-server/config/ | AAS V3 (aasx-server) 플러그인 |
kafka.properties | /plantpulse-messaging/kafka/config/kafka.properties | Kafka(KRaft) 브로커 |
kafka-jaas.conf | /plantpulse-messaging/kafka/config/jaas.conf | Kafka JAAS |
hivemq.xml | /plantpulse-messaging/mqtt/conf/config.xml | HiveMQ 브로커 |
plantpulse-mq-auth.properties | /plantpulse-messaging/mqtt/conf/auth.properties | HiveMQ 인증 소스 |
hive-auth.properties | /plantpulse-analytics/spark/conf/ | Hive/분석 계정 인증 소스 |
plantpulse-timeseries-engine.conf | /plantpulse-timeseries/engine/conf/ (2곳) | TSE |
valkey.conf · postgresql.conf · pg_hba.conf · cassandra.yaml · jvm-server.options | /plantpulse-storage/... | 스토리지 |
spark-env.sh · spark-defaults.conf · hive-site.xml · kyuubi-defaults.conf · gravitino-iceberg-rest-server.conf | /plantpulse-analytics/... | 분석 |
workflow.yaml · application.yaml | /plantpulse-workflow/... | Temporal / Kestra |
plantpulse-startup.properties | (startup 자체 사용) | 부팅 시 데이터레이크 헬스체크 접속 정보 |
plantpulse-sql.properties는 존재하지 않는다. SQL 모듈은plantpulse-jdbc.properties를 받는다.plantpulse-websocket.properties도 존재하지 않는다. WebSocket/STOMP 계열 설정 파일은 없다.template/cluster/는 워커 노드 전용 오버라이드다 — master 템플릿을 고치면 여기도 동기화해야 한다.
plantpulse-batch.properties
접속 블록(플랫폼/메타스토어/캐시/TSE/Kafka/Cassandra/Spark)과 배치 동작 설정으로 구성된다. 접속 키는 storage/jdbc 와 이름이 다르니 주의 — 예: Cassandra 는 storage.db.host / storage.db.port / storage.db.keyspace (server 는 storage.host / storage.port / storage.keyspace).
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
platform.host | ${PP_MASTER_IP} | 플랫폼(server-web) 호스트 |
mq.port | 9092 | Kafka 포트 (리터럴 — 치환 아님) |
kafka.topic | pp-batch | 배치 인입 토픽 |
kafka.group.id | PP-BATCH-GROUP | 배치 컨슈머 그룹 |
batch.timer_schedule_delay | 5000 | 배치 타이머 주기 (ms) |
batch.thread_pool_batch_thread_size | 4 | 배치 워커 스레드 수 |
batch.buffer_drain_limit_size | 10000 | 한 번에 비우는 최대 건수 |
batch.sync.inmemory.enabled | false | 인메모리 동기화 |
batch.sync.inmemory.ttl.minute | 10 | 인메모리 동기화 TTL (분) |
batch.sync.tse.enabled | true | TSE 로 분배 |
batch.sync.external.db.enabled | false | 외부 DB 동기화 |
external.db.name | TIMESCALEDB | 외부 DB 종류. INFLUXDB/QUESTDB 블록은 템플릿에 주석 상태로 있다 |
analytics.url | jdbc:spark://${PP_SPARK_HOST}:${PP_KYUUBI_PORT}/default | Spark Thrift JDBC |
plantpulse-cep.properties
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
cep.ha.enabled | true | Redis 기반 HA 킬스위치 (재시작 시 배포/named window/단일키 테이블 상태 보존) |
cep.ha.snapshot.interval_ms | 1000 | 스냅샷 주기 (이벤트 스레드 비차단 백그라운드) |
cep.ha.snapshot.named_windows | true | named window 스냅샷 |
cep.ha.snapshot.tables | true | 테이블 스냅샷 |
cep.async.core_pool_size | 32 | 비동기 코어 풀 |
cep.async.max_pool_size | 256 | 비동기 최대 풀 |
cep.async.queue_capacity | 50000 | 비동기 큐 |
cep.async.keep_alive_seconds | 60 | 스레드 keep-alive |
cep.async.shutdown_timeout_seconds | 30 | graceful shutdown 대기 |
cep.consumer.thread_count | 16 | 컨슈머 스레드 |
cep.stream.shard_count | 16 | 스트림 샤드 수 |
cep.stream.drain_limit_size | 1000 | 드레인 한도 |
cep.stream.drain_warn_ms | 1000 | 드레인 경고 (ms) |
cep.monitor.initial_delay_seconds | 5 | 모니터 최초 지연 |
cep.monitor.interval_seconds | 1 | 모니터 주기 |
cep.monitor.store_interval_seconds | 60 | EQL 문장별 메트릭 Cassandra 저장 주기 |
cep.monitor.statement_metrics_enabled | true | 문장별 메트릭 수집 |
cep.performance.cpu_warn_threshold_ns | 1000000000 | CPU 경고 임계 (ns) |
cep.performance.wall_warn_threshold_ns | 1000000000 | wall 경고 임계 (ns) |
cep.api.key | ${PP_CEP_API_KEY} | EQL 관리 엔드포인트 인증 (X-API-Key) |
cep.api.max_eql_text_length | 100000 | EQL 텍스트 최대 길이 (DOS 방어) |
cep.storage.request_timeout_seconds | 10 | Cassandra 요청 타임아웃 |
cep.storage.max_inflight_writes | 256 | 인플라이트 쓰기 상한 |
cep.storage.connect_max_retries | 3 | 접속 재시도 |
cep.storage.ttl_seconds | 864000 | 메트릭 TTL (초, 10일) |
cep.stream.pending_idle_threshold_ms | 60000 | pending 유휴 임계 |
cep.stream.cleaner_initial_delay_ms | 60000 | 클리너 최초 지연 |
cep.stream.cleaner_interval_ms | 10000 | 클리너 주기 |
cep.stream.max_clean_duration_ms | 30000 | 클린 최대 소요 |
cep.stream.cleaner_max_claim_count | 5000 | 클레임 최대 건수 |
cep.stream.ack_chunk_size | 500 | ACK 청크 크기 |
cep.monitor.store_interval_seconds 의 60 은 근거가 있다 — 문장 수(자산×EMS/알람 룰, dev 실측 1,263개)에 비례해 쓰기가 발생해 10s 에서는 분당 7.6K 행이었다. 온디맨드 조회 전용이라 60s 로 완화(−83%)했다.
HA 전용 Redis 접속(cep.ha.redis.host/port/password)은 템플릿에 주석 상태로 있다 — 캐시와 다른 Redis 를 쓸 때만 해제한다.
plantpulse-jdbc.properties
외부 JDBC 클라이언트(SQL 모듈 · Data Gateway)의 통합 접속 설정이다. 프리픽스는 jdbc.<tech> (postgres/cassandra/spark/tse).
| 프로퍼티 | 값 | 설명 |
|---|---|---|
jdbc.postgres.driver | org.postgresql.Driver | META / PQL |
jdbc.postgres.url | jdbc:postgresql://${PP_POSTGRES_HOST}:${PP_POSTGRES_PORT}/${PP_DB_NAME}?characterEncoding=UTF-8 | |
jdbc.cassandra.driver | plantpulse.cassandra.jdbc.CassandraDriver | OLTP 시계열(CQL). 드라이버 값은 설정 일관성용(기능상 미사용) |
jdbc.cassandra.url | jdbc:cassandra://${PP_CASSANDRA_HOST}:${PP_CASSANDRA_PORT}/${PP_SCHEME} | |
jdbc.tse.driver | plantpulse.timeseries.tql.TQLDriver | OTAP / TQL |
jdbc.tse.url | jdbc:ts://${PP_TSE_HOST}:${PP_TSE_PORT}/${PP_SCHEME} | ⚠️ plain http(ts/7800) 고정 |
jdbc.spark.driver | plantpulse.spark.jdbc.SparkSQLDriver | OLAP 분석 |
jdbc.spark.url | jdbc:spark://${PP_SPARK_HOST}:${PP_KYUUBI_PORT}/default/${PP_SCHEME} | |
data.gateway.api.key | ${PP_DATA_GATEWAY_API_KEY} | JDBC 호출 인증용 |
⚠️
jdbc.tse.url을 https(tss/7801)로 바꾸지 마라. TQL JDBC 드라이버는 평문 TSE 리스너(7800)를 쓴다. TSE 클라이언트는 전역적으로 평문 http/7800 이 기본이다(2026-08, env.sh TSE 섹션). tss/7801 로 잡히면 JDBC 접속 실패 → data-gateway 부팅 실패 →/api/v1/*전부 404 → analytics 카탈로그 404 로 이어진다. 그래서ts/PP_TSE_PORT로 핀 고정돼 있다.
jdbc.spark.username은 분석 전용 계정${PP_ANALYTICS_USER}다. Kyuubi 내부 메타스토어 계정(PP_HIVE_*)과 분리돼 있다. 선택 키로jdbc.<tech>.pool.initial|min|max(postgres/spark/tse),jdbc.<tech>.query.timeout|fetch-size를 쓸 수 있다(전체 레퍼런스는plantpulse-jdbc/docs/configuration.md).jdbc.cassandra.local-datacenter는 템플릿에 주석 상태이며 미설정 시datacenter1이다.
plantpulse-data-gateway.properties
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
data.gateway.api.key | ${PP_DATA_GATEWAY_API_KEY:ADFA-URDV-QWED-1234} | API 인증 키 (필수). dev 기본값은 납품 시 교체 |
data.gateway.rate.limit | 1000 | 초당 최대 요청 수 (IP + API 키 기준) |
data.gateway.slow.query.ms | 10000 | 느린 조회 경고 임계 (ms) |
data.gateway.slow.update.ms | 2000 | 느린 갱신 경고 임계 (ms) |
data.gateway.async.timeout.ms | 60000 | 비동기 타임아웃 (ms) |
plantpulse-monitor.properties
단일 노드(type=MASTER) 기준 각 서비스의 JMX/관리 엔드포인트 모음이다. 키에 점(.)이 아니라 언더스코어(_) 를 쓰는 유일한 파일이다.
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
type | MASTER | 단일 노드 또는 클러스터 마스터 |
db_type | CASSANDRA | 모니터링 대상 DB 종류 |
master / host | ${PP_MASTER_IP} / ${PP_HOST_IP} | 마스터 / 자기 호스트 |
db_host · db_port · db_keyspace · db_username · db_password · db_replication_factor | ${PP_CASSANDRA_*} · 9042 · ${PP_SCHEME} · 1 | Cassandra 접속 |
tse_host · tse_port · tse_protocol · tse_username · tse_password | ${PP_TSE_*} · 7801 · https · tse · tse123! | TSE 접속(메트릭 적재) |
kafka_jmx_uri | service:jmx:rmi:///jndi/rmi://${PP_KAFKA_HOST}:7299/jmxrmi | Kafka JMX |
mqtt_jmx_uri | ...://${PP_MQTT_HOST}:7279/jmxrmi | HiveMQ JMX |
cep_jmx_uri | ...://${PP_HOST_IP}:6499/jmxrmi | CEP JMX |
datagateway_jmx_uri | ...://${PP_HOST_IP}:7499/jmxrmi | Data Gateway JMX |
sql_jmx_uri | ...://${PP_HOST_IP}:7599/jmxrmi | SQL JMX |
tse_jmx_uri | ...://${PP_HOST_IP}:7899/jmxrmi | TSE JMX |
cassandra_jmx_uri | ...://${PP_CASSANDRA_HOST}:7199/jmxrmi | Cassandra JMX |
spark_jmx_uri | ...://${PP_SPARK_HOST}:10010/jmxrmi | Spark JMX |
redis_jmx_uri | redis://${PP_REDIS_HOST}:${PP_REDIS_PORT}?password=... | Valkey 접속 URI |
redis_ssl_truststore_location / _password / _type / redis_ssl_endpoint_identification_enabled | p12 · ${PP_TLS_TRUSTSTORE_PASSWORD:kopens123!} · PKCS12 · false | Valkey TLS |
postgres_jmx_uri | jdbc:postgresql://.../${PP_DB_NAME}?user=...&password=... | PostgreSQL 접속 URI |
JMX 포트 요약: HiveMQ 7279, Kafka 7299, CEP 6499, Data Gateway 7499, SQL 7599, TSE 7899, Cassandra 7199, Spark 10010.
plantpulse-warehouse.properties
Cassandra → Iceberg(S3) 아카이브 배치. 이 파일만 키가 대문자 스네이크(UPPER_SNAKE) 다.
| 그룹 | 주요 키 | 기본값 |
|---|---|---|
| Temporal | TEMPORAL_SERVER · TEMPORAL_TASK_QUEUE · TEMPORAL_WORKFLOW_ID · TEMPORAL_SCHEDULE_ID · OPTIMIZER_SCHEDULE_ID · OPTIMIZER_WORKFLOW_ID | ${PP_TEMPORAL_HOST}:${PP_TEMPORAL_PORT} · PP-S3-QUEUE · PP-S3-ARCHIVE-DAILY-WORKFLOW · PP-S3-ARCHIVER-DAILY · PP-S3-OPTIMIZER-WEEKLY · PP-S3-OPTIMIZER-WEEKLY-WORKFLOW |
| 스케줄 | DAILY_HOUR · DAILY_MINUTE · OPTIMIZER_DAY_OF_WEEK · OPTIMIZER_HOUR · OPTIMIZER_MINUTE · TIMEZONE | 2 · 20 · 0(일요일) · 3 · 0 · ${PP_TZ} |
| 실행 모드 | ARCHIVER_MODE | SHELL (또는 KESTRA) |
| Kestra | KESTRA_SERVER · KESTRA_NAMESPACE · KESTRA_TASK_ID · KESTRA_USER · KESTRA_PASS | ${PP_KESTRA_HOST}:${PP_KESTRA_PORT} · plantpulse · plantpulse-daily-s3-archiver · admin@plantpulse.io · (빈 값) |
| 스크립트 | S3_SCRIPT_DIR · S3_SCRIPT_NAME · S3_OPTIMIZER_SCRIPT_NAME | ${PP_HOME}/plantpulse-warehouse/s3 · archive.sh · optimize.sh |
| Spark | SPARK_APP_NAME · SPARK_MASTER · SPARK_JAR_PATH · SPARK_DRIVER_MEMORY · SPARK_EXECUTOR_MEMORY · SPARK_EXECUTOR_CORES · SPARK_NUM_EXECUTORS · ARCHIVER_PARALLELISM · SPARK_CHECKPOINT_DIR | PP-SPARK-S3-LAKEHOUSE · local[*] · .../plantpulse-warehouse-s3.jar · 2g · 4g · 4 · 3 · 4 · s3a://${PP_MINIO_BUCKET:-plantpulse}/spark-checkpoint/ |
| 소스/타깃 | CASSANDRA_CATALOG · CASSANDRA_DATABASE · S3_BUCKET · ICEBERG_CATALOG · ICEBERG_DATABASE | cassandra · ${PP_SCHEME:pp} · ${PP_MINIO_BUCKET:-plantpulse} · spark_catalog · ${PP_SCHEME:pp} |
| 최적화 | SNAPSHOT_RETENTION_DAYS · OPTIMIZER_MIN_INPUT_FILES · OPTIMIZER_TARGET_FILE_SIZE_BYTES | 3 · 10 · 134217728 (128MB) |
| 타임아웃 | ARCHIVER_WF_EXECUTION/RUN/TASK_TIMEOUT_HOURS · OPTIMIZER_WF_EXECUTION/RUN/TASK_TIMEOUT_HOURS · ACTIVITY_MAX_ATTEMPTS · ACTIVITY_TIMEOUT_HOURS · OPTIMIZER_ACTIVITY_TIMEOUT_HOURS · SCRIPT_TIMEOUT_SECONDS · OPTIMIZER_TIMEOUT_SECONDS · HEARTBEAT_INTERVAL_SECONDS | 12/12/12 · 8/7/12 · 3 · 12 · 8 · 21600(6h) · 25200(7h) · 60 |
| 웹 | WEB_SERVER_PORT | 9600 |
메시징 / 인증 소스 템플릿
plantpulse-mqtt.properties — HiveMQ 브로커 설정.
| 프로퍼티 | 기본값 |
|---|---|
mqtt.host · mqtt.user · mqtt.password | ${PP_MQTT_HOST} · ${PP_MQ_USER} · ${PP_MQ_PASSWORD} |
mqtt.port · mqtt.ssl.enabled | ${PP_MQTT_TLS_PORT} · true |
mqtt.websocket_port | 8888 |
mqtt.data_dir | /data1/pp-data/hivemq |
plantpulse-mq-auth.properties — HiveMQ security extension(FileAuthAuthenticator)이 HIVEMQ_AUTH_FILE 환경변수로 가리키는 인증 소스. 키는 mqtt.user / mqtt.password 둘뿐이다.
hive-auth.properties — plantpulse-hive-auth(PasswordAuthenticator)가 읽는다. HIVE_AUTH_FILE 환경변수 또는 $PP_HOME/plantpulse-analytics/spark/conf/hive-auth.properties. 키 이름 자체가 placeholder 라는 점이 특이하다.
${PP_HIVE_USER}=${PP_HIVE_PASSWORD}
${PP_ANALYTICS_USER}=${PP_ANALYTICS_PASSWORD}
kafka.properties — KRaft 모드 Kafka 브로커. 주요 값: process.roles=broker,controller, node.id=1, num.partitions=4, 리스너 3종(SASL_PLAINTEXT/CONTROLLER/SASL_SSL), sasl.enabled.mechanisms=PLAIN, super.users=User:admin, allow.everyone.if.no.acl.found=false, log.dirs=${PP_DATA_DIR}/kafka/kraft_combined_logs, log.retention.ms=3600000(1시간), message.max.bytes=157286400, default.replication.factor=1, auto.create.topics.enable=true.
⚠️
log.retention.ms=3600000= 1시간. Kafka 는 버퍼 역할이고 영속화는 Cassandra/TSE 가 맡는다는 전제다. 컨슈머가 1시간 이상 멈추면 데이터가 유실된다.
플러그인 템플릿
plantpulse-plugin-opcua.properties — PostgreSQL / Cassandra / Valkey / Kafka 접속 + OPC UA 서버 엔드포인트.
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
kafka.topic | pp-tag-point | ⚠️ 리터럴 — ${PP_TOPIC_PREFIX} 치환이 아니다 |
kafka.thread · kafka.group.id | 8 · opcua-plugin-group | |
opc.ua.server.domain · opc.ua.server.port | ${PP_HOST_IP} · 8007 | |
opc.ua.server.user · password · anonymous | opcua · 설치-시-변경 · false | |
opc.ua.server.tcp.port · tls.port | ${PP_OPCUA_TCP_PORT:11004} · ${PP_OPCUA_TLS_PORT:11005} | |
redis.thread · redis.ssl.enabled | 4 · false |
plantpulse-plugin-aas.properties — AAS V3 서버 + Kafka 소비 설정.
| 프로퍼티 | 기본값 | 설명 |
|---|---|---|
aas.v3.port | ${PP_AAS_V3_PORT:8090} | V3 HTTP 포트 |
kafka.topic | ${PP_TOPIC_PREFIX}-tag-point | 실시간 태그 포인트 수신 |
kafka.thread · kafka.poll.count | 8 · 1000 | |
group.id · auto.offset.reset · enable.auto.commit | pp-plugin-aas-server · earliest · false | |
session.timeout.ms · auto.commit.interval.ms | 30000 · 1000 | |
plugin.message.listener | plantpulse.plugin.opcua.messaging.KafkaPluginMessageListener |
BaSyx V2 의 registry/AAS 포트는 설정이 아니라 코드 하드코딩이다 —
AASServer.java의REGISTRY_PORT=4800,AAS_PORT=4801.
plantpulse-startup.properties
부팅 시 Checker 가 데이터레이크/헬스체크에 쓰는 접속 정보다. platform.host · metastore.* · cache.* · tse.* · storage.db.* · analytics.* · object.*(MinIO) 블록으로 구성된다. 값은 모두 env.sh 치환이며 배치 템플릿과 같은 키 이름 규약(storage.db.*)을 쓴다.
템플릿에 없지만 코드가 읽는 엔진 키
EngineConfig 는 아래 키들도 읽는다. 템플릿(plantpulse-engine.properties)에는 없으므로 평소에는 코드 기본값이 적용되며, 값을 바꾸려면 plantpulse-server/config/plantpulse-engine.properties 에 직접 줄을 추가해야 한다.
엣지 시계 / 상태 폴링
| 프로퍼티 | 코드 기본값 |
|---|---|
edge.clock.poll.term.sec | 60 |
edge.clock.skew.threshold.ms | 10000 |
edge.clock.rtt.max.ms | 2000 |
edge.clock.autosync.enabled | true |
edge.clock.autosync.cooldown.ms | 600000 |
edge.clock.warn.cooldown.ms | 600000 |
edge.clock.skip.warn.count | 5 |
edge.status.poll.seconds | 30 |
edge.status.poll.jitter.max.ms | 3000 |
edge.clock.poll.term.sec 와 edge.status.poll.seconds 는 스케줄러 잡 주기를 결정한다 — 값 제약은 스케줄러 아키텍처 의 Edge 절 참고.
DDS / 이벤트버스 / 푸시 / 버퍼
| 프로퍼티 | 코드 기본값 |
|---|---|
engine.dds.queue.size | 80000 |
engine.dds.worker.threads | 4 |
engine.dds.latency.warn.ms | 1000 |
engine.eventbus.queue.capacity | 65536 |
engine.push.threads | 4 |
engine.push.queue.size | 10000 |
engine.storage.buffer.type | KAFKA |
engine.streaming.timeout.backup.queue.capacity | 12000000 |
engine.dds.enabled·engine.dds.data.tag.enabled·engine.dds.data.asset.enabled의 코드 기본값은false다. 템플릿이true로 명시하고 있기 때문에 배포본에서만 켜져 있다 — 이 세 줄을 지우면 DDS 가 조용히 꺼진다.
잡 스레드 (템플릿 미기재분)
| 프로퍼티 | 코드 기본값 |
|---|---|
engine.job.thread.oee | 10 |
engine.job.thread.ram | 5 |
engine.job.thread.ems | 5 |
engine.job.thread.system | 4 |
engine.job.asset.slow.threshold.ms | 20000 |
⚠️
engine.job.thread.point의 코드 기본값은4인데 템플릿은8이다(engine.job.thread.asset은 양쪽8로 일치). 템플릿 줄을 지우면 값이 절반으로 떨어진다.
Flow 엔진 (템플릿 미기재분)
| 프로퍼티 | 코드 기본값 |
|---|---|
flow.engine.enabled | true |
flow.executor.parallelism | 64 |
flow.executor.queue.capacity | 10000 |
flow.executor.queue.size | 10000 |
flow.executor.poll.timeout.ms | 50 |
flow.scheduler.pool.size | 4 |
flow.timer.pool.size | 2 |
flow.jdbc.trigger.pool.size | 2 |
flow.shutdown.timeout.sec | 5 |
flow.enabled.cache.ttl.ms | 5000 |
flow.webhook.auth.enabled | true |
알람 / ISO 지표 / OEE
| 프로퍼티 | 코드 기본값 |
|---|---|
alarm.duplicate.check.minutes | 10 |
engine.oee.debounce.ms | 100 |
iso.oee.rolling.window.minutes | 10 |
iso.ems.rolling.window.minutes | 10 |
iso.ram.rolling.window.minutes | 1440 |
이상 탐지 상세 (에셋 포인트 / 시스템)
engine.data.anomaly.enabled=true 로 켰을 때만 의미가 있다.
| 프로퍼티 | 코드 기본값 |
|---|---|
engine.data.anomaly.asset.point.interval | MINUTE |
engine.data.anomaly.asset.point.lookback.minutes | 14400 |
engine.data.anomaly.asset.point.recent.seconds | 600 |
engine.data.anomaly.asset.point.limit | 2100 |
engine.data.anomaly.asset.point.context.length | 2048 |
engine.data.anomaly.asset.point.prediction.length | 96 |
engine.data.anomaly.asset.point.score.history | 60 |
engine.data.anomaly.asset.point.threshold.k | 3.5 |
engine.data.anomaly.asset.point.threshold.min | 0.80 |
engine.data.anomaly.asset.point.threshold.max | 0.98 |
engine.data.anomaly.asset.point.topk.request | 5 |
engine.data.anomaly.asset.point.topn.report | 5 |
engine.data.anomaly.system.lookback.minutes | 1440 |
engine.data.anomaly.system.recent.seconds | 60 |
engine.data.anomaly.system.limit | 2100 |
engine.data.anomaly.system.context.length | 2048 |
engine.data.anomaly.system.pred.length | 96 |
engine.data.anomaly.system.threshold.min | 0.80 |
engine.data.anomaly.system.topk | 2 |
존재하지 않는 설정
아래 이름들은 과거 문서·외부 자료에 등장하지만 템플릿에도 코드에도 없다. 이 이름으로 설정을 추가해도 아무 효과가 없다.
| 찾던 것 | 실제 위치 |
|---|---|
storage.postgresql.* | metastore.driver / metastore.url / metastore.user / metastore.password |
storage.redis.* | cache.host / cache.port / cache.password / cache.ssl.* |
storage.cassandra.* | storage.host / storage.port / storage.keyspace / storage.user / storage.password |
storage.tse.* | tse.protocol / tse.host / tse.port / tse.user / tse.password |
storage.ttl.realtime 등 | 테이블별 storage.tag.point.ttl / storage.asset.data.ttl 등 (TTL 절) |
storage.compression.enable / .algorithm | storage.compression.zstd.level / storage.compression.zstd.type (템플릿 줄은 오타 — 오타 키 경고) |
storage.compaction.enable / .schedule | storage.table.compaction.strategy 계열 (Compaction 절) |
storage.metastore.* / storage.cache.* | 없음 |
mq.type / mq.kafka.bootstrap.servers / mq.kafka.group.id | mq.host + mq.kafka.port. 컨슈머 그룹은 설정이 아니라 코드 상수(PP-KAFKA-POINT-GROUP 등, 메시징 아키텍처) |
mail.* 를 plantpulse-server/config/ 밖에서 | plantpulse-mail.properties 한 곳 |
websocket.* / plantpulse-websocket.properties | 없음. STOMP/WebSocket 은 2026-07 퇴역, 브라우저 푸시는 SSE(/push/sse) — 메시징 아키텍처 |
scheduler.enabled / scheduler.thread.count / scheduler.misfire.* / scheduler.history.* | 없음. Quartz 설정은 plantpulse-server-web/src/quartz.properties(WAR 클래스패스) — 스케줄러 아키텍처 |
engine.ntp.enable / engine.ntp.server | engine.ntpdate.sync / engine.ntpdate.server.ip |
engine.cep.enable / engine.cep.host / engine.cep.port | engine.cep.server.ip / engine.cep.server.port / engine.cep.server.protocol |
engine.anomaly.* | engine.data.anomaly.* |
engine.dds.enable / engine.dds.topic.prefix | engine.dds.enabled, 토픽 접두는 PP_TOPIC_PREFIX(mq 템플릿) |
engine.async.queue.size / engine.async.timeout / engine.pipeline.batch.size / engine.timeout.* / engine.dataflow.threads / engine.dataflow.buffer.size | 없음 |
PP_STOMP_* / PP_WEBSOCKET_* env 변수 | env.sh 에 없다 |
비밀번호가 들어 있는 프로퍼티
납품 전 반드시 교체해야 하는 값들이다. dev 평문 기본값은 env.sh(또는 템플릿)의 placeholder 이며, 운영/고객 납품 시 고객 전용 값으로 바꾸거나 Docker -e VAR=... / export 로 덮어쓴다.
| 파일 | 키 |
|---|---|
plantpulse-storage.properties | metastore.password · cache.password · cache.ssl.truststore.password · storage.password · tse.password · data.gateway.api.key |
plantpulse-engine.properties | api.key · flow.webhook.api.key · engine.cep.server.api.key |
plantpulse-mq.properties | mq.password · mq.ssl.truststore.password |
plantpulse-mail.properties | mail.smtp.password |
plantpulse-ai.properties | ai.openai.api.key |
plantpulse-cep.properties | cache.password · storage.password · cep.api.key |
plantpulse-batch.properties | metastore.password · cache.password · tse.password · mq.password · storage.db.password · analytics.password · external.db.password |
plantpulse-jdbc.properties | cache.password · jdbc.postgres.password · jdbc.cassandra.password · jdbc.tse.password · jdbc.spark.password · data.gateway.api.key |
plantpulse-data-gateway.properties | data.gateway.api.key |
plantpulse-monitor.properties | db_password · tse_password · redis_jmx_uri(URL 내 password) · redis_ssl_truststore_password · postgres_jmx_uri(URL 내 password) |
plantpulse-mqtt.properties · plantpulse-mq-auth.properties | mqtt.password |
plantpulse-plugin-opcua.properties | postgres.password · cassandra.password · redis.password · kafka.password · opc.ua.server.password |
plantpulse-plugin-aas.properties | aas.db.password · cassandra.password · kafka.password |
kafka.properties | ssl.keystore.password · ssl.key.password · ssl.truststore.password |
hive-auth.properties | 값 전체가 비밀번호 |
API 키 정책:
PP_API_KEY·PP_DATA_GATEWAY_API_KEY·PP_FLOW_WEBHOOK_API_KEY·PP_CEP_API_KEY는 dev 평문 기본값 폴백(${VAR:-<dev기본값>})으로 둔다 — dev/테스트가 추가 시크릿 주입 없이 부팅·배포되게 하기 위함이다. 하드페일(:?)로 바꾸지 마라 —restart-server.sh가env.sh를 source 하다 즉사해 배포가 실패한다.
권장 조치
# 설정 파일 권한 제한
chmod 600 /opt/kopens/plantpulse-platform/plantpulse-*/config/*.properties
# 사이트별 비밀값은 env.local.sh 로 분리 (env.sh 는 SSOT 유지)
vi /opt/kopens/plantpulse-platform/plantpulse-startup/env.local.sh
시크릿은 리포지토리에 커밋하지 않는다.