암호화 모듈 설정 관리 화면 추가 (feature/crypto-module)
- CryptoModuleConfig CRUD 관리 화면 신규 개발 - JPA DataService/Repository, MapStruct UiMapper, ManService, Controller - 목록(jqGrid, 4가지 검색조건), 상세/등록/수정/삭제 화면 - INSERT/UPDATE/DELETE 후 게이트웨이 전 인스턴스에 ReloadCryptoModuleCommand broadcast - 버그 수정 - getById(getReferenceById) → findById 교체: Persistable.isNew=true 유지로 인한 persist 에러 - insert 시 entity.setCryptoId(null): 빈 문자열 cryptoId 전송 시 UUID 생성기 오동작 방지 - 검색 버튼 클릭 시 algType/keySourceType/useYn getSearchForJqgrid 누락 수정 - UX 개선 - 암호화키/복호화키/IV 필드에 텍스트→HEX 변환 보조 입력 및 키 길이 실시간 표시 - 상세 화면에 수정자/수정일시 정보성 표시 - DB: EMSADM.CRYPTO_MODULE_CONFIG 테이블 (MODIFIED_BY/MODIFIED_AT 포함 전체 DDL) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
# 작업내역 — feature/crypto-module (eapim-admin)
|
||||
|
||||
> 작업일: 2026-05-07
|
||||
> 브랜치: `feature/crypto-module`
|
||||
> 작업자: curry772
|
||||
> 프로젝트: `eapim-admin`
|
||||
|
||||
---
|
||||
|
||||
## 작업 목적
|
||||
|
||||
2026-05-06 작업 미완료 항목 처리 및 기능 테스트 중 발견된 버그 수정, UX 개선.
|
||||
|
||||
---
|
||||
|
||||
## 변경 파일 목록
|
||||
|
||||
### DB DDL
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| `EMSADM.CRYPTO_MODULE_CONFIG` 테이블 컬럼 추가 | 기존 DDL에서 누락된 `MODIFIED_BY`, `MODIFIED_AT` 컬럼 추가 |
|
||||
|
||||
```sql
|
||||
ALTER TABLE EMSADM.CRYPTO_MODULE_CONFIG
|
||||
ADD (
|
||||
MODIFIED_BY VARCHAR2(50),
|
||||
MODIFIED_AT TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
> 전체 DDL (신규 환경용)
|
||||
```sql
|
||||
CREATE TABLE EMSADM.CRYPTO_MODULE_CONFIG (
|
||||
CRYPTO_ID VARCHAR2(36) NOT NULL,
|
||||
CRYPTO_NAME VARCHAR2(100) NOT NULL,
|
||||
CRYPTO_DESC VARCHAR2(500),
|
||||
ALG_TYPE VARCHAR2(10) NOT NULL,
|
||||
CIPHER_MODE VARCHAR2(20) NOT NULL,
|
||||
PADDING VARCHAR2(30),
|
||||
IV_HEX VARCHAR2(200),
|
||||
KEY_SOURCE_TYPE VARCHAR2(20) NOT NULL,
|
||||
ENC_KEY_HEX VARCHAR2(200),
|
||||
DEC_KEY_HEX VARCHAR2(200),
|
||||
KEY_DERIV_STRATEGY VARCHAR2(200),
|
||||
KEY_DERIV_PARAMS VARCHAR2(2000),
|
||||
CACHE_YN CHAR(1) NOT NULL,
|
||||
CACHE_TTL_SEC NUMBER(10),
|
||||
USE_YN CHAR(1) NOT NULL,
|
||||
MODIFIED_BY VARCHAR2(50),
|
||||
MODIFIED_AT TIMESTAMP,
|
||||
CONSTRAINT PK_CRYPTO_MODULE_CONFIG PRIMARY KEY (CRYPTO_ID),
|
||||
CONSTRAINT UQ_CRYPTO_MODULE_CONFIG_NAME UNIQUE (CRYPTO_NAME)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 비즈니스 레이어 — `CryptoModuleConfigManService.java`
|
||||
|
||||
#### 버그 수정: detached entity passed to persist
|
||||
|
||||
**원인**
|
||||
- `AbstractEntity`가 `Persistable<I>`를 구현하고 `@Transient boolean isNew = true`로 선언
|
||||
- `@PostLoad`에서 `isNew = false`로 전환하는 구조
|
||||
- `AbstractDataService.getById(id)`는 `repository.getReferenceById(id)` (lazy proxy) 반환
|
||||
- lazy proxy는 실제 DB 조회를 하지 않아 `@PostLoad`가 호출되지 않음 → `isNew = true` 유지
|
||||
- `save(proxy)` 호출 시 `isNew() = true` → `em.persist(proxy)` → detached entity 에러
|
||||
|
||||
**수정 내용**
|
||||
|
||||
| 메서드 | 변경 전 | 변경 후 |
|
||||
|---|---|---|
|
||||
| `selectDetail()` | `dataService.getById(cryptoId)` | `dataService.findById(cryptoId).orElseThrow(...)` |
|
||||
| `update()` | `dataService.getById(ui.getCryptoId())` | `dataService.findById(ui.getCryptoId()).orElseThrow(...)` |
|
||||
| `insert()` | — | `entity.setCryptoId(null)` 추가 |
|
||||
|
||||
- `findById()`는 실제 DB 조회 → `@PostLoad` 호출 → `isNew = false` → `merge()` 정상 동작
|
||||
- `insert()` 에서 `setCryptoId(null)` 추가: JSP `<input type="hidden" name="cryptoId" />`가 빈 문자열 `""`로 전송될 때 UUID 생성기가 정상 동작하도록 보장
|
||||
|
||||
---
|
||||
|
||||
### 목록 화면 — `cryptoModuleMan.jsp`
|
||||
|
||||
#### 버그 수정: 검색 조건 누락
|
||||
|
||||
**원인**
|
||||
- 공통 함수 `getSearchForJqgrid()`는 `name^=search` 패턴 필드만 자동 수집
|
||||
- `algType`, `keySourceType`, `useYn`은 해당 패턴이 아니어서 검색 버튼 클릭 시 postData에서 누락
|
||||
|
||||
**수정 내용**
|
||||
- 검색 버튼 클릭 핸들러에서 세 필드를 명시적으로 postData에 추가
|
||||
|
||||
```javascript
|
||||
var postData = getSearchForJqgrid("cmd", "LIST");
|
||||
postData['algType'] = $('select[name=algType]').val();
|
||||
postData['keySourceType'] = $('select[name=keySourceType]').val();
|
||||
postData['useYn'] = $('select[name=useYn]').val();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 상세 화면 — `cryptoModuleManDetail.jsp`
|
||||
|
||||
#### 기능 추가 1: 텍스트 → HEX 변환 보조 입력 + 키 길이 표시
|
||||
|
||||
**배경**
|
||||
- AES/ARIA 암호화 키, 복호화 키, IV를 HEX 값으로 직접 입력하는 것은 불편
|
||||
- 단, HEX → 텍스트 역변환이 항상 가능하지 않음 (랜덤 바이트 키는 유효하지 않은 UTF-8 시퀀스 포함 가능)
|
||||
- 텍스트 변환 기능은 개발/테스트 편의용, 운영 환경에서는 랜덤 키 생성 권장
|
||||
|
||||
**추가 내용**
|
||||
- `encKeyHex`, `decKeyHex`, `ivHex` 각 필드에 텍스트 입력 보조 필드 추가
|
||||
- 텍스트 입력 시 `TextEncoder`(UTF-8)로 HEX 자동 변환 → HEX 필드에 반영
|
||||
- 보조 입력 필드는 `name` 속성 없음 → form submit에 포함되지 않음
|
||||
- HEX 필드 옆에 키 길이 실시간 표시 (`N bytes (M자)` 형식)
|
||||
- HEX 직접 입력 시 및 조회 시에도 즉시 반영
|
||||
- 참고 기준: AES-128: 16bytes / AES-192: 24bytes / AES-256: 32bytes
|
||||
|
||||
**추가 함수**
|
||||
```javascript
|
||||
textToHex(text) // TextEncoder UTF-8 기반 HEX 변환
|
||||
updateHexFromText(...) // 텍스트 입력 → HEX 필드 갱신 + 길이 표시
|
||||
updateHexLength(hex, id) // HEX 문자열 길이 계산 및 표시
|
||||
```
|
||||
|
||||
#### 기능 추가 2: 수정자 / 수정일시 정보 표시
|
||||
|
||||
- 테이블 하단에 수정자/수정일시 행 추가 (read-only `<span>` 표시)
|
||||
- 신규 등록 화면: 행 숨김 (`display:none`)
|
||||
- 상세 조회 화면: 값이 있을 때만 행 표시
|
||||
- `MODIFIED_AT` 포맷: `LocalDateTime.toString()` 결과의 `T` → 공백 치환 (`2026-05-07 09:30:00`)
|
||||
|
||||
---
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
### `getById()` vs `findById()`
|
||||
이 프로젝트에서 `AbstractDataService.getById()`는 `getReferenceById()`를 래핑한다.
|
||||
`AbstractEntity`가 `Persistable<isNew>`를 구현하므로, lazy proxy 상태에서는 `isNew = true`가 유지되어 `save()` 시 `persist()`가 호출되는 문제가 있다.
|
||||
**수정/조회 후 저장이 필요한 경우 반드시 `findById()`를 사용해야 한다.**
|
||||
|
||||
---
|
||||
|
||||
## 미완료 / 다음 작업
|
||||
|
||||
- [ ] 관리자 메뉴 테이블에 경로 등록 (`/onl/admin/security/cryptoModuleMan.view`)
|
||||
- [ ] 화면 접근 권한(ACL) 등록
|
||||
- [ ] 전체 파일 커밋 (eapim-admin + eapim-online 양쪽)
|
||||
Reference in New Issue
Block a user