> 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/engine-lifecycle.md).

# 엔진 라이프사이클

## 개요 <a href="#overview" id="overview"></a>

이 문서에서는 플랜트펄스 엔진의 9단계 초기화 시퀀스와 종료 시퀀스를 안내합니다. 엔진은 Tomcat의 `ServletContextListener`를 통해 시작되며, 엄격한 순서에 따라 각 컴포넌트를 초기화합니다.

## 아키텍처 개요 다이어그램 <a href="#architecture-diagram" id="architecture-diagram"></a>

```mermaid
flowchart TD
  TC[Tomcat Start]
  LL[LifecycleListener<br/>ServletContextListener]
  TC --> LL --> INIT

  subgraph INIT["Engine Initialization (9 Phases)"]
    P1[Phase 1 코어 인프라<br/>OSEnv · AsyncWorkerPool<br/>TimerPool · DAOFactory · Redis]
    P2[Phase 2 메트릭 & 설정<br/>MetricRegistry · DataFlow<br/>DDS · MessageBroker]
    P3[Phase 3 외부 서비스<br/>CEP · Quartz · Metastore<br/>Security · TimeSeriesDB]
    P4[Phase 4 스트림 & 스토리지<br/>StreamProcessor · StorageProcessor<br/>Pipeline]
    P5[Phase 5 캐시 배포<br/>Site/Asset/OPC/Tag<br/>SiteStats/SiteArch/Report]
    P6[Phase 6 복구 & 리스너<br/>PointMapRecovery<br/>MessageListener · DDS Recovery]
    P7[Phase 7 디플로이어<br/>30+ Deployers<br/>Point/Tag/OPC/Edge/...]
    P8[Phase 8 스케줄러 & 모니터링<br/>22 Monitoring Timers]
    P9[Phase 9 started = true]

    P1 --> P2 --> P3 --> P4 --> P5 --> P6 --> P7 --> P8 --> P9
  end

  INIT --> READY[Engine Ready<br/>서비스 시작]
```

## 엔트리 포인트 <a href="#entry-point" id="entry-point"></a>

### LifecycleListener

`LifecycleListener`는 Tomcat의 `ServletContextListener`를 구현한 엔진의 엔트리 포인트입니다.

```java
public class LifecycleListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 9 Phase 초기화 시퀀스 시작
        EngineBootstrap.start();
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 23단계 종료 시퀀스 시작
        EngineBootstrap.shutdown();
    }
}
```

`web.xml`에 리스너로 등록되어 있으며, Tomcat 컨텍스트 시작 시 자동으로 호출됩니다.

## 9 Phase 초기화 시퀀스 <a href="#init-sequence" id="init-sequence"></a>

### Phase 1: 코어 인프라 <a href="#phase-1" id="phase-1"></a>

플랫폼 운영에 필요한 기본 인프라를 초기화합니다.

| 순서  | 컴포넌트              | 설명                                                    |
| --- | ----------------- | ----------------------------------------------------- |
| 1-1 | `OSEnv`           | 운영체제 환경 정보를 수집합니다 (CPU, 메모리, 디스크, OS 종류 등)            |
| 1-2 | `AsyncWorkerPool` | 비동기 작업 처리를 위한 공용 스레드 풀을 생성합니다                         |
| 1-3 | `TimerPool`       | 주기적 타이머 작업을 위한 스케줄드 스레드 풀을 생성합니다                      |
| 1-4 | `DAOFactory`      | 데이터 접근 객체(DAO) 팩토리를 초기화합니다 (PostgreSQL, Cassandra 연결) |
| 1-5 | `Redis`           | Redis(Valkey) 클라이언트 연결을 수립합니다                         |

이 단계에서 실패하면 엔진이 시작되지 않습니다. 특히 데이터베이스와 Redis 연결은 필수 요건입니다.

### Phase 2: 메트릭 및 설정 <a href="#phase-2" id="phase-2"></a>

메트릭 수집 체계와 핵심 설정을 로드합니다.

