> 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/user-management.md).

# 사용자 관리

## 개요

이 문서에서는 PlantPulse 플랫폼의 사용자 계정, 보안 그룹, 권한 관리 방법을 안내합니다. 사용자 관리는 관리 콘솔의 **보안 관리 > 사용자 관리** 메뉴에서 수행할 수 있습니다.

## 사용자 구조 <a href="#user-structure" id="user-structure"></a>

PlantPulse의 사용자 관리는 세 가지 핵심 요소로 구성됩니다.

```mermaid
graph TD
  USER[User<br/>로그인 계정]
  SG[Security Group<br/>역할 그룹]
  PERM[Permission<br/>메뉴 / 화면 / API 접근]
  RES[보호 리소스<br/>화면 · REST API · 데이터]

  USER -->|소속| SG
  SG -->|할당| PERM
  PERM -->|적용| RES
```

* **사용자(User):** 플랫폼에 로그인하는 개별 계정입니다.
* **보안 그룹(Security Group):** 사용자의 역할을 정의하는 그룹입니다. 각 사용자는 하나의 보안 그룹에 속합니다.
* **권한(Permission):** 보안 그룹에 할당된 기능별 접근 권한입니다. 메뉴, 화면, API에 대한 접근을 제어합니다.

### 표준 역할 매트릭스 (운영 권장)

| 역할           | 콘솔 메뉴      | 데이터 쓰기 | 시스템 설정 | 사용자 관리 | 예시           |
| ------------ | ---------- | ------ | ------ | ------ | ------------ |
| **ADMIN**    | 전체         | ✓      | ✓      | ✓      | 플랫폼 관리자      |
| **OPERATOR** | 운영 메뉴      | ✓      | -      | -      | 라인 / 생산 관리자  |
| **ENGINEER** | 운영 + 설계 메뉴 | ✓      | 일부     | -      | 시스템 엔지니어     |
| **VIEWER**   | 읽기 전용      | -      | -      | -      | 경영진 / 분석가    |
| **API**      | API only   | ✓      | -      | -      | 외부 시스템 연동 계정 |

> **최소 권한 원칙**: 새 사용자에게는 가급적 `VIEWER` 로 시작하고, 필요한 권한만 점진적으로 추가하세요.

## 사용자 속성 <a href="#user-attributes" id="user-attributes"></a>

| 속성     | 필수 | 설명                                 |
| ------ | -- | ---------------------------------- |
| 사용자 ID | O  | 로그인에 사용하는 고유 식별자 (영문, 숫자, 4\~20자)  |
| 사용자 이름 | O  | 화면에 표시되는 이름                        |
| 비밀번호   | O  | 로그인 비밀번호 (8자 이상)                   |
| 이메일    | -  | 알림 수신 이메일 주소                       |
| 보안 그룹  | O  | 소속 보안 그룹 (ADMIN, OPERATOR, USER 등) |
| 상태     | O  | 활성(Active) 또는 비활성(Inactive)        |
| 설명     | -  | 사용자에 대한 메모                         |
| 생성일    | 자동 | 계정 생성 일시                           |
| 최종 로그인 | 자동 | 마지막 로그인 일시                         |

## 사용자 목록 조회 <a href="#user-list" id="user-list"></a>

관리 콘솔에서 **보안 관리 > 사용자 관리** 메뉴를 선택하면 등록된 사용자 목록을 확인할 수 있습니다.

* **URL:** `/user/index`
* 사용자 ID, 이름, 보안 그룹, 상태, 최종 로그인 일시를 확인할 수 있습니다.
* 검색 필터를 사용하여 특정 사용자를 빠르게 찾을 수 있습니다.

> **안내:** 사용자 목록은 ADMIN 보안 그룹에 속한 사용자만 조회할 수 있습니다.

## 사용자 추가 <a href="#user-add" id="user-add"></a>

1. 사용자 목록 화면에서 **추가** 버튼을 클릭합니다.
2. 필수 항목을 입력합니다.
   * **사용자 ID:** 영문과 숫자로 구성된 고유 ID (4\~20자)
   * **사용자 이름:** 화면에 표시될 이름
   * **비밀번호:** 8자 이상, 영문 대소문자, 숫자, 특수문자 조합을 권장합니다.
   * **보안 그룹:** 사용자에게 적용할 보안 그룹을 선택합니다.
3. 선택 항목 (이메일, 설명 등)을 필요에 따라 입력합니다.
4. **저장** 버튼을 클릭합니다.

> **참고:** 사용자 ID는 생성 후 변경할 수 없습니다. 신중하게 설정해 주세요.

## 사용자 수정 <a href="#user-edit" id="user-edit"></a>

1. 사용자 목록에서 수정할 사용자를 클릭합니다.
2. 수정 가능한 항목을 변경합니다 (이름, 이메일, 보안 그룹, 상태, 설명 등).
3. **저장** 버튼을 클릭합니다.

