title: "백업과 운영 체크포인트" chapter: 9 images:
- database-backup.png
백업과 운영 체크포인트
운영 안정성의 마지막 단계입니다. SQLite 의 경우 Online Backup API 를 사용하므로 DB 가 동작하는 중에도 안전하게 백업할 수 있습니다.
public/manual/gui/database-backup.png두 가지 호출 방식
| 메서드 | 동작 | 용도 |
|---|---|---|
Backup(filePath) | 동기 — 완료까지 호출자가 블로킹됨 | 소형 DB · 즉시 백업 |
StartBackupThread(filePath) | 비동기 — 별도 쓰레드에서 진행 | 대형 DB · 진행률 표시가 필요한 경우 |
비동기 호출은 진행률을 OnBackupProgress 이벤트로 1초마다 통지하고, 완료 시점에 OnBackupDone 을 발화합니다.
동기 백업
FUNCTION BackupNow()
{
// ==========================================================================
// Caption : 즉시 백업 (소형 DB / 작업자 명시 호출용)
// Return : bool
// ==========================================================================
string dst = $"XDatabase\\Backup\\local_{SYS.DateTimeFilename}.db";
if( X.DB["local"].Backup(/*filePath*/dst) == false )
{
LogError($"Backup Error : {X.DB[\"local\"].LastError}");
return false;
}
Log($"Backup OK : {dst}");
return true;
}SYS.DateTimeFilename 은 20260501_091230 같은 파일명용 시간 문자열을 반환합니다 — 같은 폴더에 여러 회차를 보관하기 좋습니다.
비동기 백업 + 진행률
// ProgressBar 의 LinkValueName 이 가리키는 변수
int BackupPercent;
FUNCTION BackupAsync()
{
string dst = $"XDatabase\\Backup\\local_{SYS.DateTimeFilename}.db";
X.DB["local"].StartBackupThread(/*filePath*/dst);
Log($"Backup started : {dst}");
}
FUNCTION OnBackupProgress(string dbName, int percent)
{
BackupPercent = percent;
}
FUNCTION OnBackupDone(string dbName, string filePath, bool success, string errorMsg)
{
BackupPercent = success ? 100 : 0;
if( success )
{
Log($"Backup OK [{dbName}] : {filePath}");
ShowTimerMessage(EB_Ok, 1710); //백업이 완료되었습니다.
}
else
{
LogError($"Backup FAIL [{dbName}] : {errorMsg}");
ShowMessage(EB_Ok, 1711); //백업에 실패했습니다.
}
}XDesigner 측 ProgressBar:
| 속성 | 값 |
|---|---|
LinkValueName | ViewBackup::BackupPercent |
Minimum | 0 |
Maximum | 100 |
진행 중에는 IsBackupRunning 속성으로 다른 백업 호출을 막을 수도 있습니다.
if( X.DB["local"].IsBackupRunning )
{
ShowTimerMessage(EB_Ok, 1712); //이미 백업이 진행 중입니다.
return false;
}자동 백업
매일 정해진 시간에 자동으로 백업하려면, Database Connection 화면의 Auto Backup 설정 또는
별도의 시퀀스 루프에서 시간 비교로 호출합니다.
// Backup 시퀀스의 STEP_Daily
Sleep(60000); // 1분마다 점검
if( SYS.Hour == 3 && SYS.Minute == 0 && BackupDoneToday == false )
{
BackupAsync();
BackupDoneToday = true;
}
if( SYS.Hour == 4 )
{
BackupDoneToday = false; // 다음 날 다시 가능하도록 리셋
}새벽 3시 같은 한산한 시간대를 권장합니다.
백업 파일 보관 정책
XDatabase\Backup\
├── local_20260429_030000.db
├── local_20260430_030000.db
└── local_20260501_030000.db오래된 파일은 자동으로 정리하는 로직을 같이 두는 것을 권장합니다.
FUNCTION CleanupOldBackups(int keepDays)
{
string dir = "XDatabase\\Backup";
array files = SYS.GetFiles(dir, "local_*.db");
int cutoff = SYS.UnixTime - keepDays * 86400;
for(i, 0, files.Count-1)
{
if( SYS.GetFileUnixTime(files[i]) < cutoff )
{
SYS.DeleteFile(files[i]);
Log($"Old backup deleted : {files[i]}");
}
}
}MSSQL 의 경우
Backup() / StartBackupThread() 는 SQLite 전용 입니다. MSSQL 의 경우 데이터베이스 서버 측에서
T-SQL BACKUP DATABASE 를 사용해야 합니다 (DB 관리자 정책에 따름).
스크립트에서는 RunSqlQuery("BACKUP DATABASE ... TO DISK=...") 식으로 호출 가능하지만,
권한 / 경로 / 정책 모두 운영 DBA 와 협의하시기 바랍니다.
단계별 ‘여기까지 하면 OK’ 체크포인트
| 단계 | 확인할 것 |
|---|---|
| 01. 개요 | 시나리오 표 + 학습 흐름 다이어그램이 머릿속에 있다 |
| 02. 연결 등록 | XDatabase\local.db 가 자동 생성됨 / 부팅 로그에 Register 줄 |
| 03. 스키마 | Tables 목록에 order_history 가 보임 / 인덱스 2개 자동 생성 |
| 04. SQL 검증 | INSERT/UPDATE/SELECT 모두 SQL 탭에서 정상 동작 |
| 05. INSERT/UPDATE | BeginOrder / EndOrder 호출 시 Data 탭에 즉시 반영 |
| 06. SELECT | RefreshList 가 50건을 정확히 반환 / CountTodayNg 가 SQL 탭과 동일 |
| 07. DataGrid | 화면에 6개 컬럼이 표시 / 5초마다 자동 갱신 / 버튼 클릭 즉시 갱신 |
| 08. 이벤트 | 잘못된 SQL → OnDbError 발화 / ShowTimerMessage 가 뜸 |
| 09. 백업 | XDatabase\Backup\ 에 .db 생성 / 진행률 ProgressBar 가 0→100 |
운영 사고 패턴 정리
| 증상 | 가능한 원인 | 1차 대응 |
|---|---|---|
database is locked | 동시 쓰기 / 너무 큰 트랜잭션 | 트랜잭션 분할, busy_timeout 검토 |
| INSERT 는 됐는데 화면 갱신이 안 됨 | RefreshList 미호출 | OnInsertClick 끝에 RefreshList() 추가 |
| DataGrid 컬럼이 어긋남 | 콤마 수가 Columns 수와 불일치 | DispData[i] 의 콤마 개수 확인 |
| 진행률이 100 % 에서 멈추지 않음 | OnBackupDone 미정의 | Database Events 에서 [+ Add] |
| 원격 MSSQL 가 끊긴 채로 표시되지 않음 | OnRemoteDbDisconnected 미정의 | UI 깜박임 처리를 후킹 |
학습 포인트
- 운영 안정성은 ‘세 가지 가시성’ 으로 만든다 —
LastError,OnDbError,XLog.AddError. - 백업은 운영 시작 전에 자동화 — 새벽 3시 + 7일 보관이 가장 보편적인 기본값입니다.
- DataGrid + array 패턴 을 한 번 손에 익히면,
order_history외 다른 테이블도 같은 방식으로 표시됩니다.log테이블, 운영 통계 등이 모두 동일한RefreshList+DispData+DataName조합으로 구현됩니다.
매뉴얼 마무리
이로써 9장의 학습 흐름이 끝났습니다. 정리하면:
- GUI 산출물 → 스크립트 입력 — Connection ✓ Schema ✓ SQL 검증 ✓ 가 모두 끝난 후에
.xms작성. - 빌트인 템플릿 우선 —
order_history/log는 그대로 사용. - DataGrid = DataName + array — 콤마 구분 문자열 한 행씩 채우면 자동 표시.
- 에러 가시성은 한 페이지로 —
LastError→OnDbError→XLog.AddError.
샘플 프로젝트는 QMS_Data\Samples\DatabaseSample\ 에 동봉되어 있으며,
order_history.json, Sample.xms, ViewOrderHistory.xaml/.xms 가 함께 들어있어 그대로 열어 학습할 수 있습니다.