| 순서  | 컴포넌트             | 설명                                       |
| --- | ---------------- | ---------------------------------------- |
| 2-1 | `MetricRegistry` | Dropwizard Metrics 레지스트리를 초기화합니다         |
| 2-2 | `DataFlow`       | DataFlow 6단계 파이프라인 설정을 로드합니다             |
| 2-3 | `DDS`            | DDS(Data Distribution Service) 설정을 로드합니다 |
| 2-4 | `MessageBroker`  | 멀티 프로토콜 메시지 브로커 설정을 로드합니다                |

### Phase 3: 외부 서비스 <a href="#phase-3" id="phase-3"></a>

외부 시스템과의 연동을 초기화합니다.

| 순서  | 컴포넌트                  | 설명                             |
| --- | --------------------- | ------------------------------ |
| 3-1 | `CEP`                 | 복합 이벤트 처리(CEP) 엔진을 초기화합니다      |
| 3-2 | `Quartz`              | Quartz 스케줄러를 초기화합니다            |
| 3-3 | `MetastoreDataSource` | 메타스토어(Gravitino) 데이터 소스를 연결합니다 |
| 3-4 | `Security`            | 보안 컨텍스트(인증/인가)를 초기화합니다         |
| 3-5 | `TimeSeriesDB`        | 시계열 데이터베이스 연결을 수립합니다           |

### Phase 4: 스트림 및 스토리지 <a href="#phase-4" id="phase-4"></a>

데이터 처리의 핵심인 스트림 프로세서와 스토리지 프로세서를 초기화합니다.

| 순서  | 컴포넌트               | 설명                                                     |
| --- | ------------------ | ------------------------------------------------------ |
| 4-1 | `StreamProcessor`  | 실시간 스트림 처리 엔진을 초기화합니다                                  |
| 4-2 | `StorageProcessor` | Cassandra 스토리지 프로세서를 초기화합니다                            |
| 4-3 | `Pipeline`         | 파이프라인 엔진(ShardRouter, PipelineQueue, DataFlow)을 초기화합니다 |

이 단계가 완료되면 데이터 수신 및 처리 준비가 완료됩니다.

### Phase 5: 캐시 배포 <a href="#phase-5" id="phase-5"></a>

운영에 필요한 7종의 캐시를 데이터베이스로부터 로드합니다.

| 순서  | 캐시               | 설명                 |
| --- | ---------------- | ------------------ |
| 5-1 | `SiteCache`      | 사이트 정보 캐시입니다       |
| 5-2 | `AssetCache`     | 에셋(설비) 정보 캐시입니다    |
| 5-3 | `OPCCache`       | OPC 연결 정보 캐시입니다    |
| 5-4 | `TagCache`       | 태그 메타정보 캐시입니다      |
| 5-5 | `SiteStatsCache` | 사이트 통계 캐시입니다       |
| 5-6 | `SiteArchCache`  | 사이트 아키텍처(계층) 캐시입니다 |
| 5-7 | `ReportCache`    | 리포트 설정 캐시입니다       |

캐시 로드 완료 후에야 데이터 파이프라인의 Prepare 스테이지에서 도메인 보강이 정상 동작합니다.

### Phase 6: 복구 및 리스너 <a href="#phase-6" id="phase-6"></a>

이전 실행 시 미처리된 데이터를 복구하고, 메시지 리스너를 시작합니다.

| 순서  | 컴포넌트               | 설명                                   |
| --- | ------------------ | ------------------------------------ |
| 6-1 | `PointMapRecovery` | 포인트맵 불일치를 검사하고 복구합니다                 |
| 6-2 | `MessageListener`  | Kafka/MQTT/STOMP/HTTP 메시지 리스너를 시작합니다 |
| 6-3 | `DDS Recovery`     | DDS 타임아웃 백업 데이터를 재처리합니다              |

이 단계에서 메시지 리스너가 시작되면 실제 데이터 수신이 시작됩니다.

### Phase 7: 디플로이어 <a href="#phase-7" id="phase-7"></a>