> **안내:** 사용자 ID는 수정할 수 없습니다. ID를 변경하려면 기존 사용자를 삭제하고 새로 생성해야 합니다.

## 사용자 삭제 <a href="#user-delete" id="user-delete"></a>

1. 사용자 목록에서 삭제할 사용자를 선택합니다.
2. **삭제** 버튼을 클릭합니다.
3. 확인 팝업에서 **확인**을 클릭합니다.

> **주의:** 삭제된 사용자는 복구할 수 없습니다. 사용자를 일시적으로 차단하려면 삭제 대신 **비활성화**를 사용하는 것을 권장합니다.

## 사용자 비활성화 <a href="#user-deactivate" id="user-deactivate"></a>

사용자 계정을 삭제하지 않고 로그인을 차단하려면 비활성화 기능을 사용합니다.

1. 사용자 수정 화면에서 **상태**를 `Inactive`로 변경합니다.
2. **저장** 버튼을 클릭합니다.

비활성화된 사용자는 로그인이 차단되지만 데이터(감사 로그, 설정 이력 등)는 그대로 유지됩니다. 다시 활성화하려면 상태를 `Active`로 변경해 주세요.

***

## 비밀번호 관리 <a href="#password-management" id="password-management"></a>

### 비밀번호 초기화 <a href="#password-reset" id="password-reset"></a>

관리자가 사용자의 비밀번호를 초기화할 수 있습니다.

1. 사용자 수정 화면에서 **비밀번호 초기화** 버튼을 클릭합니다.
2. 새 비밀번호를 입력합니다.
3. **저장** 버튼을 클릭합니다.

> **안내:** 초기화된 비밀번호는 사용자에게 별도로 전달해 주세요. 사용자가 첫 로그인 후 비밀번호를 변경하도록 안내하는 것을 권장합니다.

### 비밀번호 변경 <a href="#password-change" id="password-change"></a>

사용자 본인이 비밀번호를 변경하는 방법입니다.

1. 화면 우측 상단의 사용자 아이콘을 클릭합니다.
2. **비밀번호 변경**을 선택합니다.
3. 현재 비밀번호와 새 비밀번호를 입력합니다.
4. **변경** 버튼을 클릭합니다.

### 비밀번호 분실 처리 <a href="#password-lost" id="password-lost"></a>

비밀번호를 분실한 경우 다음 방법으로 처리합니다.

* **관리자에게 요청:** 관리자가 비밀번호를 초기화합니다.
* **DB 직접 초기화 (비상 시):** 관리자 계정까지 잠긴 경우 PostgreSQL에서 직접 초기화할 수 있습니다.

```sql
-- 비상 시 관리자 비밀번호 초기화 (SHA-256 해시)
-- 주의: 이 방법은 비상 상황에서만 사용해 주세요
UPDATE pp_user
SET password = encode(digest('임시비밀번호123!', 'sha256'), 'hex')
WHERE user_id = 'admin';
```

### 비밀번호 정책 <a href="#password-policy" id="password-policy"></a>

안전한 비밀번호 운영을 위해 다음 정책을 권장합니다.

| 항목          | 권장 설정                            |
| ----------- | -------------------------------- |
| 최소 길이       | 8자 이상                            |
| 복잡도         | 영문 대문자, 소문자, 숫자, 특수문자 중 3종 이상 조합 |
| 변경 주기       | 90일마다 변경 권장                      |
| 이전 비밀번호 재사용 | 최근 3개 비밀번호 재사용 금지 권장             |
| 로그인 실패 횟수   | 5회 연속 실패 시 계정 잠금 고려              |

***

## 보안 그룹 관리 <a href="#security-group" id="security-group"></a>

### 기본 보안 그룹 <a href="#default-groups" id="default-groups"></a>

PlantPulse는 세 가지 기본 보안 그룹을 제공합니다.

| 보안 그룹    | 설명      | 주요 권한                             |
| -------- | ------- | --------------------------------- |
| ADMIN    | 시스템 관리자 | 전체 기능 접근 (사용자 관리, 시스템 설정, 모든 메뉴)  |
| OPERATOR | 운영자     | 운영 관련 기능 접근 (모니터링, 알람 관리, 데이터 조회) |
| USER     | 일반 사용자  | 기본 기능 접근 (대시보드 조회, 데이터 조회)        |

### 보안 그룹 추가 <a href="#group-add" id="group-add"></a>

기본 그룹 외에 조직의 역할에 맞는 보안 그룹을 추가할 수 있습니다.

1. **보안 관리 > 보안 그룹** 메뉴를 선택합니다.
2. **추가** 버튼을 클릭합니다.
3. 그룹 ID, 그룹 이름, 설명을 입력합니다.
4. **저장** 버튼을 클릭합니다.

