> 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/admin/modules/server.md).

# server (웹 콘솔)

## 역할

플랫폼의 **얼굴이자 두뇌**에 해당하는 핵심 모듈입니다. 운영자가 보는 웹 콘솔, 외부 시스템이 호출하는 REST API, 그리고 산업 데이터를 실제로 처리하는 IIoT 엔진이 모두 이 한 모듈 안에서 동작합니다.

| 항목    | 값                                                    |
| ----- | ---------------------------------------------------- |
| 모듈명   | `plantpulse-server`                                  |
| 설치 경로 | `/opt/kopens/plantpulse-platform/plantpulse-server/` |
| 외부 포트 | **80** (HTTP), **443** (HTTPS)                       |
| 관리 포트 | **7443** (HTTPS 관리 콘솔)                               |
| 내부 포트 | 7000 (셧다운), 8000 (WebSocket), 8004 (WebSocket TLS)   |
| 런타임   | Apache Tomcat 10 + Java 21                           |
| 처리량   | 초당 40,000건 메시지 (36스레드 파이프라인)                         |

## 책임 영역

```mermaid
graph TB
  subgraph IN["입력"]
    KAFKA[Kafka 토픽]
    REST[REST API 호출]
    WS[WebSocket]
  end

  subgraph SERVER["plantpulse-server"]
    PIPE[IIoT 엔진<br/>36 스레드]
    CEP_INT[내장 CEP 클라이언트]
    APP_LOGIC[비즈니스 로직<br/>Spring MVC]
    CONSOLE[JSP 콘솔]
    SCHED[Quartz 스케줄러]
  end

  subgraph OUT["출력"]
    CASS[(Cassandra)]
    PG[(PostgreSQL)]
    VALKEY[(Valkey)]
    KAFKA_OUT[Kafka 토픽]
    BROWSER[브라우저]
  end

  KAFKA --> PIPE
  REST --> APP_LOGIC
  WS --> CONSOLE
  PIPE --> CASS
  PIPE --> KAFKA_OUT
  PIPE --> CEP_INT
  APP_LOGIC --> PG
  APP_LOGIC --> VALKEY
  APP_LOGIC --> CONSOLE
  CONSOLE --> BROWSER
  SCHED --> APP_LOGIC
```

## 디렉토리 구조

```
plantpulse-server/
├── app/                                       # Tomcat webapps
│   └── plantpulse-server-web/                 # 웹 애플리케이션 (펼쳐진 WAR)
│       ├── WEB-INF/
│       │   ├── classes/
│       │   │   ├── application.properties     # 핵심 설정
│       │   │   ├── plantpulse-engine.properties     # IIoT 엔진 튜닝
│       │   │   ├── plantpulse-storage.properties    # DB 연결
│       │   │   ├── plantpulse-mq.properties         # 메시징 연결
│       │   │   ├── plantpulse-mail.properties       # SMTP
│       │   │   ├── plantpulse-websocket.properties  # 실시간 푸시
│       │   │   ├── plantpulse-ai.properties         # AI 게이트웨이
│       │   │   └── quartz.properties                # 스케줄러
│       │   ├── lib/                           # Jar 라이브러리
│       │   └── web.xml
│       ├── WEB-INF/jsp/                       # 콘솔 JSP
│       └── resources/                         # 정적 자원
├── bin/
│   ├── start.sh
│   ├── stop.sh
│   └── log-viewer.sh
├── logs/
│   └── system.log
├── path/                                       # 경로 매핑
└── server/                                     # 내장 Tomcat
    └── conf/
        ├── server.xml                          # 커넥터 / 포트
        ├── context.xml                         # 컨텍스트 / 데이터소스
        ├── catalina.properties
        ├── logging.properties
        ├── tomcat-users.xml
        ├── web.xml
        └── Catalina/localhost/                 # 가상 호스트 컨텍스트
```

## 주요 설정 파일

### application.properties

콘솔 전반의 동작을 결정하는 핵심 설정입니다.

| 항목                                | 설명                    |
| --------------------------------- | --------------------- |
| `pp.service.ip`                   | 외부 접속 IP / 도메인        |
| `pp.session.timeout`              | 세션 타임아웃 (기본 30분)      |
| `pp.locale`                       | 기본 로케일 (`ko` / `en`)  |
| `pp.timezone`                     | 타임존 (기본 `Asia/Seoul`) |
| `pp.console.theme`                | 콘솔 테마 (light / dark)  |
| `pp.security.password.min`        | 비밀번호 최소 길이            |
| `pp.security.login.lock.attempts` | 로그인 실패 잠금 횟수          |