30개 이상의 디플로이어를 실행하여 등록된 자원을 활성화합니다.

| 디플로이어 그룹        | 설명                     |
| --------------- | ---------------------- |
| Point Deployer  | 등록된 포인트를 활성화합니다        |
| Tag Deployer    | 태그를 파이프라인에 매핑합니다       |
| OPC Deployer    | OPC 연결을 수립하고 폴링을 시작합니다 |
| Edge Deployer   | 엣지 디바이스를 등록합니다         |
| Asset Deployer  | 에셋 계층 구조를 빌드합니다        |
| System Deployer | 시스템 모니터링 잡을 배포합니다      |
| Report Deployer | 리포트 잡을 배포합니다           |

각 디플로이어는 데이터베이스에서 설정 정보를 읽어 해당 자원을 런타임에 배포합니다.

### Phase 8: 스케줄러 및 모니터링 <a href="#phase-8" id="phase-8"></a>

주기적 잡 스케줄러와 모니터링 타이머를 시작합니다.

| 항목             | 설명                                                  |
| -------------- | --------------------------------------------------- |
| Quartz 스케줄러 시작 | 배포된 모든 잡의 트리거를 활성화합니다                               |
| 22개 모니터링 타이머   | CPU, 메모리, GC, 디스크, 스레드, 큐, 파이프라인 등의 상태를 주기적으로 수집합니다 |

### Phase 9: started = true <a href="#phase-9" id="phase-9"></a>

모든 초기화가 완료되면 `started` 플래그를 `true`로 설정합니다. 이 플래그는 헬스 체크 엔드포인트와 로드 밸런서에서 참조합니다.

```
Phase 1 ~ Phase 8 완료
    │
    ▼
Engine.started = true
    │
    ├── Health Check: /api/health → 200 OK
    └── 로드 밸런서 트래픽 수신 시작
```

## 종료 시퀀스 <a href="#shutdown-sequence" id="shutdown-sequence"></a>

엔진 종료 시에는 초기화의 역순으로 23단계에 걸쳐 안전하게 셧다운합니다.

| 단계 | 동작                 | 설명                              |
| -- | ------------------ | ------------------------------- |
| 1  | `started = false`  | 신규 요청 수신을 중단합니다                 |
| 2  | 모니터링 타이머 중지        | 22개 모니터링 타이머를 중지합니다             |
| 3  | 스케줄러 중지            | Quartz 스케줄러를 셧다운합니다             |
| 4  | 디플로이어 언디플로이        | 배포된 자원을 해제합니다                   |
| 5  | 메시지 리스너 중지         | 데이터 수신을 중단합니다                   |
| 6  | DDS 중지             | DDS 발행을 중단합니다                   |
| 7  | 파이프라인 드레인          | 큐에 남아있는 데이터를 처리 완료합니다           |
| 8  | 파이프라인 중지           | 파이프라인 엔진을 중지합니다                 |
| 9  | 스트림 프로세서 중지        | 스트림 처리를 중단합니다                   |
| 10 | 스토리지 프로세서 플러시      | 미저장 데이터를 Cassandra에 플러시합니다      |
| 11 | 스토리지 프로세서 중지       | 스토리지 연결을 종료합니다                  |
| 12 | CEP 중지             | CEP 엔진을 중지합니다                   |
| 13 | 캐시 클리어             | 7종 인메모리 캐시를 해제합니다               |
| 14 | 리포트 플러시            | 인메모리 리포트 카운터를 Cassandra에 플러시합니다 |
| 15 | TimeSeriesDB 중지    | 시계열 DB 연결을 종료합니다                |
| 16 | MetricRegistry 중지  | 메트릭 레지스트리를 셧다운합니다               |
| 17 | 오프로드 큐 플러시         | RocksDB 오프로드 큐를 플러시합니다          |
| 18 | Redis 중지           | Redis 클라이언트 연결을 종료합니다           |
| 19 | Kafka 중지           | Kafka Producer/Consumer를 종료합니다  |
| 20 | MQTT 중지            | MQTT 클라이언트를 종료합니다               |
| 21 | DAOFactory 중지      | 데이터베이스 연결 풀을 종료합니다              |
| 22 | AsyncWorkerPool 중지 | 비동기 워커 스레드 풀을 종료합니다             |
| 23 | TimerPool 중지       | 타이머 스레드 풀을 종료합니다                |

