본문으로 건너뛰기

프로퍼티 레퍼런스

이 문서는 배포되는 실물 설정 템플릿(*.properties)에서 재생성됩니다. 템플릿의 정본은 plantpulse-datalake-cli/config/templates 이고, 호스트의 /etc/kopens/conf 가 그 자리로 바인드 마운트됩니다. 어느 템플릿이 어디로 렌더되는지는 config/render.map 한 장이 정합니다. 로딩 우선순위의 정본은 plantpulse-core/src/plantpulse/core/engine/utils/PropertiesUtils.java 입니다.

키를 추가·삭제·개명했다면 이 문서가 아니라 템플릿이 정본입니다. 문서를 손으로 채우지 말고 템플릿에서 다시 뽑으세요. 각 표의 「기본값」은 템플릿에 적힌 그대로이며, ${PP_XXX} 는 렌더할 때 환경변수 값으로 치환되는 자리입니다.

값이 어디서 와서 어디로 가나​

무엇어디권한바꾸는 법
비밀 — DB 비밀번호 · API 키/etc/kopens/plantpulse-platform.env0600bin/passwd.sh (서버 계정 변경 → 사이드카 갱신 → 재렌더 → 재시작을 한 명령으로)
이 박스 고유 값 — PP_MASTER_IP · Kafka 광고 주소 · 이미지 태그 핀/etc/kopens/platform.node.env0600직접 편집 후 bin/restart-datalake.sh
설정 — 포트 · 이미지 태그 · 로케일 · 데이터 경로repo 의 .env (.env.example 만 커밋)—직접 편집 후 재시작
엔진 설정의 «줄» — postgresql.conf 파라미터, Kafka 보존, Aster TSDB 힙/etc/kopens/conf/<파일>.template—템플릿 편집 → pd config render → pd restart <서비스>
컴포넌트의 설정 파일을 직접 고치면 다음 기동에 사라집니다

pd start 는 매번 템플릿을 렌더해 각 컴포넌트의 설정 자리로 덮어씁니다. cassandra.yaml · postgresql.conf · kafka.properties 를 열어 고쳐도 다음 기동에 원래대로 돌아갑니다. 고칠 곳은 템플릿입니다 → 설정 바꾸는 법

비밀과 노드 값을 한 파일로 합치지 마세요

비밀 파일은 split install 때 앱 노드로 복사되고, 노드 파일은 복사되면 안 됩니다. 합치면 한 박스의 PP_MASTER_IP 와 이미지 태그 핀이 다른 박스로 샙니다. 형식은 VAR=값 한 가지입니다 — export 를 붙이면 env_file: 이 파싱하지 못합니다.

템플릿 변경 표준 절차​

호스트에서 값을 고치고, 컨테이너 안의 pd 로 반영합니다.

vi /etc/kopens/conf/<템플릿> # 1. 호스트의 템플릿을 고칩니다

docker exec plantpulse-datalake pd doctor # 2. 검사 (선택)
docker exec plantpulse-datalake pd config diff # 3. 무엇이 달라지는지 봅니다
docker exec plantpulse-datalake pd config render # 4. 실제로 씁니다
docker exec plantpulse-datalake pd restart <서비스> # 5. 재시작
docker exec plantpulse-datalake pd status # 6. 확인

pd config render 는 설정 파일을 다시 쓸 뿐 서비스를 재시작하지 않습니다. 재시작 전까지는 새 설정이 디스크에만 있고 옛 프로세스가 살아 있습니다. 그래서 4번과 5번이 한 세트입니다.

설정 파일 로딩 우선순위​

웹 애플리케이션(server / batch / cep / sql / data-gateway)은 다음 순서로 설정 파일을 찾는다. 구현은 PropertiesUtils.readExternalFirst() 다.

  1. -Dpp.conf.dir 시스템 프로퍼티로 지정한 디렉토리 (상수 PropertiesUtils.CONF_DIR_SYSTEM_PROPERTY = "pp.conf.dir")
  2. ${catalina.base}/../config — 모듈의 config/ 디렉토리
  3. 웹앱 클래스패스 (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:기본값} 표기는 두 시점에서 해석된다.

시점주체동작
기동 시pd config render사이드카(plantpulse-platform.env · platform.node.env)와 컨테이너 환경으로 치환. 순서는 환경변수 → :기본값 → 원본 유지. 중첩 placeholder 미지원
런타임PropertiesUtils.resolveEnvPlaceholders로드한 Properties 의 모든 값에 대해 ${ENV_VAR[:default]} 를 다시 해석

즉 배포 후 남아 있는 ${...} 도 프로세스의 환경변수로 채워질 수 있다. Docker -e VAR=... 주입이 템플릿 기본값보다 우선하는 이유다.

사이드카에 없는 PP_* 변수 (템플릿 기본값이 그대로 적용됨)​

아래 변수들은 템플릿이 ${PP_XXX:기본값} 으로 참조하지만 사이드카 파일이 정의하지 않는다. 따라서 별도 주입이 없으면 항상 템플릿 기본값이 쓰인다.

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_* 는 이 목록에 있었지만 이제 아무 일도 하지 않습니다

PP_AI_OPENAI_* · PP_AI_MCP_* · PP_AI_CHAT_ENABLED 를 주면 조용히 무시됩니다. 그 값들을 읽던 층이 2026-09-18 에 없어졌습니다 — AI 설정을 보십시오.

PP_STORAGE_PASSWORD · PP_METASTORE_PASSWORD 는 이 목록에 있었지만 «없는 변수» 입니다

템플릿도 사이드카도 그 이름을 참조하지 않습니다. 실제 이름은 이렇습니다 —

무엇실제 변수
시계열 저장소(Aster TSDB) 접속PP_CASSANDRA_HOST · PP_CASSANDRA_PORT · PP_CASSANDRA_USER · 🔑 PP_CASSANDRA_PASSWORD
메타스토어(PostgreSQL) 접속PP_POSTGRES_HOST · PP_POSTGRES_PORT · PP_PG_USER · 🔑 PP_PG_PASSWORD

🔴 PP_MAIL_SMTP_* 도 이제 아무 일도 하지 않는다. 메일 설정의 정본은 pp.mm_config 이고, 값은 콘솔(/config/index)이나 그 표에서 바꾼다 — 메일 설정. 한 벌로 맞아야 하는 값(호스트 · 포트 · 인증 여부 · 계정)을 한 곳에서만 고치게 한 것이 이 이관의 이유이기도 하다.

서버 관리 설정 5종​

ConfigTemplates.SERVER_CONFIGS 배열이 정의하는, plantpulse-server/config/ 로 배포되는 설정 파일은 5개다.

#템플릿배포 경로
1plantpulse-engine.properties/plantpulse-server/config/plantpulse-engine.properties
2plantpulse-storage.properties/plantpulse-server/config/plantpulse-storage.properties
3plantpulse-mq.properties/plantpulse-server/config/plantpulse-mq.properties

