eGovFrame 기반 시스템에서 메뉴 등록 후 웹페이지가 멈추거나 Duplicate Key 오류가 발생했다. 최종 원인은 채번 테이블의 NEXT_ID가 실제 데이터 최댓값보다 작았고, 대상 테이블에 PK 제약이 없어 중복 삽입이 즉시 막히지 않았던 것이다.
증상
- 관리 화면에서 메뉴 등록·저장 시 오류가 발생하거나, 저장 후 메뉴 트리·특정 페이지가 로딩되지 않는다(먹통)
- 애플리케이션 로그에 Duplicate entry / Unique constraint violation 류 메시지가 남는다
- DB에는 이미 동일 entityId(메뉴 ID) 를 가진 행이 2건 이상 존재할 수 있다
- 처음에는 애플리케이션 버그·캐시 문제를 의심했으나, 채번 값과 실데이터 불일치 쪽으로 좁혀졌다
어떻게 좁혔나
1) 오류 시점·경로 확인
- 프로그램 경로(관리 화면 INSERT)에서만 재현되는지, 조회만으로도 깨지는지 구분했다
- 운영 DB 수동 INSERT·UPDATE 이력이 있는지 확인했다
2) 채번 테이블 vs 실데이터 비교
| 검증 | 결과 |
| 채번 테이블 NEXT_ID (예: TABLE_NAME = 'MENU_ID') | 예: 105 |
| 실제 메뉴 테이블 MAX(entityId) | 예: 108 |
| 프로그램이 다음에 발급할 ID | 105 → 이미 존재하는 ID와 충돌 |
3) 제약조건·중복 데이터 확인
-- PK/UNIQUE 없음 여부 (메타 조회 또는 스키마 확인)
-- 중복 entityId 존재 여부
SELECT entity_id, COUNT(*)
FROM menu_info
GROUP BY entity_id
HAVING COUNT(*) > 1;
- PK가 없으면 INSERT 시점에 DB가 막지 못하고, 이후 조회·조인·트리 구성 단계에서 오류가 터질 수 있다
원인
eGovFrame 테이블 기반 채번 동작
- EgovTableIdGnrServiceImpl 은 채번 전용 테이블에서 TABLE_NAME 별 NEXT_ID 를 읽고 +1 UPDATE 후 반환한다
- blockSize=1 이면 호출마다 SELECT → UPDATE 를 수행한다
<bean name="entityIdGnrService"
class="egovframework.rte.fdl.idgnr.impl.EgovTableIdGnrServiceImpl"
destroy-method="destroy">
<property name="dataSource" ref="dataSource" />
<property name="strategy" ref="menuStrategy" />
<property name="blockSize" value="1"/>
<property name="table" value="SEQ_TABLE"/>
<property name="tableName" value="MENU_ID"/>
</bean>
| 컬럼 | 역할 |
| TABLE_NAME | 채번 대상 식별자 (예: MENU_ID) |
| NEXT_ID | 다음 발급할 ID |
불일치가 생긴 경로
- 운영 중 DB에서 직접 메뉴 행을 INSERT·UPDATE 하면서 entityId 를 수동 지정했다
- 이때 채번 테이블의 NEXT_ID 는 갱신되지 않았다
- 실데이터 MAX(entityId) ≥ 채번 NEXT_ID 상태가 되었다
- 이후 프로그램이 메뉴 INSERT 시 이미 존재하는 ID 를 다시 발급받아 충돌했다
PK 미설정이 증상을 악화시킨 이유
- 대상 테이블 entityId 에 PK·UNIQUE 가 없으면 중복 INSERT 가 DB에서 즉시 거부되지 않는다
- Duplicate Key 는 늦게 드러나거나, 조회 로직이 단건 가정일 때 페이지 전체가 멈춘 것처럼 보인다
해결
1) 채번 값 보정 — 실데이터 최댓값 + 1 로 맞춘다
UPDATE seq_table
SET next_id = (SELECT MAX(entity_id) + 1 FROM menu_info)
WHERE table_name = 'MENU_ID';
2) 중복 데이터 정리 — 위 중복 조회 쿼리로 걸린 행을 업무 규칙에 맞게 병합·삭제한다 (선행 필수)
3) PK 또는 UNIQUE 제약 추가 — 향후 수동·프로그램 경로 모두에서 중복 삽입을 원천 차단한다
4) 운영 DB 직접 수정 가이드 — 수동으로 ID 를 넣을 때는 반드시 채번 테이블 NEXT_ID 도 동기화하도록 Runbook 에 명시한다
정리
- eGovFrame 테이블 채번은 SEQ_TABLE.NEXT_ID 만 믿으면 안 된다 — 실데이터 MAX(id) 와 주기적으로 대조한다.
- 운영 DB 수동 INSERT 후 채번 불일치가 가장 흔한 원인이다 — 수동 작업 시 채번 동기화를 절차에 넣는다.
- ID 컬럼에 PK·UNIQUE 가 없으면 중복이 조용히 쌓이고, 조회·트리 화면에서 늦게 터진다.
- 메뉴·권한·코드처럼 전역 참조되는 ID 는 충돌 시 영향 범위가 넓다 — 등록 실패 로그와 MAX(id) vs NEXT_ID 를 함께 본다.
참고: 발생 오류 유형
| 레이어 | 증상 |
| DB | Duplicate entry, Unique constraint violation (PK 설정 후에는 INSERT 시점에 즉시) |
| 애플리케이션 | 중복 ID 로 인한 메뉴 조회 실패, Null/다건 처리 오류, 페이지 로딩 실패 |
728x90
반응형