종료 시 가장 중요한 것은 **파이프라인 드레인**(7단계)과 **스토리지 플러시**(10단계)입니다. 이 두 단계를 통해 메모리에 남아있는 데이터가 유실되지 않도록 보장합니다.

## 캐시 계층 <a href="#cache-layers" id="cache-layers"></a>

엔진은 7종의 캐시 매니저를 운영하며, 각 캐시는 독립적인 라이프사이클을 가집니다.

```
┌────────────────────────────────────────────────────────┐
│                  Cache Hierarchy                        │
│                                                         │
│  L1: In-Memory Cache (ConcurrentHashMap)               │
│      ├── SiteCache          (사이트 정보)                │
│      ├── AssetCache         (에셋/설비 정보)             │
│      ├── OPCCache           (OPC 연결 정보)              │
│      ├── TagCache           (태그 메타정보)               │
│      ├── SiteStatsCache     (사이트 통계)                │
│      ├── SiteArchCache      (사이트 계층 구조)            │
│      └── ReportCache        (리포트 설정)                │
│                                                         │
│  L2: Redis (Valkey)                                     │
│      └── 분산 캐시 (클러스터 환경 시)                     │
│                                                         │
│  L3: Database (PostgreSQL / Cassandra)                  │
│      └── 원본 데이터                                     │
└────────────────────────────────────────────────────────┘
```

| 캐시 매니저           | 데이터 소스     | 갱신 주기 | 용도                                        |
| ---------------- | ---------- | ----- | ----------------------------------------- |
| `SiteCache`      | PostgreSQL | 10분   | 사이트 설정 및 메타정보를 제공합니다                      |
| `AssetCache`     | PostgreSQL | 10분   | 에셋(설비) 계층 정보를 제공합니다                       |
| `OPCCache`       | PostgreSQL | 5분    | OPC 연결 정보를 제공합니다                          |
| `TagCache`       | PostgreSQL | 5분    | 태그 메타정보(타입, 범위, 단위 등)를 제공합니다              |
| `SiteStatsCache` | Cassandra  | 1분    | 사이트 실시간 통계를 제공합니다                         |
| `SiteArchCache`  | PostgreSQL | 10분   | 사이트 계층 구조(Area → Line → Equipment)를 제공합니다 |
| `ReportCache`    | PostgreSQL | 10분   | 리포트 설정 정보를 제공합니다                          |

## 에러 복구 전략 <a href="#error-recovery" id="error-recovery"></a>

초기화 중 발생하는 에러에 대한 복구 전략입니다.

| 에러 유형       | 복구 전략                  | Phase   |
| ----------- | ---------------------- | ------- |
| DB 연결 실패    | 재시도 3회 후 엔진 시작 중단      | Phase 1 |
| Redis 연결 실패 | 재시도 3회 후 엔진 시작 중단      | Phase 1 |
| Kafka 연결 실패 | 백그라운드 재연결 (엔진은 시작)     | Phase 6 |
| MQTT 연결 실패  | 백그라운드 재연결 (엔진은 시작)     | Phase 6 |
| 캐시 로드 실패    | 빈 캐시로 시작, 주기적 리로드 시도   | Phase 5 |
| 디플로이어 실패    | 개별 실패 로깅 후 다음 디플로이어 진행 | Phase 7 |
| 스케줄러 실패     | 재시도 3회 후 해당 잡만 비활성화    | Phase 8 |

DB와 Redis는 필수 의존성으로, 연결에 실패하면 엔진이 시작되지 않습니다. 반면 Kafka, MQTT 등 메시지 브로커는 백그라운드에서 재연결을 시도하므로 엔진 시작에는 영향을 주지 않습니다.