세 파일은 PropertiesLoader.load() 가 한꺼번에 읽고(engine/mq/storage), 타입드 설정 빈 EngineConfig · StorageConfig · MqConfig 를 재구성한다.

메일 · AI 설정은 파일이 아니다 — pp.mm_config 가 정본이다

plantpulse-mail.properties 와 plantpulse-ai.properties 는 2026-09-17 에 삭제됐고, 외부 설정 디렉터리에 남아 있을 수 있는 옛 사본을 읽어 표로 옮기던 경로도 2026-09-18 에 통째로 없어졌다. 즉 그 파일을 만들어 두어도 아무것도 읽지 않는다.

값이 들어가는 길은 콘솔과 PostgreSQL pp.mm_config 둘뿐이다. 키 이름과 기본값의 정본은 코드의 MailConfigKeys · AiConfigKeys 이고, 표에 행이 없는 키는 그 기본값으로 읽힌다 — 아래 두 절의 키 표는 그대로 유효하다.

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.parallelism256—Async worker pool parallelism (total cores ~= 256)
engine.pipeline.threads36—파이프라인 스레드 수
engine.pipeline.ratelimit40000—파이프라인 초당 처리 상한 (rate limit)
engine.pipeline.queue.size1200000—파이프라인 큐 크기 (백프레셔 한계)
engine.pipeline.queue.o3.delay50—순서 어긋난(out-of-order) 데이터 허용 지연 (ms)
engine.pipeline.task.modeSINGLE—태스크 실행 모드 (SINGLE / PARALLEL)

NTP​

프로퍼티기본값치환설명
engine.ntpdate.server.ip127.0.0.1—NTP 서버 IP
engine.ntpdate.syncfalse—부팅 시 NTP 동기화 수행 여부

스트림 / CEP​

