Framework

eGovFrame 채번 테이블 불일치로 메뉴 ID가 중복된 사례

범데이 2026. 6. 16. 19:03

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

 

불일치가 생긴 경로

  1. 운영 중 DB에서 직접 메뉴 행을 INSERT·UPDATE 하면서 entityId 를 수동 지정했다
  2. 이때 채번 테이블의 NEXT_ID 는 갱신되지 않았다
  3. 실데이터 MAX(entityId) ≥ 채번 NEXT_ID 상태가 되었다
  4. 이후 프로그램이 메뉴 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 에 명시한다

 

 

 

정리

  1. eGovFrame 테이블 채번은 SEQ_TABLE.NEXT_ID 만 믿으면 안 된다 — 실데이터 MAX(id) 와 주기적으로 대조한다.
  2. 운영 DB 수동 INSERT 후 채번 불일치가 가장 흔한 원인이다 — 수동 작업 시 채번 동기화를 절차에 넣는다.
  3. ID 컬럼에 PK·UNIQUE 가 없으면 중복이 조용히 쌓이고, 조회·트리 화면에서 늦게 터진다.
  4. 메뉴·권한·코드처럼 전역 참조되는 ID 는 충돌 시 영향 범위가 넓다 — 등록 실패 로그와 MAX(id) vs NEXT_ID 를 함께 본다.

 

 

참고: 발생 오류 유형

레이어 증상
DB Duplicate entry, Unique constraint violation (PK 설정 후에는 INSERT 시점에 즉시)
애플리케이션 중복 ID 로 인한 메뉴 조회 실패, Null/다건 처리 오류, 페이지 로딩 실패
728x90
반응형