### 권한 설정 <a href="#permission-setting" id="permission-setting"></a>

보안 그룹에 메뉴 및 기능별 권한을 설정합니다.

1. **보안 관리 > 보안 그룹** 메뉴에서 그룹을 선택합니다.
2. **권한 설정** 탭을 클릭합니다.
3. 각 메뉴/기능에 대해 **읽기**, **쓰기**, **삭제** 권한을 체크합니다.
4. **저장** 버튼을 클릭합니다.

권한 설정 예시:

| 메뉴     | ADMIN    | OPERATOR | USER |
| ------ | -------- | -------- | ---- |
| 연결 관리  | 읽기/쓰기/삭제 | 읽기/쓰기    | 읽기   |
| 팩토리 관리 | 읽기/쓰기/삭제 | 읽기/쓰기    | 읽기   |
| 알람 관리  | 읽기/쓰기/삭제 | 읽기/쓰기    | 읽기   |
| 사용자 관리 | 읽기/쓰기/삭제 | -        | -    |
| 시스템 설정 | 읽기/쓰기/삭제 | 읽기       | -    |
| 캔버스    | 읽기/쓰기/삭제 | 읽기/쓰기    | 읽기   |

***

## 접근 제어 <a href="#access-control" id="access-control"></a>

### 사이트 접근 제어 <a href="#site-access" id="site-access"></a>

멀티 사이트 환경에서는 사용자별로 접근 가능한 사이트를 제한할 수 있습니다.

1. 사용자 수정 화면에서 **사이트 접근 권한** 탭을 선택합니다.
2. 접근을 허용할 사이트를 체크합니다.
3. **저장** 버튼을 클릭합니다.

> **안내:** 사이트 접근 권한이 설정되지 않은 사용자는 모든 사이트에 접근할 수 있습니다.

### 캔버스 공유 <a href="#dashboard-sharing" id="dashboard-sharing"></a>

캔버스 화면은 특정 사용자 또는 보안 그룹과 공유할 수 있습니다.

1. 캔버스 편집 화면에서 **공유 설정**을 클릭합니다.
2. 공유 대상을 선택합니다.
   * **전체 공개:** 모든 사용자가 접근 가능합니다.
   * **보안 그룹:** 선택한 보안 그룹의 사용자만 접근 가능합니다.
   * **사용자 지정:** 선택한 사용자만 접근 가능합니다.
3. **저장** 버튼을 클릭합니다.

***

## 세션 관리 <a href="#session-management" id="session-management"></a>

### 세션 타임아웃 <a href="#session-timeout" id="session-timeout"></a>

사용자의 세션 타임아웃은 기본 **30분**으로 설정되어 있습니다. 30분 동안 활동이 없으면 자동으로 로그아웃됩니다.

세션 타임아웃을 변경하려면 `web.xml`에서 설정을 수정합니다.

```xml
<!-- plantpulse-server/app/plantpulse-server-web/WEB-INF/web.xml -->
<session-config>
    <session-timeout>30</session-timeout> <!-- 분 단위 -->
</session-config>
```

### 동시 로그인 <a href="#concurrent-login" id="concurrent-login"></a>

기본적으로 동일 계정으로 여러 브라우저/기기에서 동시 로그인이 가능합니다. 보안이 중요한 환경에서는 동시 로그인을 제한하는 것을 권장합니다.

동시 로그인 설정은 `application.properties`에서 관리합니다.

```properties
# 동시 로그인 허용 여부 (true: 허용, false: 차단)
app.security.concurrent.login=true

# 동시 로그인 차단 시 기존 세션 처리
# KICK: 기존 세션 강제 종료, BLOCK: 신규 로그인 차단
app.security.concurrent.login.policy=KICK
```

***

## 감사 로그 <a href="#audit-log" id="audit-log"></a>

사용자의 주요 활동은 감사 로그에 자동으로 기록됩니다. 감사 로그를 통해 시스템 변경 이력을 추적할 수 있습니다.

기록되는 활동:

| 활동 유형     | 설명                        |
| --------- | ------------------------- |
| 로그인/로그아웃  | 사용자 인증 이벤트                |
| 사용자 관리    | 사용자 생성, 수정, 삭제, 비활성화      |
| 보안 그룹 변경  | 그룹 생성, 수정, 삭제, 권한 변경      |
| 시스템 설정 변경 | 프로퍼티, 연결 정보 등 설정 변경       |
| 데이터 수정    | 팩토리, 설비, 포인트 등 마스터 데이터 변경 |

감사 로그는 **도구 > 감사 로그** 메뉴에서 조회할 수 있으며, 기간, 사용자, 활동 유형별로 필터링할 수 있습니다.

***