프로퍼티기본값치환설명
engine.stream.processorDIRECT—스트림 처리 모드 (DIRECT/BUFFERED)
engine.cep.server.ip127.0.0.1${PP_CEP_HOST:127.0.0.1}CEP 서버 IP
engine.cep.server.port7400${PP_CEP_CONNECT_PORT:7400}CEP 서버 포트 (protocol 에 자동 정렬: http→7400, https→7401)
engine.cep.server.protocolhttp${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.ms5000—메시지 전달 지연 경고 (ms)
engine.streaming.messaging.timeout.ms10000—메시지 전달 타임아웃 (ms)
engine.streaming.messaging.timeout.store.typeFILE_QUEUE—타임아웃 메시지 저장 방식 (FILE_QUEUE/MEMORY)
engine.streaming.messaging.timeout.recovery.typeDB—타임아웃 메시지 복구 소스 (DB/FILE)

잡 워커 스레드​

프로퍼티기본값치환설명
engine.job.thread.asset8—에셋 잡 스레드 수
engine.job.thread.point8—포인트 잡 스레드 수

DDS​

프로퍼티기본값치환설명
engine.dds.enabledtrue—DDS 전역 활성화
engine.dds.data.tag.enabledtrue—태그 데이터 DDS 발행
engine.dds.data.asset.enabledtrue—에셋 데이터 DDS 발행

이상 탐지 / 데이터플로우​

프로퍼티기본값치환설명
engine.data.anomaly.enabledfalse—이상 탐지 활성화 (외부 서비스 연동)
engine.data.anomaly.urlhttps://127.0.0.1:8970—이상 탐지 서비스 URL
engine.dataflow.classplantpulse.core.engine.pipeline.dataflow.BaseDataFlow—데이터플로우 구현 클래스
engine.dataflow.server-timestamp.overridefalse—서버 타임스탬프 강제 여부 (true: 수집 시각, false: 원본)
engine.dataflow.negative-timestamp.overridetrue—음수 타임스탬프 보정 여부
engine.factory.model.updater.classplantpulse.core.engine.model.impl.DefaultFactoryMetaModelUpdater—팩토리 메타모델 업데이터
engine.event.handler.classplantpulse.core.engine.event.DefaultEventHanlder—이벤트 핸들러 구현 (클래스명 오타 Hanlder 는 실제 클래스명 그대로)
engine.javagc.enabledfalse—명시적 System.gc() 호출 허용 여부

Flow 엔진​

프로퍼티기본값치환설명
flow.debug.execution.logfalse—노드 실행 INFO 로그. 디버깅 세션에만 true
flow.stats.prune.interval.ms86400000—카운터 정리 실행 주기 (ms, 24시간). Aster TSDB 카운터 테이블은 default_time_to_live 를 못 쓰므로 애플리케이션 레벨로 정리
flow.stats.prune.hourly.days30—tm_flow_stats_hourly 의 hour_bucket 보관 일수
flow.stats.prune.daily.days90—tm_flow_stats_daily 의 day_bucket 보관 일수
flow.health.check.interval.ms600000—Flow 헬스체크 주기 (ms, 10분). 현재 시각 버킷 errors > 0 이면 ERROR, 아니면 NORMAL (KST 기준)
flow.webhook.api.keydev-webhook-19ba7a54-1132-49f2-967e-3c6f5cd989a0${PP_FLOW_WEBHOOK_API_KEY:...}Flow 엔진 외부 웹훅 인증

Flow 헬스체크가 쓰는 Aster TSDB 테이블: tm_flow_health_status(flow_id, hour_bucket — 현재 시각 누적기), tm_flow_health_status_10m(flow_id, min10_bucket — 10분 단위 시계열).

엣지 헬스체크​

프로퍼티기본값치환설명
edge.health.check.interval.ms600000—엣지 헬스체크 주기 (ms, 10분)

판정 소스는 Aster TSDB 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.enabledtrue—V5 API 인증 브루트포스 방어
engine.api.v5.auth.bruteforce.ip_limit30—IP 당 시도 한도
engine.api.v5.auth.bruteforce.user_limit10—사용자 당 시도 한도
engine.api.v5.auth.bruteforce.window.seconds60—카운팅 윈도우 (초)
engine.api.v5.trusted_proxies(빈 값)—신뢰 프록시 IP 화이트리스트. 설정 시에만 remoteAddr 이 목록에 있을 때 X-Forwarded-For 첫 IP 를 client IP 로 사용. 비어 있으면 getRemoteAddr() 만 사용(fail-safe)
engine.session.bruteforce.enabledtrue—/login/login 브라우저 세션 브루트포스 방어
engine.session.bruteforce.ip_limit30—IP 당 시도 한도
engine.session.bruteforce.user_limit10—사용자 당 시도 한도
engine.session.bruteforce.window.seconds300—카운팅 윈도우 (초)

세션 브루트포스 카운터는 Caffeine 인메모리다 — 다중 노드 공유(Redis)는 미구현.

API 토큰​

프로퍼티기본값치환설명
engine.api.token.cleanup.enabledtrue—만료(expires_at < now)/회수(revoked_at IS NOT NULL) 토큰 정리
engine.api.token.cleanup.retention_days30—이 기간 경과 후 mm_token 에서 hard delete. 매 24시간 1회(부팅 60초 후 첫 실행)
engine.api.token.default_ttl_days90—신규 토큰 발급 시 기본 만료(일). 0 = 영구 토큰. 발급 요청이 ttl_days 를 주면 그 값이 우선한다 → API 토큰 발급

기존 expires_at 이 NULL 인 토큰은 영구 활성으로 유지된다(하위 호환).


plantpulse-storage.properties​

경로: plantpulse-server/config/plantpulse-storage.properties · 템플릿: template/plantpulse-storage.properties

메타스토어(PostgreSQL) · 캐시(Valkey) · 시계열(Aster TSDB) · TSE · Data Gateway 접속과 스토리지 정책을 관리한다.

⚠️ 이 파일에는 오타 키가 실재한다. 3개 키가 코드가 읽는 철자와 다르다 — 오타 키 경고 절을 반드시 읽어라.

PostgreSQL 메타스토어​

프로퍼티기본값치환설명
metastore.driverorg.postgresql.Driver—JDBC 드라이버 클래스
metastore.urljdbc: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.enabledfalse—캐시 TLS. 내부 클라이언트는 redis:// 기본
cache.ssl.truststore.location/var/security/plantpulse/master/master.truststore.p12—트러스트스토어 경로
cache.ssl.truststore.passwordkopens123!${PP_TLS_TRUSTSTORE_PASSWORD:kopens123!}트러스트스토어 비밀번호
cache.ssl.truststore.typePKCS12—트러스트스토어 타입
cache.ssl.endpoint.identification.enabledfalse—엔드포인트 식별 검증

키 상수 정본은 plantpulse-inmemory 의 InMemoryConfigKeys 다.

TSE (TimeSeries Engine)​

프로퍼티기본값치환설명
tse.protocolhttp${PP_TSE_PROTOCOL:http}TSE 프로토콜. 내부 통신이라 평문 http 기본 (2026-08)
tse.host—${PP_TSE_HOST}TSE 호스트
tse.port7800${PP_TSE_CONNECT_PORT:7800}TSE 포트. 평문 리스너 7800 기본
tse.usertse${PP_TSE_USER:tse}TSE 계정
tse.passwordtse123!${PP_TSE_PASSWORD:tse123!}TSE 비밀번호

Aster TSDB 시계열 저장소​

프로퍼티기본값치환설명
storage.db_typeCASSANDRA—DB 종류. 템플릿 주석에 CASSANDRA/DSE/SCYLLADB 가 남아 있으나 지금 지원되는 값은 CASSANDRA 뿐입니다
storage.db_version5.0—서버 버전이 아니라 «기능 호환 수준» 입니다 — 아래 주를 보십시오
storage.host—${PP_CASSANDRA_HOST}contact point 호스트
storage.db_version 이 5.0 인데 nodetool version 은 6.0.0 이라고 나옵니다

둘 다 맞습니다. 같은 것을 가리키는 값이 아닙니다.

값무엇
storage.db_version5.0드라이버가 어느 기능 집합으로 말할지를 정하는 호환 수준
실제 번들 서버6.0.0apache-cassandra-timeseries-6.0.0.jar — cassandra-6.0 의 사내 포크

5.0 을 보고 「서버가 5.0 이구나」라고 읽지 마십시오. 서버 쪽 이야기는 시계열 데이터베이스에 있습니다. 이 값을 임의로 6.0 으로 올리지 마십시오 — 드라이버 동작이 바뀝니다.

| 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.ttl62태그 시계열 원본
storage.tag.point.map.ttl1태그 포인트 맵
storage.tag.point.sampling.ttl93태그 샘플링
storage.tag.point.snapshot.ttl93태그 스냅샷
storage.tag.point.aggregation.ttl93태그 집계
storage.tag.point.archive.ttl365태그 아카이브 (장기 보존)
storage.tag.blob.ttl93태그 BLOB
storage.asset.data.ttl10에셋 데이터
storage.asset.data.sampling.ttl31에셋 샘플링

에셋 스냅샷 주기​

프로퍼티기본값설명
storage.asset.data.snapshot.interval10 SECONDS매 사이클 전 자산의 태그맵(data_map)을 asset_data 계열(data/second/timestamp + 분/시/일 경계)에 기록

템플릿 주석이 근거를 밝히고 있다: 1 SECONDS 는 자산 121 기준 분당 약 22K 쓰기(Aster TSDB 전체의 약 4%)로 과밀했다. 태그 원본(초 단위)은 tm_tag_point/TSE 에 완전 보존되므로 자산 뷰 스냅샷은 10s(코드 기본값과 일치)로 낮췄다 — 쓰기 −90%, 기록 완전성 유지.

이 값은 스케줄러의 ASSET_DATA_JOB 주기가 된다. "<수> <단위>" 2토큰 형식이어야 하며 규칙은 스케줄러 아키텍처 참고.

내부 메타스토어 동기화 (실험적)​

프로퍼티기본값설명
storage.internal.metastore.enabledfalse내부 메타스토어 동기화 활성화
storage.internal.metastore.thread.count4동기화 워커 스레드 수
storage.internal.metastore.queue.size12000000동기화 큐 크기
storage.internal.metastore.point.retation.days10포인트 보관 일수 (⚠️ 오타 키 — 아래 참고)

행 캐시​

프로퍼티기본값설명
storage.asset.data.row.cache.sizeNONE에셋 데이터 행 캐시 (NONE/ROWS_ONLY/ALL) — ⚠️ 읽는 코드 없음
storage.tag.point.row.cache.sizeNONE태그 포인트 행 캐시 — ⚠️ 읽는 코드 없음

Compaction​

프로퍼티기본값설명
storage.table.compaction.strategyUCS기본 전략 (TWCS: TimeWindow, UCS: Unified). CassandraCreateDAO 가 읽는다(코드 fallback 은 TWCS)
storage.table.compaction.strategy.twcs.window_size1TWCS 윈도우 크기 — ⚠️ 읽는 코드 없음
storage.table.compaction.strategy.twcs.window_unitDAYSTWCS 윈도우 단위 — ⚠️ 읽는 코드 없음
storage.table.compaction.strategy.ucs.scailing_parameterT8UCS 스케일링 파라미터 (T8 = tiered 8 levels). 키 철자 scailing 은 코드와 일치
storage.table.compaction.strategy.ucs.min_sstable_size128MiBUCS 최소 sstable 크기 (코드 fallback 100MiB)
storage.table.compaction.strategy.ucs.target_sstable_size512MiBUCS 목표 sstable 크기
storage.table.compaction.strategy.ucs.base_shard_count8UCS base shard 수
storage.table.compaction.strategy.ucs.max_sstables_to_compact6한 번에 compaction 할 최대 sstable 수
storage.table.compaction.strategy.ucs.sstable_growth0.7UCS sstable 증가 비율

압축 / 쿼리 한도 / 백업 / Data Gateway​

프로퍼티기본값치환설명
storage.compresion.zstd.level3—zstd 압축 레벨 (1~22) — ⚠️ 오타 키, 아래 참고
storage.tag.point.select.limit.size1000000—단일 태그 포인트 select 최대 행 수
storage.doamin.model.changed.to.metastore.backuptrue—도메인 모델 변경 시 메타스토어 백업 — ⚠️ 오타 키 + 읽는 코드 없음
data.gateway.protocolhttp${PP_DATA_GATEWAY_PROTOCOL:http}Data Gateway 프로토콜
data.gateway.host127.0.0.1${PP_DATA_GATEWAY_HOST:127.0.0.1}Data Gateway 호스트 (로컬 동거 전제)
data.gateway.port5500${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.levelstorage.compression.zstd.level3StorageConfig → CassandraCreateDAO
storage.internal.metastore.point.retation.daysstorage.internal.metastore.point.retention.days10StorageConfig → PointDAO
storage.doamin.model.changed.to.metastore.backup없음 (올바른 철자로도 읽는 코드가 없다)——

값을 실제로 바꾸려면 코드 철자의 키를 같은 파일에 추가하라. 예를 들어 zstd 레벨을 6으로 올리려면 storage.compression.zstd.level=6 을 넣어야 한다(오타 키를 고쳐 쓰는 것이 아니라 올바른 철자 줄을 추가). 오타 줄은 남겨 두어도 무해하지만, 템플릿 자체를 고치는 편이 근본 해법이다.

storage.doamin.model.changed.to.metastore.backup 은 어느 철자로도 읽는 코드가 없다. 도메인 모델 변경 시 백업은 이 키가 아니라 MetastoreBackupDeployer(cron 0 0 12 1 1/1 ? *, 매월 1일 12:00)가 담당한다 — 스케줄러 아키텍처 참고.

템플릿에는 없지만 코드가 읽는 storage 키​

프로퍼티코드 기본값설명
storage.compression.zstd.typeZstdCompressor압축기 클래스명

읽는 코드가 없는 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.port9092${PP_KAFKA_PORT:9092}Kafka 포트
mq.kafka.security.protocolSASL_PLAINTEXT—Kafka 보안 프로토콜
mq.ssl.truststore.location/var/security/plantpulse/master/master.truststore.p12—메시징 TLS 트러스트스토어 (MQTT + 선택적 Kafka TLS)
mq.ssl.truststore.passwordkopens123!${PP_TLS_TRUSTSTORE_PASSWORD:kopens123!}트러스트스토어 비밀번호
mq.ssl.truststore.typePKCS12—트러스트스토어 타입
mq.ssl.endpoint.identification.algorithm(빈 값)—호스트명 검증 알고리즘 (빈 값 = 검증 안 함)
mq.mqtt.port—${PP_MQTT_TLS_PORT}MQTT 접속 포트
mq.mqtt.ssl.enabledtrue—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 를 동시에 결정한다.


메일 설정 (pp.mm_config)​

정본: PostgreSQL pp.mm_config · 키 정본: plantpulse.core.config.MailConfigKeys. 읽는 쪽은 SMTPMailSender.loadMailConfig() 다.

🔴 PP_MAIL_* 환경변수도 아무 일도 하지 않습니다

AI 와 같습니다 — plantpulse-mail.properties 와 ${PP_MAIL_*} 치환 층이 2026-09-17~18 에 없어졌습니다. 사이드카나 docker run -e 로 주어도 조용히 무시됩니다. 값은 콘솔의 설정 화면(/config/index) 또는 pp.mm_config 표에 넣습니다.

설정 키기본값설명
MAIL_SEND_ENABLEDfalse마스터 발송 게이트. 꺼져 있으면 SMTP 접속 없이 건너뛰고 WARN 만 남깁니다
MAIL_SMTP_HOSTsmtp-relay.brevo.comSMTP 릴레이 주소
MAIL_SMTP_PORT587587 = STARTTLS, 465 = 암시적 TLS(MAIL_SMTP_SSL_ENABLE 과 함께)
MAIL_SMTP_AUTHtrueSMTP 로그인 여부. 켜 있어도 MAIL_SMTP_USER 가 비어 있으면 로그인하지 않습니다
MAIL_SMTP_USER(빈 값)SMTP 계정. 릴레이가 발급한 이름이라 발신 주소와 다를 수 있습니다. 비워서 저장할 수 있습니다
🔑 MAIL_SMTP_PASSWORD(빈 값)SMTP 비밀번호 또는 API 키. 로그인하는 릴레이에서 비어 있으면 인증이 거부됩니다
MAIL_SMTP_STARTTLS_ENABLEtrue587 에서 STARTTLS 로 승격할지
MAIL_SMTP_SSL_ENABLEfalse465 처럼 처음부터 TLS 로 붙을지. 이 경우 starttls 는 끕니다
MAIL_SMTP_CONNECTIONTIMEOUT10000접속 타임아웃(ms). 없으면 JavaMail 기본값은 「무한 대기」입니다
MAIL_SMTP_TIMEOUT10000읽기 타임아웃(ms). 〃
MAIL_SMTP_WRITETIMEOUT10000쓰기 타임아웃(ms). 〃
MAIL_FROM(빈 값)발신 주소. 비우면 MAIL_SMTP_USER 를 쓰는데, 릴레이 계정명은 대개 유효한 주소가 아니라 수신 측이 거부할 수 있습니다 — 실제 주소를 적으십시오
sms.sender.classplantpulse.core.service.support.alarm.sms.DefaultSMSSenderSMS 발송기 구현 FQN. 없는 클래스를 적으면 기본 구현으로 되돌아갑니다

TLS 는 1.3 · 1.2 만 쓰고 서버 인증서의 이름을 검사합니다.

기본값에 SMTP 자격증명이 더 이상 들어 있지 않습니다

MAIL_SMTP_USER · MAIL_SMTP_PASSWORD 의 기본값은 빈 값입니다. MAIL_SEND_ENABLED 가 기본 false 이므로 운영자가 켜기 전까지는 발송을 시도하지 않습니다.

Gmail SMTP 릴레이로 보내기​

Google Workspace 의 SMTP 릴레이(smtp-relay.gmail.com)는 보내는 서버의 IP 주소로 허가할 수 있습니다. 이때는 계정이 없으므로 로그인하지 않게 둡니다. 먼저 Google 관리 콘솔의 SMTP 릴레이 설정에 이 서버가 밖으로 나가는 IP 를 등록합니다.

설정 키값
MAIL_SEND_ENABLEDtrue
MAIL_SMTP_HOSTsmtp-relay.gmail.com
MAIL_SMTP_PORT587
MAIL_SMTP_AUTHfalse
MAIL_SMTP_USER(비움)
MAIL_SMTP_STARTTLS_ENABLEtrue
MAIL_SMTP_SSL_ENABLEfalse
MAIL_FROMWorkspace 도메인의 실제 주소

저장한 뒤 설정 화면의 재적용 을 누릅니다.

알람 메일​

  • 머리에는 제품 로고가 메일 안에 실려 갑니다(CID 인라인 이미지). 콘솔 주소가 없어도 보이고, 밖에서 받아 오는 것이 없습니다.
  • 메일의 위치 줄은 사이트부터 적힙니다(사이트 › 구역 › 라인 › 설비, 기업은 넣지 않습니다).
  • «알람 확인하러 가기» 링크는 PP_UI_CONSOLE_URL(<콘솔 주소>/alarm/view/<알람 번호>)입니다. 비어 있으면 메일은 그대로 나가고 링크만 빠집니다 — 주소 설정.
diagnostic.log.email 은 없어졌습니다

읽는 코드가 하나도 없어 표에서 제거됐습니다(제품 테스트가 그 키가 다시 들어오는 것을 막고 있습니다). 어딘가에 남아 있어도 아무 일도 하지 않습니다.


AI 설정 (pp.mm_config)​

정본: PostgreSQL pp.mm_config · 키 정본: plantpulse.core.config.AiConfigKeys. 읽는 쪽은 AiConfig(+ AiConfig.mcpSettings()) 다.

🔴 PP_AI_* 환경변수는 아무 일도 하지 않습니다

옛 plantpulse-ai.properties 는 2026-09-17 에 삭제됐고, 그 파일을 읽던 경로와 ${PP_AI_*} 치환 층까지 2026-09-18 에 함께 없어졌습니다. 지금 PP_AI_OPENAI_ENABLED 같은 이름을 사이드카나 docker run -e 로 주면 조용히 무시됩니다 — 오류도 경고도 없습니다.

제품이 그 이름들을 「혹시 모르니」 남겨 두지 않고 지운 이유가 그것입니다. 있으면서 무시되는 이름은 없는 이름보다 나쁩니다. 서버가 설정된 것처럼 보이기 때문입니다.

값을 넣는 길은 둘뿐입니다 — 콘솔의 설정 화면(/env), 또는 pp.mm_config 표를 직접 고치는 것. 행이 없는 키는 아래 표의 기본값으로 읽히고, 값을 넣으면 그때 행이 생깁니다.

LLM 게이트웨이​

프로퍼티기본값설명
ai.llm.enabledfalseAI 전체 스위치. 꺼져 있으면 AI 화면과 엔드포인트가 모두 닫힙니다
ai.llm.base.urlhttps://api.openai.comOpenAI 호환 게이트웨이(LiteLLM/vLLM). 끝에 / 를 붙이지 않습니다
ai.llm.chat.path/v1/chat/completions게이트웨이가 다른 경로를 쓸 때만 바꿉니다
ai.llm.responses.path/v1/responses〃
🔑 ai.llm.api.key(빈 값)게이트웨이 키. 비어 있으면 호출이 401 로 거부됩니다
ai.llm.modelgpt-5-mini게이트웨이가 노출하는 모델명. base.url 을 바꾸면 이것도 함께 바꿉니다
ai.llm.timeout.ms60000LLM 호출 타임아웃(ms)
ai.llm.max.output.tokens4000응답 최대 토큰 수
ai.llm.temperature-1음수면 요청에서 아예 생략해 모델 기본값을 씁니다
옛 이름 ai.openai.* 는 더 이상 읽히지 않습니다

접두사가 ai.llm. 으로 바뀌었습니다. pp.mm_config 에 ai.openai.base.url 행이 남아 있어도 읽는 코드가 없어 기본값(https://api.openai.com)이 쓰입니다 — 게이트웨이를 설정해 두었는데 OpenAI 로 나가려다 실패하는 모양이 됩니다. 업그레이드한 설치는 이 행들을 확인하십시오.

ai.llm.temperature 는 왜 음수가 기본인가

gpt-5 계열은 temperature 를 지원하지 않아 기본값 1 외의 값을 보내면 400 Unsupported value 가 납니다. 그래서 「보내지 않음」을 뜻하는 음수를 기본으로 둡니다. LiteLLM/vLLM 뒤의 다른 모델을 쓸 때만 0 이상으로 올리십시오.

기능 스위치​

🔴 기본값이 2026-09-16 에 바뀌었습니다. 화면에 남은 AI 기능은 채팅 하나이고, 나머지는 제품이 내렸습니다. 값을 true 로 되돌리면 기능은 돌아오지만, 그 화면들은 그 판에서 검증된 상태가 아닙니다.

프로퍼티기본값설명
ai.chat.enabledtrueAI 채팅 콘솔 — 화면에 남은 AI 기능은 이것 하나입니다
ai.chat.history.ttl.days90채팅 이력 보존(일). Cassandra TTL 로 적용되며 재기동 후 «신규» 메시지부터 반영됩니다
ai.alarm.rca.enabledfalse알람 RCA — 켜면 알람 상세에 AI 원인분석이 붙습니다
ai.alarm.eql.enabledfalse알람 EQL 어시스턴트 — 켜면 알람 설정 폼에 초안 버튼이 붙습니다
ai.uns.topic.enabledfalseUNS 토픽 설명 — 켜면 UNS 트리에 설명 패널이 붙습니다
ai.result.audit.enabledfalseAI 결과 감사 — 화면 없는 RCA 내부 부품. RCA 를 켤 때 함께 켭니다
ai.similar.incident.enabledfalse유사 장애 증거 수집 — 〃
ai.similar.incident.max.items5증거로 실을 유사 장애 최대 건수
ai.similar.incident.min.score40유사 장애로 인정할 최소 점수
2026-08 에 없어진 키 6개

ai.diagnostic.summary.* 3개(진단 로그 AI 요약)와 ai.operations.report.* 3개(AI 운영 리포트)는 2026-08-25 제품에서 제거되었습니다. 화면·JS·컨트롤러까지 함께 걷어냈으므로 값을 되돌려도 기능이 살아나지 않습니다. 남아 있어도 해는 없습니다 — 읽는 코드가 없습니다.

MCP​

🔴 MCP 는 ai.llm.enabled 와 «독립»입니다. 화면이 아니라 외부 클라이언트용이라, 게이트웨이가 꺼져 있어도 /api/v5/mcp 는 열려 있습니다. 자세한 것은 MCP 서버.

프로퍼티기본값설명
AI_MCP_ENABLEDtruefalse 면 /api/v5/mcp 가 404 를 냅니다
AI_MCP_ALLOWED_ORIGINS(빈 값)브라우저 Origin 화이트리스트(쉼표 구분). 비어 있으면 브라우저 요청을 전부 거부하고 네이티브 클라이언트만 허용합니다
AI_MCP_TREE_MAX_NODES2000트리 응답 노드 상한 — 모델 컨텍스트 창에 종속되는 값이라 모델이 커지면 올립니다
AI_MCP_TREE_DEFAULT_DEPTH2트리 조회 기본 깊이
AI_MCP_TREE_MAX_NODE_TAGS100노드 하나에 실을 태그 수 상한
AI_MCP_TREE_ONTOLOGY_MAX_CHARS200000온톨로지 응답 문자 수 상한
AI_MCP_TREE_ONTOLOGY_DEFAULT_DEPTH3트리 기본 깊이보다 한 단계 깊습니다 — 태그 수가 실리는 설비 노드까지 나와야 「이 설비 태그 몇 개」를 기본 응답으로 답할 수 있습니다
AI_MCP_TREE_ONTOLOGY_MAX_TAGS500온톨로지 응답 전체의 태그 행 예산(노드별 상한과 별개). 슬림 태그 1건이 약 85B 라, 사이트 전체를 실으면 컨텍스트 창의 33~56% 를 먹습니다

그 외 템플릿​

template/ 에는 위 5종 외에도 애플리케이션·인프라 설정 템플릿이 있다. 배포 경로 매핑 정본은 ConfigTemplates.java 다.

템플릿배포 경로용도
plantpulse-batch.properties/plantpulse-batch/config/배치(시계열 동기/집계)
plantpulse-cep.properties/plantpulse-cep/config/CEP 엔진
plantpulse-jdbc.properties/plantpulse-data-gateway/config/JDBC 통합 설정
plantpulse-data-gateway.properties/plantpulse-data-gateway/config/Data Gateway 동작
plantpulse-warehouse.properties/plantpulse-warehouse/config/Aster TSDB → Iceberg(S3) 아카이브
plantpulse-datalake-admin-api.properties/plantpulse-datalake-admin-api/config/관리 콘솔 API · 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.propertiesKafka(KRaft) 브로커
kafka-jaas.conf/plantpulse-messaging/kafka/config/jaas.confKafka JAAS
hivemq.xml/plantpulse-messaging/mqtt/conf/config.xmlHiveMQ 브로커
plantpulse-mq-auth.properties/plantpulse-messaging/mqtt/conf/auth.propertiesHiveMQ 인증 소스
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-websocket.properties 도 존재하지 않는다. WebSocket/STOMP 계열 설정 파일은 없다. template/cluster/ 는 워커 노드 전용 오버라이드다 — master 템플릿을 고치면 여기도 동기화해야 한다.

plantpulse-batch.properties​

접속 블록(플랫폼/메타스토어/캐시/TSE/Kafka/Aster TSDB/Spark)과 배치 동작 설정으로 구성된다. 접속 키는 storage/jdbc 와 이름이 다르니 주의 — 예: Aster TSDB 는 storage.db.host / storage.db.port / storage.db.keyspace (server 는 storage.host / storage.port / storage.keyspace).

프로퍼티기본값설명
platform.host${PP_MASTER_IP}플랫폼(server-web) 호스트
mq.port9092Kafka 포트 (리터럴 — 치환 아님)
kafka.topicpp-batch배치 인입 토픽
kafka.group.idPP-BATCH-GROUP배치 컨슈머 그룹
batch.timer_schedule_delay5000배치 타이머 주기 (ms)
batch.thread_pool_batch_thread_size4배치 워커 스레드 수
batch.buffer_drain_limit_size10000한 번에 비우는 최대 건수
batch.sync.inmemory.enabledfalse인메모리 동기화
batch.sync.inmemory.ttl.minute10인메모리 동기화 TTL (분)
batch.sync.tse.enabledtrueTSE 로 분배
batch.sync.external.db.enabledfalse외부 DB 동기화
external.db.nameTIMESCALEDB외부 DB 종류. INFLUXDB/QUESTDB 블록은 템플릿에 주석 상태로 있다
analytics.urljdbc:spark://${PP_SPARK_HOST}:${PP_KYUUBI_PORT}/defaultSpark Thrift JDBC

plantpulse-cep.properties​

프로퍼티기본값설명
cep.backendaster부팅할 백엔드 (aster · flink). 그 밖의 값은 부팅 실패 — 백엔드
cep.aster.state.enabledtrueAster CEP 룰 상태(창 · 집계 · 진행 중 패턴)를 cache.* Redis 에 보존. 키는 PP:CEP:ASTER-STATE:<문장>
cep.aster.state.snapshot_interval_ms60000스냅샷 주기 — 크래시 때 잃을 수 있는 최대 상태. 정상 정지는 마지막 스냅샷을 찍고 내려간다
cep.async.core_pool_size32비동기 코어 풀
cep.async.max_pool_size256비동기 최대 풀
cep.async.queue_capacity50000비동기 큐
cep.async.keep_alive_seconds60스레드 keep-alive
cep.async.shutdown_timeout_seconds30graceful shutdown 대기
cep.consumer.thread_count16컨슈머 스레드
cep.stream.shard_count16스트림 샤드 수
cep.stream.drain_limit_size1000드레인 한도
cep.stream.drain_warn_ms1000드레인 경고 (ms)
cep.monitor.initial_delay_seconds5모니터 최초 지연
cep.monitor.interval_seconds1모니터 주기
cep.monitor.store_interval_seconds60지표 Aster TSDB 저장 주기
cep.api.key${PP_CEP_API_KEY}EQL 관리 엔드포인트 인증 (X-API-Key)
cep.api.max_eql_text_length100000EQL 텍스트 최대 길이 (DOS 방어)
cep.storage.request_timeout_seconds10Aster TSDB 요청 타임아웃
cep.storage.connect_max_retries3접속 재시도
cep.storage.ttl_seconds864000메트릭 TTL (초, 10일)
cep.stream.pending_idle_threshold_ms60000pending 유휴 임계
cep.stream.cleaner_initial_delay_ms60000클리너 최초 지연
cep.stream.cleaner_interval_ms10000클리너 주기
cep.stream.max_clean_duration_ms30000클린 최대 소요
cep.stream.cleaner_max_claim_count5000클레임 최대 건수
cep.stream.ack_chunk_size500ACK 청크 크기
cep.stream.max_deliveries3이 횟수만큼 배달돼도 처리되지 못한 이벤트만 데드레터로 보낸다
cep.stream.dead_letter.retention_ms86400000데드레터 보존 나이(24시간)
cep.stream.dead_letter.max_bytes268435456데드레터 바이트 예산(256 MiB, 샤드 전체 합계). 넘으면 샤드마다 오래된 것부터 자른다

plantpulse-jdbc.properties​

외부 JDBC 클라이언트(SQL 모듈 · Data Gateway)의 통합 접속 설정이다. 프리픽스는 jdbc.<tech> (postgres/cassandra/spark/tse).

프로퍼티값설명
jdbc.postgres.driverorg.postgresql.DriverMETA / PQL
jdbc.postgres.urljdbc:postgresql://${PP_POSTGRES_HOST}:${PP_POSTGRES_PORT}/${PP_DB_NAME}?characterEncoding=UTF-8
jdbc.cassandra.driverplantpulse.cassandra.jdbc.CassandraDriverOLTP 시계열(CQL). 드라이버 값은 설정 일관성용(기능상 미사용)
jdbc.cassandra.urljdbc:cassandra://${PP_CASSANDRA_HOST}:${PP_CASSANDRA_PORT}/${PP_SCHEME}
jdbc.tse.driverplantpulse.timeseries.tql.TQLDriverOTAP / TQL
jdbc.tse.urljdbc:ts://${PP_TSE_HOST}:${PP_TSE_PORT}/${PP_SCHEME}⚠️ plain http(ts/7800) 고정
jdbc.spark.driverplantpulse.spark.jdbc.SparkSQLDriverOLAP 분석
jdbc.spark.urljdbc: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.limit1000초당 최대 요청 수 (IP + API 키 기준)
data.gateway.slow.query.ms10000느린 조회 경고 임계 (ms)
data.gateway.slow.update.ms2000느린 갱신 경고 임계 (ms)
data.gateway.async.timeout.ms60000비동기 타임아웃 (ms)

plantpulse-datalake-admin-api.properties​

단일 노드(type=MASTER) 기준 각 서비스의 JMX/관리 엔드포인트 모음이다. 키에 점(.)이 아니라 언더스코어(_) 를 쓰는 유일한 파일이다.

프로퍼티기본값설명
typeMASTER단일 노드 또는 클러스터 마스터
db_typeCASSANDRA모니터링 대상 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} · 1Aster TSDB 접속
tse_host · tse_port · tse_protocol · tse_username · tse_password${PP_TSE_*} · 7801 · https · tse · tse123!TSE 접속(메트릭 적재)
kafka_jmx_uriservice:jmx:rmi:///jndi/rmi://${PP_KAFKA_HOST}:7299/jmxrmiKafka JMX
mqtt_jmx_uri...://${PP_MQTT_HOST}:7279/jmxrmiHiveMQ JMX
cep_jmx_uri...://${PP_HOST_IP}:6499/jmxrmiCEP JMX
datagateway_jmx_uri...://${PP_HOST_IP}:7499/jmxrmiData Gateway JMX
sql_jmx_uri...://${PP_HOST_IP}:7599/jmxrmiSQL JMX
tse_jmx_uri...://${PP_HOST_IP}:7899/jmxrmiTSE JMX
cassandra_jmx_uri...://${PP_CASSANDRA_HOST}:7199/jmxrmiAster TSDB JMX
spark_jmx_uri...://${PP_SPARK_HOST}:10010/jmxrmiSpark JMX
redis_jmx_uriredis://${PP_REDIS_HOST}:${PP_REDIS_PORT}?password=...Valkey 접속 URI
redis_ssl_truststore_location / _password / _type / redis_ssl_endpoint_identification_enabledp12 · ${PP_TLS_TRUSTSTORE_PASSWORD:kopens123!} · PKCS12 · falseValkey TLS
postgres_jmx_urijdbc:postgresql://.../${PP_DB_NAME}?user=...&password=...PostgreSQL 접속 URI

JMX 포트 요약: HiveMQ 7279, Kafka 7299, CEP 6499, Data Gateway 7499, SQL 7599, TSE 7899, Aster TSDB 7199, Spark 10010.

plantpulse-warehouse.properties​

Aster TSDB → Iceberg(S3) 아카이브 배치. 이 파일만 키가 대문자 스네이크(UPPER_SNAKE) 다.

그룹주요 키기본값
TemporalTEMPORAL_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-ARCHIVER-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 · TIMEZONE2 · 20 · 0(일요일) · 3 · 0 · ${PP_TZ}
실행 모드ARCHIVER_MODESHELL (또는 KESTRA)
KestraKESTRA_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
SparkSPARK_APP_NAME · SPARK_MASTER · SPARK_JAR_PATH · SPARK_DRIVER_MEMORY · SPARK_EXECUTOR_MEMORY · SPARK_EXECUTOR_CORES · SPARK_NUM_EXECUTORS · ARCHIVER_PARALLELISM · SPARK_CHECKPOINT_DIRPP-SPARK-S3-LAKEHOUSE · local[*] · .../plantpulse-warehouse-s3.jar · 2g · 4g · 4 · 3 · 4 · s3a://${PP_S3_BUCKET:-plantpulse}/spark-checkpoint/
소스/타깃CASSANDRA_CATALOG · CASSANDRA_DATABASE · S3_BUCKET · ICEBERG_CATALOG · ICEBERG_DATABASEcassandra · ${PP_SCHEME:pp} · ${PP_S3_BUCKET:-plantpulse} · spark_catalog · ${PP_SCHEME:pp}
최적화SNAPSHOT_RETENTION_DAYS · OPTIMIZER_MIN_INPUT_FILES · OPTIMIZER_TARGET_FILE_SIZE_BYTES3 · 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_SECONDS12/12/12 · 8/7/12 · 3 · 12 · 8 · 21600(6h) · 25200(7h) · 60
웹WEB_SERVER_PORT9600

메시징 / 인증 소스 템플릿​

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_port8888
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 는 버퍼 역할이고 영속화는 Aster TSDB/TSE 가 맡는다는 전제다. 컨슈머가 1시간 이상 멈추면 데이터가 유실된다.

플러그인 템플릿​

plantpulse-plugin-opcua.properties — PostgreSQL / Aster TSDB / Valkey / Kafka 접속 + OPC UA 서버 엔드포인트.

프로퍼티기본값설명
kafka.topicpp-tag-point⚠️ 리터럴 — ${PP_TOPIC_PREFIX} 치환이 아니다
kafka.thread · kafka.group.id8 · opcua-plugin-group
opc.ua.server.domain · opc.ua.server.port${PP_HOST_IP} · 8007
opc.ua.server.user · password · anonymousopcua · 설치-시-변경 · false
opc.ua.server.tcp.port · tls.port${PP_OPCUA_TCP_PORT:11004} · ${PP_OPCUA_TLS_PORT:11005}
redis.thread · redis.ssl.enabled4 · 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.count8 · 1000
group.id · auto.offset.reset · enable.auto.commitpp-plugin-aas-server · earliest · false
session.timeout.ms · auto.commit.interval.ms30000 · 1000
plugin.message.listenerplantpulse.plugin.opcua.messaging.KafkaPluginMessageListener

BaSyx V2 의 registry/AAS 포트는 설정이 아니라 코드 하드코딩이다 — AASServer.java 의 REGISTRY_PORT=4800, AAS_PORT=4801.


템플릿에 없지만 코드가 읽는 엔진 키​

EngineConfig 는 아래 키들도 읽는다. 템플릿(plantpulse-engine.properties)에는 없으므로 평소에는 코드 기본값이 적용되며, 값을 바꾸려면 plantpulse-server/config/plantpulse-engine.properties 에 직접 줄을 추가해야 한다.

엣지 시계 / 상태 폴링​

프로퍼티코드 기본값
edge.clock.poll.term.sec60
edge.clock.skew.threshold.ms10000
edge.clock.rtt.max.ms2000
edge.clock.autosync.enabledtrue
edge.clock.autosync.cooldown.ms600000
edge.clock.warn.cooldown.ms600000
edge.clock.skip.warn.count5
edge.status.poll.seconds30
edge.status.poll.jitter.max.ms3000

edge.clock.poll.term.sec 와 edge.status.poll.seconds 는 스케줄러 잡 주기를 결정한다 — 값 제약은 스케줄러 아키텍처 의 Edge 절 참고.

DDS / 이벤트버스 / 푸시 / 버퍼​

프로퍼티코드 기본값
engine.dds.queue.size80000
engine.dds.worker.threads4
engine.dds.latency.warn.ms1000
engine.eventbus.queue.capacity65536
engine.push.threads4
engine.push.queue.size10000
engine.storage.buffer.typeKAFKA
engine.streaming.timeout.backup.queue.capacity12000000

engine.dds.enabled · engine.dds.data.tag.enabled · engine.dds.data.asset.enabled 의 코드 기본값은 false 다. 템플릿이 true 로 명시하고 있기 때문에 배포본에서만 켜져 있다 — 이 세 줄을 지우면 DDS 가 조용히 꺼진다.

잡 스레드 (템플릿 미기재분)​

프로퍼티코드 기본값
engine.job.thread.oee10
engine.job.thread.ram5
engine.job.thread.ems5
engine.job.thread.system4
engine.job.asset.slow.threshold.ms20000

⚠️ engine.job.thread.point 의 코드 기본값은 4 인데 템플릿은 8 이다(engine.job.thread.asset 은 양쪽 8 로 일치). 템플릿 줄을 지우면 값이 절반으로 떨어진다.

Flow 엔진 (템플릿 미기재분)​

프로퍼티코드 기본값
flow.engine.enabledtrue
flow.executor.parallelism64
flow.executor.queue.capacity10000
flow.executor.queue.size10000
flow.executor.poll.timeout.ms50
flow.scheduler.pool.size4
flow.timer.pool.size2
flow.jdbc.trigger.pool.size2
flow.shutdown.timeout.sec5
flow.enabled.cache.ttl.ms5000
flow.webhook.auth.enabledtrue

알람 / ISO 지표 / OEE​

프로퍼티코드 기본값
alarm.duplicate.check.minutes10
engine.oee.debounce.ms100
iso.oee.rolling.window.minutes10
iso.ems.rolling.window.minutes10
iso.ram.rolling.window.minutes1440

이상 탐지 상세 (에셋 포인트 / 시스템)​

engine.data.anomaly.enabled=true 로 켰을 때만 의미가 있다.

프로퍼티코드 기본값
engine.data.anomaly.asset.point.intervalMINUTE
engine.data.anomaly.asset.point.lookback.minutes14400
engine.data.anomaly.asset.point.recent.seconds600
engine.data.anomaly.asset.point.limit2100
engine.data.anomaly.asset.point.context.length2048
engine.data.anomaly.asset.point.prediction.length96
engine.data.anomaly.asset.point.score.history60
engine.data.anomaly.asset.point.threshold.k3.5
engine.data.anomaly.asset.point.threshold.min0.80
engine.data.anomaly.asset.point.threshold.max0.98
engine.data.anomaly.asset.point.topk.request5
engine.data.anomaly.asset.point.topn.report5
engine.data.anomaly.system.lookback.minutes1440
engine.data.anomaly.system.recent.seconds60
engine.data.anomaly.system.limit2100
engine.data.anomaly.system.context.length2048
engine.data.anomaly.system.pred.length96
engine.data.anomaly.system.threshold.min0.80
engine.data.anomaly.system.topk2

존재하지 않는 설정​

아래 이름들은 과거 문서·외부 자료에 등장하지만 템플릿에도 코드에도 없다. 이 이름으로 설정을 추가해도 아무 효과가 없다.

찾던 것실제 위치
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 / .algorithmstorage.compression.zstd.level / storage.compression.zstd.type (템플릿 줄은 오타 — 오타 키 경고)
storage.compaction.enable / .schedulestorage.table.compaction.strategy 계열 (Compaction 절)
storage.metastore.* / storage.cache.*없음
mq.type / mq.kafka.bootstrap.servers / mq.kafka.group.idmq.host + mq.kafka.port. 컨슈머 그룹은 설정이 아니라 코드 상수(PP-KAFKA-POINT-GROUP 등, 메시징 아키텍처)
mail.* 를 파일에서pp.mm_config 한 곳(2026-09-17 이관, 파일은 삭제)
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.serverengine.ntpdate.sync / engine.ntpdate.server.ip
engine.cep.enable / engine.cep.host / engine.cep.portengine.cep.server.ip / engine.cep.server.port / engine.cep.server.protocol
engine.anomaly.*engine.data.anomaly.*
engine.dds.enable / engine.dds.topic.prefixengine.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.propertiesmetastore.password · cache.password · cache.ssl.truststore.password · storage.password · tse.password · data.gateway.api.key
plantpulse-engine.propertiesapi.key · flow.webhook.api.key · engine.cep.server.api.key
plantpulse-mq.propertiesmq.password · mq.ssl.truststore.password
pp.mm_config (메일)mail.smtp.password
pp.mm_config (AI)ai.llm.api.key — 옛 이름 ai.openai.* 의 폴백은 두지 않습니다
plantpulse-cep.propertiescache.password · storage.password · cep.api.key
plantpulse-batch.propertiesmetastore.password · cache.password · tse.password · mq.password · storage.db.password · analytics.password · external.db.password
plantpulse-jdbc.propertiescache.password · jdbc.postgres.password · jdbc.cassandra.password · jdbc.tse.password · jdbc.spark.password · data.gateway.api.key
plantpulse-data-gateway.propertiesdata.gateway.api.key
plantpulse-datalake-admin-api.propertiesdb_password · tse_password · redis_jmx_uri(URL 내 password) · redis_ssl_truststore_password · postgres_jmx_uri(URL 내 password)
plantpulse-mqtt.properties · plantpulse-mq-auth.propertiesmqtt.password
plantpulse-plugin-opcua.propertiespostgres.password · cassandra.password · redis.password · kafka.password · opc.ua.server.password
plantpulse-plugin-aas.propertiesaas.db.password · cassandra.password · kafka.password
kafka.propertiesssl.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 하다 즉사해 배포가 실패한다.

권장 조치​

비밀은 설정 파일에 적지 않습니다. 사이드카 파일 하나에 모으고 0600 으로 둡니다.

ls -l /etc/kopens/plantpulse-platform.env # 비밀 — 0600, repo 밖
ls -l /etc/kopens/platform.node.env # 이 박스 고유 값 — 0600

# 값을 바꿀 때는 파일을 열지 말고 도구를 씁니다
cd /opt/kopens/plantpulse-platform-docker
bin/passwd.sh --list # 바꿀 수 있는 키
bin/passwd.sh PP_PG_PASSWORD # 서버 계정 변경 → 사이드카 → 재렌더 → 재시작

렌더된 설정 파일에는 치환이 끝난 값이 들어가므로, 그 파일을 저장소에 커밋하지 않습니다.