### plantpulse-engine.properties

IIoT 엔진 파이프라인 튜닝.

| 항목                               | 기본값    | 설명          |
| -------------------------------- | ------ | ----------- |
| `engine.pipeline.threads`        | 36     | 병렬 처리 스레드 수 |
| `engine.pipeline.ratelimit`      | 50000  | 초당 최대 메시지   |
| `engine.pipeline.batch.size`     | 1000   | 배치 묶음 크기    |
| `engine.pipeline.queue.capacity` | 100000 | 큐 용량        |
| `engine.dedup.enabled`           | true   | 중복 제거 활성화   |

### plantpulse-storage.properties

데이터 저장소 연결.

```properties
# Cassandra
cassandra.host=${PP_CASSANDRA_HOST}
cassandra.port=${PP_CASSANDRA_PORT}
cassandra.keyspace=${PP_KEYSPACE}
cassandra.user=${PP_CASSANDRA_USER}
cassandra.password=${PP_CASSANDRA_PASSWORD}

# PostgreSQL (Spring DataSource)
postgres.url=jdbc:postgresql://${PP_POSTGRES_HOST}:${PP_POSTGRES_PORT}/${PP_DB_NAME}
postgres.user=${PP_PG_USER}
postgres.password=${PP_PG_PASSWORD}

# Valkey
redis.host=${PP_REDIS_HOST}
redis.port=${PP_REDIS_PORT}
redis.password=${PP_REDIS_PASSWORD}
```

> **자동 생성**: 이 파일들은 `plantpulse-startup/configure.sh` 가 `env.sh` 의 값을 치환해서 생성합니다. 직접 편집 후 재시작하려면 `env.sh` 를 수정한 뒤 `./configure.sh && ./restart-server.sh` 순서로 적용해야 합니다.

### server/conf/server.xml

Tomcat 커넥터 설정. 포트 변경 / TLS / 압축 / 스레드 풀.

```xml
<Connector port="80" protocol="HTTP/1.1"
           connectionTimeout="20000"
           maxThreads="500"
           acceptCount="200"
           URIEncoding="UTF-8"
           compression="on"
           compressibleMimeType="text/html,text/css,application/json,application/javascript" />

<Connector port="443" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
           SSLEnabled="true"
           maxThreads="500"
           sslEnabledProtocols="TLSv1.3,TLSv1.2">
    <SSLHostConfig>
        <Certificate certificateKeystoreFile="/var/security/plantpulse/server.jks"
                     certificateKeystorePassword="${PP_TLS_KEYSTORE_PASSWORD}" />
    </SSLHostConfig>
</Connector>
```

## 운영 명령

### 개별 시작 / 정지 / 로그

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-server/bin

./start.sh         # 포그라운드 (개발 / 검증용)
./stop.sh          # 정지
./log-viewer.sh    # 실시간 로그
```

### 권장: 통합 스크립트 사용

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

./restart-server.sh    # 서버만 재시작
./status.sh            # 전체 상태 — port 80 RUNNING 확인
./log-viewer.sh        # 통합 로그 뷰어
```

### 핫 리로드 (재시작 없이 설정 반영)

일부 설정은 콘솔의 **시스템 > 설정 관리** 메뉴에서 핫 리로드가 가능합니다. `application.properties` / `server.xml` 등 부팅 시점 설정은 재시작이 필요합니다.

## 로그

| 로그              | 경로                                                | 내용            |
| --------------- | ------------------------------------------------- | ------------- |
| 메인 로그           | `logs/system.log`                                 | 애플리케이션 로직, 에러 |
| Tomcat catalina | `server/logs/catalina.out`                        | Tomcat 표준 출력  |
| 액세스 로그          | `server/logs/localhost_access_log.YYYY-MM-DD.txt` | HTTP 요청 로그    |
| 엔진 로그           | `logs/engine.log`                                 | IIoT 엔진 처리 상세 |
| 슬로우 쿼리          | `logs/slow.log`                                   | 200ms 이상 쿼리   |

로그 레벨 변경:

```bash
# logback 설정 (재시작 불필요 - 30초 후 자동 반영)
vi /opt/kopens/plantpulse-platform/plantpulse-server/app/plantpulse-server-web/WEB-INF/classes/logback.xml

<logger name="plantpulse" level="DEBUG"/>
```

## 성능 튜닝

### JVM 힙

```bash
# server/bin/setenv.sh (없으면 생성)
export CATALINA_OPTS="-Xms16g -Xmx32g \
  -XX:+UseG1GC -XX:MaxGCPauseMillis=200 \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/var/log/plantpulse/heap/ \
  -Xlog:gc*:file=/var/log/plantpulse/gc.log:time,uptime:filecount=10,filesize=100M"
```

### Tomcat 스레드 풀

`server.xml` 의 Connector 에서 `maxThreads` / `acceptCount` 조정. 대규모 동시 접속 환경에서는 다음을 권장합니다.

| 동시 접속  | maxThreads | acceptCount |
| ------ | ---------- | ----------- |
| \~ 100 | 200        | 100         |
| \~ 500 | 500        | 200         |
| 500+   | 1000       | 500         |

### IIoT 엔진 처리량

`plantpulse-engine.properties` 의 `engine.pipeline.threads` 를 호스트 코어 수의 70\~80% 로 설정. 메시지 적체 시 `engine.pipeline.queue.capacity` 도 함께 상향.

자세한 튜닝은 [성능 튜닝](/plantpulse-platform/admin/performance-tuning.md) 페이지를 참고해 주세요.

## 헬스 체크

```bash
# 콘솔 ping
curl -fsS http://127.0.0.1/api/v5/ping

# 인증 필요 헬스체크
curl -fsS -u admin:admin123! http://127.0.0.1/api/v5/health

# WebSocket 핸드셰이크 확인
curl -i -N \
  -H "Connection: Upgrade" -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==" \
  -H "Sec-WebSocket-Version: 13" \
  http://127.0.0.1:8000/ws
```

## 자주 발생하는 문제

| 증상                    | 원인               | 조치                                                                |
| --------------------- | ---------------- | ----------------------------------------------------------------- |
| `OutOfMemoryError`    | 힙 부족             | `setenv.sh` 에서 `-Xmx` 상향 + GC 로그 분석                               |
| `Too many open files` | 파일 디스크립터 한계      | `/etc/security/limits.conf` 의 `nofile` 65535+                     |
| 콘솔 응답 느림              | DB 슬로우 쿼리        | PostgreSQL slow query 로그, Valkey 캐시 적중률 확인                        |
| 로그인 무한 루프             | 세션 / 쿠키 문제       | 브라우저 캐시 삭제, `application.properties` 의 `session.cookie.domain` 확인 |
| 502 / 504 (리버스 프록시)   | 백엔드 응답 시간 초과     | nginx `proxy_read_timeout` 상향                                     |
| WebSocket 끊김          | 방화벽 idle timeout | 방화벽 timeout > 60s, `tomcat.websocket.session.timeout` 조정          |

상세 진단은 [문제 해결](/plantpulse-platform/admin/troubleshooting.md) 페이지를 참고해 주세요.

## 보안 체크리스트

* [ ] 기본 admin 비밀번호 변경 (`admin / admin123!`)
* [ ] `tomcat-users.xml` 의 manager 계정 제거 또는 강한 비밀번호
* [ ] `server.xml` 의 `shutdown port (7000)` 외부 접근 차단
* [ ] HTTPS 인증서 적용 (`prepare-ssl.sh` 결과 또는 외부 CA)
* [ ] X-Frame-Options / CSP / HSTS 헤더 설정 확인
* [ ] API Bearer Token 운영 vault 에 저장
* [ ] `applicaction.properties` 의 디버그 옵션 비활성화

자세한 보안 설정은 [보안 설정](/plantpulse-platform/admin/security.md) 페이지를 참고해 주세요.

## 관련 문서

* [모듈 인덱스](/plantpulse-platform/admin/modules.md)
* [성능 튜닝](/plantpulse-platform/admin/performance-tuning.md)
* [백업 및 복구](/plantpulse-platform/admin/backup-recovery.md)
* [문제 해결](/plantpulse-platform/admin/troubleshooting.md)
* [개발자 API 사용 매뉴얼](/plantpulse-platform/developer/api-manual.md)
