백업 폴더에 오늘 날짜의 파일이 생기면 안심하기 쉽습니다. 하지만 파일의 존재가 알려주는 것은 저장물이 있다는 사실까지입니다. 필요한 메모가 들어 있는지, 별도 환경에서 읽을 수 있는지, 원하는 시점의 내용인지는 다시 열어봐야 알 수 있습니다. 개인 앱의 백업을 점검할 때는 복사 성공 메시지 다음에 작은 복원 실험을 붙여보세요.
여기서는 SQLite에 메모를 저장하는 가상 앱을 예로 듭니다. 원본과 백업, 복원 파일을 구분하고 구조·관계·내용을 차례로 확인합니다. 실제 서비스의 데이터는 사용하지 않았습니다. 아래 실험은 Python 3.9.6과 SQLite 3.51.0에서 임시 데이터로 실행했으며, 앱 화면이나 운영 서버까지 복구한 결과는 아닙니다.
1. 원본과 다른 곳에 복원하기

그림 1. 백업 파일을 별도 복원 DB로 옮긴 뒤 검사합니다. 원본 DB는 복원 대상으로 사용하지 않습니다.
먼저 파일 세 개의 역할을 나눕니다. source.db는 지금 사용 중인 데이터를 가정한 원본, backup.db는 보관할 사본, restored.db는 읽기 시험을 할 복원본입니다. 연습하면서 원본 자리에 백업을 덮어쓰면, 확인하려던 작업이 현재 데이터를 되돌리는 작업이 됩니다. 파일 이름뿐 아니라 각 연결이 어느 경로를 가리키는지도 확인해야 합니다.
SQLite의 Online Backup API는 한 데이터베이스의 내용을 다른 데이터베이스로 복사합니다. Python에서는 원본 연결의 backup 메서드에 대상 연결을 넘깁니다. 즉 src.backup(bak)은 원본에서 백업으로, bak.backup(out)은 백업에서 복원본으로 향합니다. 대상에 기존 내용이 있다면 대체될 수 있으므로, 예제는 실행할 때마다 새 임시 폴더를 만듭니다.
이 방식은 실행 중인 데이터베이스의 백업을 위한 기능이지만, 여기서는 동시 쓰기나 대용량 처리 시간을 시험하지 않았습니다. 복사 중인 파일을 아무 때나 운영 앱에 붙여도 된다는 뜻도 아닙니다. 앱마다 연결을 끊는 절차, 파일 권한, 저장소 위치가 다릅니다. 우선 별도 복원본을 확보해 내용을 확인하고, 운영 전환은 그다음 단계로 나누는 편이 판단하기 쉽습니다.
2. 구조가 정상이어도 내용은 다를 수 있다

그림 2. 구조 검사, 연결 관계 검사, 기대한 내용 비교는 서로 다른 질문에 답합니다.
복원본에서 PRAGMA integrity_check를 실행하면 데이터베이스의 낮은 수준 구조와 일관성을 점검합니다. 문제가 발견되지 않으면 ok 한 줄이 반환됩니다. 이것은 필요한 확인이지만, “내가 기대한 문장이 저장되어 있다”는 확인은 아닙니다. 정상적인 UPDATE로 메모 본문을 잘못 바꿔도 데이터베이스 구조 자체는 멀쩡할 수 있습니다.
관계도 따로 봐야 합니다. 메모에 붙인 태그가 어느 메모를 가리키는지 외래키로 선언한 앱이라면 PRAGMA foreign_key_check를 추가합니다. 위반이 있으면 해당 항목이 결과로 나옵니다. integrity_check는 외래키 오류를 찾지 않습니다. 다만 외래키를 아예 선언하지 않은 관계까지 자동으로 알아내는 검사는 아니므로, 결과가 비었다고 모든 업무 규칙이 검증된 것은 아닙니다.
마지막은 내용 비교입니다. 총 3건이라는 숫자만 맞추지 말고, 메모 ID와 본문을 함께 비교합니다. 날짜나 상태가 중요한 앱은 그 값도 포함합니다. 목록을 정렬하는 기준이 있다면 같은 조건으로 조회해야 비교가 흔들리지 않습니다. 이 세 검사를 분리해 두면 실패했을 때도 구조 문제인지, 연결 관계 문제인지, 기대한 값의 차이인지 설명할 수 있습니다.
3. 메모 세 건으로 확인하는 작은 실험

