Database 매뉴얼 · Chapter 8

title: "Database 이벤트 후킹 — Database Events 화면" chapter: 8 images:

  • database-events-page.png

Database 이벤트 후킹

연결 / 에러 / 백업 같은 사건이 발생했을 때 자동으로 호출되는 함수를 작성하는 단계입니다. Database Events 화면이 함수의 기본 스텁(빈 껍데기) 을 자동으로 만들어 주므로, 스크립트 측에서는 본문만 채우면 됩니다.

Database Events 화면 — 이벤트 목록과 [+ Add] 버튼

화면 진입

Solution Explorer
└── Data Editor Pages
    └── Database
        └── Database Events   ← 이 화면

지원 이벤트 목록

이벤트 함수발화 시점파라미터
OnDbOpenedDB 연결이 열렸을 때string dbName
OnDbClosedDB 연결이 닫혔을 때string dbName
OnDbError쿼리 / 연결 실패 시string dbName, string operation, string errorMsg
OnBackupStarted백업 시작string dbName, string filePath
OnBackupProgress백업 진행률 (1초마다)string dbName, int percent
OnBackupDone백업 종료 (성공/실패 모두)string dbName, string filePath, bool success, string errorMsg
OnRemoteDbDisconnected원격 MSSQL 연결이 끊김string dbName
OnRemoteDbReconnected원격 MSSQL 연결이 자동 재연결됨string dbName

이벤트 함수가 정의되지 않아도 DB 동작은 그대로 진행됩니다 (best-effort). 필요한 이벤트만 후킹하면 됩니다.

스텁 자동 생성 — [+ Add]

  1. 우측 목록에서 후킹할 이벤트 선택 (예: OnDbError)
  2. 좌측 대상 모듈 콤보에서 함수가 들어갈 모듈 선택 (기본: Event)
  3. [+ Add] 클릭 → 대상 모듈 끝에 다음 형태의 빈 함수가 자동 삽입됩니다.
FUNCTION OnDbError(string dbName, string operation, string errorMsg)
{
   // ==========================================================================
   // Caption : DB 오류 이벤트 핸들러 (자동 생성)
   // ==========================================================================
   Log($"OnDbError [{dbName}] {operation} : {errorMsg}");
}
버튼동작
[+ Add]대상 모듈에 스텁 자동 삽입
[Go]해당 모듈 스크립트 에디터 탭으로 이동 (커서를 함수 위치로)
[Remove]구현된 FUNCTION 블록 제거 (확인 다이얼로그)

운영용 샘플

1) OnDbError — 운영자에게 알림

FUNCTION OnDbError(string dbName, string operation, string errorMsg)
{
   // ==========================================================================
   // Caption : DB 오류 알림 + 운영자 메시지
   // ==========================================================================
   LogError($"DB ERROR [{dbName}] {operation} : {errorMsg}");
 
   // ‘database is locked’ 같은 동시성 문제는 운영자에게 즉시 알림
   if( STR.Contains(errorMsg, "locked") )
   {
      ShowTimerMessage(EB_Ok, 1701);   //데이터베이스가 잠겨 있어 잠시 후 다시 시도해 주세요.
      return true;
   }
 
   // 그 외 에러는 자동 복구 시도 후 알림
   if( operation == "RunSqlQuery" )
   {
      ShowTimerMessage(EB_Ok, 1702);   //데이터 저장 중 오류가 발생했습니다. 로그를 확인해 주세요.
   }
}

2) OnBackupDone — 백업 결과 알림

FUNCTION OnBackupDone(string dbName, string filePath, bool success, string errorMsg)
{
   if( success )
   {
      Log($"Backup OK [{dbName}] : {filePath}");
      ShowTimerMessage(EB_Ok, 1710);   //백업이 완료되었습니다.
   }
   else
   {
      LogError($"Backup FAIL [{dbName}] : {errorMsg}");
      ShowMessage(EB_Ok, 1711);        //백업에 실패했습니다. 로그를 확인해 주세요.
   }
}

