> 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/api-manual/flow-service.md).

# 16. Flow 서비스

`client.flow()` 으로 접근합니다. PlantPulse의 시각적 워크플로(Flow)와 그 안의 노드(Flow Node)를 조회합니다. V5에서 새로 추가된 서비스입니다.

> **참고**: V5의 Flow 서비스는 **읽기 전용**입니다. Flow 생성/수정/실행은 UI 또는 Flow 엔진 전용 API로 수행하시면 됩니다. 자세한 Flow 엔진 동작 원리는 [플로우 엔진](/plantpulse-platform/developer/flow.md) 문서를 참고하세요.

## 16.1 메서드 일람

| 메서드                  | 반환 타입                          | HTTP | 엔드포인트                    |
| -------------------- | ------------------------------ | ---- | ------------------------ |
| `get(flow_id)`       | `FlowResponseV5` 또는 `null`     | GET  | `/api/v5/flow/{id}`      |
| `list()`             | `List<FlowResponseV5>` (통계 포함) | GET  | `/api/v5/flow`           |
| `listNodes(flow_id)` | `List<FlowNodeResponseV5>`     | GET  | `/api/v5/flow/{id}/node` |

## 16.2 FlowResponseV5 DTO

| 필드                            | 타입      | 설명           |
| ----------------------------- | ------- | ------------ |
| `flow_id`                     | String  | Flow ID (PK) |
| `flow_name`                   | String  | Flow 이름      |
| `description`                 | String  | 설명           |
| `enabled`                     | boolean | 활성화 여부       |
| `is_root`                     | boolean | 루트 Flow 여부   |
| `debug_mode`                  | boolean | 디버그 모드       |
| `insert_user` / `insert_date` | String  | 등록자/시각       |
| `update_user` / `update_date` | String  | 수정자/시각       |
| **`node_count`**              | int     | 노드 수 (통계)    |
| **`trigger_count`**           | int     | 트리거 수 (통계)   |
| **`error_count`**             | long    | 누적 에러 수 (통계) |

## 16.3 FlowNodeResponseV5 DTO

| 필드                          | 타입      | 설명                                  |
| --------------------------- | ------- | ----------------------------------- |
| `flow_node_id`              | String  | 노드 ID (PK)                          |
| `flow_id`                   | String  | 소속 Flow                             |
| `type`                      | String  | 노드 타입 (trigger, function, action 등) |
| `name`                      | String  | 노드 이름                               |
| `configuration_json`        | String  | 노드 설정 JSON 문자열                      |
| `position_x` / `position_y` | int     | 캔버스 위치                              |
| `debug_mode`                | boolean | 노드별 디버그                             |

## 16.4 사용 예시

### Flow 목록 (통계 포함)

```java
import java.util.List;
import plantpulse.api.v5.dto.response.FlowResponseV5;

List<FlowResponseV5> flows = client.flow().list();
for (FlowResponseV5 f : flows) {
    System.out.printf("[%s] %s — 노드 %d개, 트리거 %d개, 에러 %d건%n",
        f.isEnabled() ? "ON" : "OFF",
        f.getFlow_name(),
        f.getNode_count(),
        f.getTrigger_count(),
        f.getError_count());
}
```

출력 예:

```
[ON]  생산 카운트 집계 — 노드 8개, 트리거 1개, 에러 0건
[ON]  알람 알림 라우팅 — 노드 12개, 트리거 3개, 에러 2건
[OFF] (실험) ML 예측 — 노드 5개, 트리거 0개, 에러 0건
```

### 단건 Flow 조회

```java
FlowResponseV5 flow = client.flow().get("flow_001");
if (flow != null && !flow.isEnabled()) {
    System.err.println("Flow가 비활성 상태: " + flow.getFlow_name());
}
```

### Flow의 노드 목록

```java
import plantpulse.api.v5.dto.response.FlowNodeResponseV5;

String flowId = "flow_001";
List<FlowNodeResponseV5> nodes = client.flow().listNodes(flowId);
for (FlowNodeResponseV5 n : nodes) {
    System.out.printf("  [%s] %s (%s)%n",
        n.getType(), n.getName(), n.getFlow_node_id());
}
```

### 에러 발생 Flow 식별

```java
import java.util.stream.Collectors;

List<FlowResponseV5> errored = client.flow().list().stream()
        .filter(f -> f.getError_count() > 0)
        .collect(Collectors.toList());

System.out.println("에러 발생 Flow: " + errored.size() + "개");
for (FlowResponseV5 f : errored) {
    System.out.printf("  %s: %d건%n", f.getFlow_name(), f.getError_count());
}
```

## 16.5 활용 시나리오

### 시나리오 — Flow 헬스 대시보드

```java
while (running) {
    List<FlowResponseV5> all = client.flow().list();

    long total    = all.size();
    long enabled  = all.stream().filter(FlowResponseV5::isEnabled).count();
    long errored  = all.stream().filter(f -> f.getError_count() > 0).count();
    long triggers = all.stream().mapToInt(FlowResponseV5::getTrigger_count).sum();

    updateUI(total, enabled, errored, triggers);
    Thread.sleep(5_000);
}
```

## 다음 단계

* [플로우 엔진 가이드](/plantpulse-platform/developer/flow.md) — Flow 동작 원리 (별도 문서)
* [통합 예제](/plantpulse-platform/developer/api-manual/examples.md) — Flow와 API 연동 예제