## 대량 사용자 등록 <a href="#bulk-user-import" id="bulk-user-import"></a>

다수의 사용자를 한 번에 등록하려면 Excel 파일을 사용하여 일괄 등록할 수 있습니다.

### 등록 절차

1. **보안 관리 > 사용자 관리** 메뉴에서 **Excel 업로드** 버튼을 클릭합니다.
2. 템플릿 Excel 파일을 다운로드합니다.
3. 템플릿에 맞게 사용자 정보를 입력합니다.

| 열               | 필수 | 설명       | 예시                 |
| --------------- | -- | -------- | ------------------ |
| user\_id        | O  | 사용자 ID   | `operator01`       |
| user\_name      | O  | 사용자 이름   | `홍길동`              |
| password        | O  | 초기 비밀번호  | `Temp1234!`        |
| email           | -  | 이메일      | `hong@example.com` |
| security\_group | O  | 보안 그룹 ID | `OPERATOR`         |
| description     | -  | 설명       | `생산1팀`             |

4. 작성한 Excel 파일을 업로드합니다.
5. 미리보기에서 등록할 사용자 정보를 확인합니다.
6. **등록** 버튼을 클릭합니다.

> **안내:** 업로드 시 유효성 검사가 수행됩니다. 중복 ID, 필수 항목 누락 등의 오류가 있으면 해당 행이 표시되며 수정 후 재업로드할 수 있습니다.

***

## 모범 사례 <a href="#best-practices" id="best-practices"></a>

* **최소 권한 원칙:** 사용자에게 업무에 필요한 최소한의 권한만 부여해 주세요.
* **관리자 계정 최소화:** ADMIN 그룹의 사용자는 최소한으로 유지하고, 일반 운영은 OPERATOR 그룹을 사용하세요.
* **주기적 감사:** 분기별로 사용자 목록과 권한을 검토하여 불필요한 계정을 비활성화해 주세요.
* **퇴직자 처리:** 퇴직 시 즉시 계정을 비활성화하거나 삭제해 주세요.
* **공유 계정 금지:** 개인별 계정을 사용하고, 공유 계정 사용은 지양해 주세요.
* **비밀번호 관리:** 초기 비밀번호는 반드시 변경하도록 안내하고, 정기적인 비밀번호 변경을 유도해 주세요.
* **로그 모니터링:** 비정상적인 로그인 시도(반복 실패, 비정상 시간대 접근 등)를 모니터링해 주세요.

***

## 자주 발생하는 문제 <a href="#troubleshooting" id="troubleshooting"></a>

### 로그인 실패 <a href="#login-failure" id="login-failure"></a>

| 증상                        | 원인                 | 해결 방법                                         |
| ------------------------- | ------------------ | --------------------------------------------- |
| "사용자 ID 또는 비밀번호가 잘못되었습니다" | 잘못된 비밀번호 입력        | 비밀번호를 확인하고 다시 시도해 주세요. Caps Lock 상태도 확인해 주세요. |
| "비활성화된 계정입니다"             | 계정이 Inactive 상태    | 관리자에게 계정 활성화를 요청해 주세요.                        |
| "계정이 잠겼습니다"               | 로그인 연속 실패로 잠금      | 관리자에게 잠금 해제를 요청해 주세요.                         |
| 로그인 화면이 표시되지 않음           | 웹서버 미실행 또는 네트워크 문제 | 서버 상태와 네트워크 연결을 확인해 주세요.                      |

### 권한 부족 <a href="#insufficient-permission" id="insufficient-permission"></a>

| 증상                | 원인                    | 해결 방법                    |
| ----------------- | --------------------- | ------------------------ |
| 메뉴가 보이지 않음        | 보안 그룹에 해당 메뉴 접근 권한 없음 | 관리자에게 권한 추가를 요청해 주세요.    |
| "접근 권한이 없습니다" 메시지 | API 또는 기능 권한 부족       | 보안 그룹의 권한 설정을 확인해 주세요.   |
| 특정 사이트 데이터 미표시    | 사이트 접근 권한 미설정         | 사용자의 사이트 접근 권한을 확인해 주세요. |

### 세션 만료 <a href="#session-expired" id="session-expired"></a>

| 증상             | 원인                      | 해결 방법                                       |
| -------------- | ----------------------- | ------------------------------------------- |
| 작업 중 로그인 화면 전환 | 세션 타임아웃 (기본 30분)        | 다시 로그인해 주세요. 타임아웃이 짧다면 `web.xml`에서 조정해 주세요. |
| 다른 기기에서 로그아웃됨  | 동시 로그인 정책(KICK)으로 강제 종료 | 동시 로그인 설정을 확인해 주세요.                         |
| 세션 관련 에러 반복    | Redis 캐시 장애             | Redis 서비스 상태를 확인해 주세요.                      |