3) OnBackupProgress — ProgressBar 갱신

FUNCTION OnBackupProgress(string dbName, int percent)
{
   // 화면의 ProgressBar 컨트롤이 LinkValueName 으로 연결된 변수
   BackupPercent = percent;
}

ProgressBar 의 XDesigner 속성:

속성
LinkValueNameViewBackup::BackupPercent
Minimum0
Maximum100

4) OnRemoteDbDisconnected — 원격 끊김 표시

FUNCTION OnRemoteDbDisconnected(string dbName)
{
   LogError($"Remote DB disconnected : {dbName}");
   GUI.SetControlBoolProperty(/*moduleName*/"ViewMain",
                              /*controlName*/"lblDbStatus",
                              /*propertyName*/"UseBlink",
                              /*onoff*/true);
}
 
FUNCTION OnRemoteDbReconnected(string dbName)
{
   Log($"Remote DB reconnected : {dbName}");
   GUI.SetControlBoolProperty(/*moduleName*/"ViewMain",
                              /*controlName*/"lblDbStatus",
                              /*propertyName*/"UseBlink",
                              /*onoff*/false);
}

에러 가시성 — 한 줄로 외우기

운영 중 어떤 에러가 발생해도 세 곳 에 모두 흔적이 남도록 해 두십시오.

LastError       →  OnDbError       →  XLog.AddError
(객체 속성)         (이벤트 발화)        (운영 로그 파일)
  • LastError즉시 직전 작업의 원인 을 들고 있습니다 — 함수가 false 를 반환한 직후 읽으십시오.
  • OnDbError자동 호출 되므로, 운영자에게 알림을 띄우거나 자동 복구 로직을 트리거하는 위치입니다.
  • XLog.AddError파일에 영구 기록 되므로, 사후 분석/통계의 기반이 됩니다.

세 곳이 한 자리에서 통일되어 있으면 디버깅 시간이 절반으로 줄어듭니다.

자주 묻는 질문

Q. 이벤트 함수에서 false 를 반환하면 DB 동작이 막히나요? 아닙니다. 이벤트는 best-effort 로 호출됩니다. 반환값은 무시되며, 본문에서 예외가 나도 DB 동작은 진행됩니다. 이벤트 처리가 실패한 경우 운영 로그에 XDatabaseEvent : OnDbError fire error : ... 형태로 기록됩니다.

Q. 같은 이벤트를 두 모듈에서 받고 싶습니다. 현재는 모듈 1개에만 함수가 정의되도록 권장됩니다. 여러 곳에 정의되어 있으면 첫 번째로 발견된 함수만 호출됩니다. 여러 모듈이 알아야 하면, 한 곳에서 받은 다음 다른 모듈의 일반 함수를 명시적으로 호출하십시오.

FUNCTION OnDbError(string dbName, string operation, string errorMsg)
{
   ViewMain::OnDbError(dbName, operation, errorMsg);
   ViewBackup::OnDbError(dbName, operation, errorMsg);
}

Q. 이벤트 함수에서 다시 DB 작업을 호출해도 되나요? 가능하지만 주의가 필요합니다. OnDbError 안에서 또 실패가 나면 OnDbError 가 재귀적으로 발화되어 무한 루프가 될 수 있습니다. 이벤트 안에서는 Log / XLog / ShowTimerMessage 정도만 사용하고, 복잡한 복구 로직은 별도 시퀀스에서 처리하는 편이 안전합니다.

체크포인트

  1. Event 모듈에 OnDbError, OnBackupDone 두 함수가 자동 생성되었다.
  2. 일부러 잘못된 SQL 을 실행 → OnDbError 가 발화 → ShowTimerMessage 가 뜬다.
  3. BackupNow() 호출 → OnBackupDone 이 발화 → 성공 메시지가 뜬다.

다음 단계

9장 — 백업 + 운영 체크포인트