그림 3. 백업 뒤에 원본의 2번 메모를 바꿔도, 이전 백업을 복원하면 백업 당시의 문장이 나와야 합니다.
실험의 기준은 단순합니다. 메모 1·2·3을 저장하고 변경 내용을 확정한 다음 백업합니다. 그 뒤 원본의 2번 본문만 바꿉니다. 백업을 새 DB에 복원했을 때 2번 메모가 예전 문장인 “우유와 빵”으로 남아 있으면, 이번 실험에서는 백업 시점과 현재 원본이 구분된 것입니다. 원본의 최신 내용과 복원본이 다르다는 이유만으로 실패라고 볼 수는 없습니다.
아래 코드는 Python 표준 라이브러리만 사용합니다. 새 파일에 저장해 python3로 실행하면 됩니다. 기존 DB 경로를 입력받지 않고 임시 폴더 안에서 세 파일을 만들며, 연결을 닫고 나면 연습용 파일도 정리됩니다. expected는 DB를 읽어서 나중에 만든 답안이 아니라, 저장하기 전에 정한 기대값입니다. 그래야 잘못 복원된 값을 정답으로 받아들이는 실수를 피할 수 있습니다.
from contextlib import ExitStack, closing
from pathlib import Path
from tempfile import TemporaryDirectory
import sqlite3
with TemporaryDirectory() as tmp, \
ExitStack() as stack:
db = {}
for name in ("source", "backup", "restored"):
path = Path(tmp) / (name + ".db")
db[name] = stack.enter_context(
closing(sqlite3.connect(path)))
src, bak, out = [db[n] for n in db]
expected = [(1, "메모 하나"),
(2, "우유와 빵"),
(3, "앱 아이디어")]
src.execute(
"CREATE TABLE notes("
"id INTEGER PRIMARY KEY, body TEXT)")
src.executemany(
"INSERT INTO notes VALUES (?, ?)",
expected)
src.commit()
src.backup(bak)
src.execute(
"UPDATE notes SET body=? WHERE id=2",
("수정한 문장",))
src.commit()
bak.backup(out)
structure = out.execute(
"PRAGMA integrity_check").fetchall()
actual = out.execute(
"SELECT id, body FROM notes "
"ORDER BY id").fetchall()
assert structure == [("ok",)]
assert actual == expected
print("구조 검사:", structure)
print("복원한 메모:", len(actual), "건")
print("2번 메모:", actual[1][1])
실행 결과는 구조 검사 [('ok',)], 복원한 메모 3건, 2번 메모 우유와 빵입니다. assert는 결과가 기대와 다르면 실행을 실패시키는 조건입니다. 이 짧은 코드에는 외래키 관계를 만들지 않았으므로 관계 검사는 넣지 않았습니다. 별도 합성 실험에서는 태그가 존재하지 않는 메모를 참조하게 만들었고, 구조 검사는 ok였지만 외래키 검사에서는 위반 1건이 나오는 것을 확인했습니다.
또 다른 실험에서는 복원본의 본문만 바꾸었습니다. 행 수는 여전히 3건이고 구조 검사도 ok였지만, 미리 정한 ID·제목·본문과의 비교는 실패했습니다. 백업 파일 크기나 행 수 하나를 완료 기준으로 삼기 어려운 이유입니다. 검사는 많이 실행하는 것보다, 서로 다른 실패를 잡도록 나누는 쪽이 유용합니다.
4. DB 복원과 앱 복구 사이에 남는 일
DB가 읽힌다고 앱 전체가 돌아온 것은 아닙니다. 예를 들어 메모의 첨부 사진을 별도 폴더에 저장했다면 DB에는 파일 이름만 있을 수 있습니다. 이때 DB 백업만 복원하면 목록은 보이지만 사진은 열리지 않을 수 있습니다. 설정 파일, 앱 버전, 외부 저장 파일 가운데 무엇이 함께 있어야 하는지 복원 범위를 미리 적어둡니다.
실제 앱에서는 복원본을 연결한 테스트 환경에서 목록 조회, 한 건 열기, 검색 같은 핵심 동작도 확인할 차례입니다. 시험 환경이 운영 알림이나 외부 전송을 실행하지 않도록 분리하는 것도 필요합니다. 이번 글에서 실행한 것은 SQL 조회와 합성 데이터 비교까지이며, 특정 앱의 화면·첨부 파일·배포 절차가 통과했다는 주장은 하지 않습니다.
5. 성공 기록에 파일 이름보다 남겨둘 것
복원 기록에는 사용한 백업, 데이터가 담긴 시점, 복원한 위치, 실행한 검사와 결과를 함께 적습니다. “백업 성공” 한 줄보다 “메모 3건의 ID·본문 일치, 구조 검사 ok, 앱 화면 확인은 남음”이라는 기록이 다음 판단에 도움이 됩니다. 확인하지 못한 범위를 같이 적어야 나중에 기록을 읽는 사람이 검증 범위를 크게 오해하지 않습니다.
백업의 간격도 이 기록과 연결됩니다. 마지막 백업 이후에 작성한 메모는 그 사본에 없으므로, 얼마만큼의 작업을 다시 입력할 수 있는지 생각해야 합니다. 별도 파일로 시험하는 것은 복원 가능성을 확인하는 단계이지, 같은 장치에 둔 모든 파일을 잃는 상황까지 대비한 것은 아닙니다. 처음에는 작은 합성 데이터로 절차를 익히고, 그다음 앱의 실제 저장 범위와 보관 위치에 맞게 검증을 넓혀보세요.
'AI BOX' 카테고리의 다른 글
| 개인 앱의 오류 메시지: 사용자가 다음 행동을 알게 만들기 (0) | 2026.09.22 |
|---|---|
| 개인 앱의 날짜가 하루 밀릴 때: 저장 시간과 표시 시간 구분하기 (0) | 2026.09.21 |
| 바이브 코딩이 막히는 건 모델이 아니라 지도다 (0) | 2026.08.18 |
| 🤖 생성형 AI 4종 비교! (3) | 2025.07.29 |