데이터 호환성과 백업 복원
90분 안팎
학습 목표
이미지 롤백과 데이터 복원을 구분합니다.
개념
이미지를 되돌려도 데이터는 남습니다
후보가 안내판 제목을 잘못 바꿨다면 이전 이미지를 선택해도 같은 볼륨을 읽습니다. 코드 복구와 데이터 복원은 다른 작업입니다. 코드만 실패했는데 데이터까지 과거로 덮어쓰면 배포 뒤의 정상 변경을 잃을 수 있습니다. 데이터가 손상됐는데 image ID만 되돌리면 조회 실패가 계속됩니다. 이번 레슨은 원본을 유지하고 새 복원 위치에서 백업과 이전 코드의 읽기 동작을 검사합니다. 두 작업의 필요 조건을 구분하여 실행 성공보다 사용자 데이터의 정확성을 복구 기준으로 삼습니다.
기준 시점과 허용 손실을 적습니다
백업에는 언제 어떤 데이터를 채취했는지와 어느 형식인지 기록합니다. 복구 목표 시간은 요청을 다시 제공하기까지 허용할 시간이고 복구 시점 목표는 어느 정도의 최근 변경 손실을 허용하는지의 기준입니다. 이 실습은 쓰기 API 없는 파일을 변경 전에 채취하므로 제목 원본 바이트가 기준입니다. 실제 DB는 엔진의 일관된 백업과 로그 재생이 필요할 수 있습니다. 파일 하나 실험을 전체 서비스 백업 보장으로 확대하지 않습니다. 백업 후 정상 변경이 있으면 어떻게 보존할지도 실제 복구 전에 판단합니다.
백업 내용은 필요한 데이터로 좁힙니다
save는 notice.txt와 manifest.json만 tar에 저장하고 로그와 외부 token은 넣지 않습니다. manifest에는 schema text-v1, 데이터 바이트 수와 SHA-256을 기록합니다. UTF-8이며 공백 제거 후 제목이 비어 있지 않고 65536바이트 이하라는 교육 계약입니다. m06 구버전은 한 제목의 평문을 읽습니다. 미션에서는 실제 이전 이미지 /notices의 id·title까지 비교하므로 압축 해제 성공만으로 인정하지 않습니다. 파일 이름과 구조를 제한하면 비밀이나 필요 없는 시스템 자료가 백업에 섞이는 실수를 줄입니다.
신뢰한 checksum을 별도로 보관합니다
archive SHA-256은 변경 전 기준으로 남기고 restore에 reference로 전달합니다. 전송 손상은 기준값과 달라 중단됩니다. 백업과 checksum을 함께 바꿀 수 있는 공격에는 발신자 인증이 되지 않으므로 reference는 신뢰한 기록에서 보존합니다. 압축 안의 manifest checksum은 데이터와 메타데이터의 일치를 확인하고 외부 reference는 archive 전체의 변경을 확인합니다. 범위가 달라 하나로 다른 검사를 대체하지 않습니다. 백업과 기준값을 같은 편집 가능한 입력에서 새로 계산하면 손상도 정상으로 만들 수 있습니다.
풀기 전에 항목 종류를 확인합니다
tar는 정상 파일 외에 절대 경로·상위 경로·심볼릭 링크·중복 항목을 담을 수 있습니다. restore는 항목이 정확히 두 개이고 이름 집합이 notice.txt와 manifest.json인지 확인합니다. 모두 일반 파일이며 크기 제한도 만족해야 합니다. extractall로 현재 경로에 풀지 않고 검증한 항목의 바이트만 읽습니다. manifest의 형식·크기·checksum과 UTF-8을 확인한 뒤 목적지를 만듭니다. 원본을 보호하려면 파싱이 끝나는 순서와 실제 파일을 쓰는 순서를 구분해야 합니다. 임의 경로를 따라 쓰는 압축 해제는 제공하지 않습니다.
새 목적지를 함수에서 강제합니다
destination은 존재하지 않는 경로여야 합니다. 기존 디렉터리가 비어 있어도 거부하고 심볼릭 링크도 거부합니다. 이미 파일이 있는 위치를 허용하면 경로 선택 실수가 즉시 덮어쓰기로 이어집니다. checksum이나 항목 오류에는 목적지 자체가 생성되지 않았는지도 검사합니다. 새 위치에 검증한 내용을 쓴 뒤 원본과 바이트를 비교하고 별도 읽기 검사를 수행합니다. 복원 결과를 자동으로 원본 경로로 승격하지 않습니다. 검증 가능한 리허설을 먼저 제공하여 실제 전환 판단에 쓸 근거를 만듭니다.
starter의 누락을 작은 실패로 찾습니다
시작 코드는 항목 검사와 새 목적지 조건은 갖췄지만 archive checksum과 reference 비교가 없습니다. 정상 왕복과 기존 목적지 보호는 통과해도 손상본이나 잘못된 기준값을 받아들이는 사례는 실패합니다. restore의 조건을 보완하며 테스트 reference를 새 checksum으로 바꾸지 않습니다. 파일 끝에 바이트가 붙어도 tar parser는 읽을 수 있어 파싱 성공만 검사하면 손상을 놓칩니다. 이 실패에서 외부 기준값의 역할을 설명할 수 있어야 합니다. 기대값을 바꾸는 대신 누락된 검증을 복원 함수에 넣습니다.
이전 읽기 동작으로 호환성을 확인합니다
schema 이름이 맞다는 주장만으로 이전 버전 호환을 보장하지 않습니다. 다른 인코딩은 읽기 실패를 만들 수 있고 JSON 변경은 문자열로 읽혀도 사용자가 기대한 제목과 다를 수 있습니다. 파일 실습은 text-v1 계약을, 미션은 복원 볼륨에 이전 image ID를 시작하여 실제 /notices의 id·title을 비교합니다. 로그 쓰기와 제목 보존은 구분합니다. 새 구조를 도입한다면 구버전도 읽을 수 있는 확장을 먼저 적용하는 순서를 설계합니다. 이번 미션은 데이터 형식을 변경하지 않습니다.
별도 볼륨에서 읽기 리허설을 합니다
Docker 미션은 기존 project-data를 읽기 전용으로 연결한 helper에서 제목만 채취합니다. 검증한 내용은 새 project-m07-restore-data로 옮깁니다. 그 볼륨에 이전 이미지를 UID 10001로 실행하고 같은 외부 비밀 경로를 읽기 전용 연결합니다. 파일 복사 뒤 소유권을 맞추는 것은 helper 초기화입니다. 이전 버전의 인증한 조회가 성공해야 호환성 통과입니다. 원본 볼륨을 삭제하거나 백업으로 덮어쓰지 않습니다. 별도 복원 볼륨과 실제 구버전이 연결되는지는 Docker 외부 실행으로 확인합니다.
오류를 입력과 환경으로 나눕니다
archive checksum mismatch는 자료와 기준값부터 조사합니다. unexpected archive entries와 unsafe archive member는 목록과 종류의 계약 위반입니다. manifest mismatch는 형식·바이트 수·데이터 checksum을 확인하게 합니다. UTF-8 오류는 내용 해석 문제입니다. 컨테이너 permission denied는 소유 UID와 부모 경로를, 인증 401은 토큰 전달을 조사합니다. 제목 손상으로 모든 오류를 설명하지 않습니다. 개인 데이터나 비밀이 오류 원문에 섞일 수 있으므로 결과 증거에는 필요한 검사 종류와 성공 여부만 남깁니다.
원본 보존까지 복원 증거입니다
검사는 왕복·기존 목적지·손상본·잘못된 reference·상위 경로·절대 경로·링크·중복 항목·manifest 불일치·미지원 schema·잘못된 UTF-8의 11개 사례입니다. 마지막에 원본 바이트도 그대로인지 확인합니다. 기본 안내문을 새로 생성한 결과를 복원이라고 보지 않습니다. 미션 증거에는 백업과 데이터 checksum, 실제 이전 이미지 응답 일치가 남습니다. 실제 데이터 전환에는 쓰기 중지와 정상 변경 재생 판단이 추가로 필요합니다. README에 기준 시점·검사 범위·남은 자원을 적고 tar 옵션의 자세한 내용은 더 읽기로 보냅니다.
볼륨의 독립적인 수명과 백업·복원 참고: Docker 볼륨 공식 문서. 컨테이너와 데이터를 별도로 다루는 원리를 확인합니다.
따라하기
내용 변경과 checksum 비교
줄바꿈 한 바이트가 달라도 원본 무결성 비교는 실패합니다. 제목의 표시 결과와 보존할 원본 바이트를 구분합니다.
import hashlib
a='배포 연습 안내\n'.encode('utf-8');b='배포 연습 안내'.encode('utf-8')
print('same visible title:',a.decode().strip()==b.decode().strip())
print('same bytes:',a==b)
print('same checksum:',hashlib.sha256(a).digest()==hashlib.sha256(b).digest())실행 결과
same visible title: True same bytes: False same checksum: False
복원 순서와 starter 누락 확인
starter.zip 루트에서 archive checksum을 reference와 비교하는 조건을 넣습니다. 항목·manifest·내용 검사를 마친 뒤에만 새 destination을 만드는 순서는 유지합니다. 손상본이 읽히더라도 거부되어야 합니다.
cat backup.py
bash check.shsolution의 안전 복원 사례 재현
solution.zip 루트에서 실행한 실제 출력입니다. 원본 보존과 새 목적지 조건까지 함께 확인합니다. 테스트용 파일은 임시 디렉터리에 생성되고 검사 뒤 정리됩니다.
bash check.sh실행 결과
PASS roundtrip and original preservation PASS existing destination retained PASS corrupt archive PASS wrong trusted reference PASS traversal PASS absolute path PASS symlink PASS duplicate member PASS manifest mismatch PASS unsupported schema PASS invalid UTF-8 PASS 11 restore cases; checksum, safe entries, compatibility, original preserved
미션에서 구버전과 별도 볼륨 확인
파일 검사 통과 후 모듈 미션 zip에서 README의 입력 준비를 마치고 실행합니다. -m07-restore-data에 복원한 제목을 실제 이전 image ID로 읽는지, 최종 evidence의 restorePreviousResponseEqual과 원본 checksum이 맞는지 확인합니다. 원본 볼륨에 직접 복원하지 않습니다. Docker 실행은 외부 대기입니다.
bash check.sh확인 문제
실습
backup.py restore에 archive SHA-256과 신뢰한 reference 비교를 추가합니다. 새 목적지·일반 파일 두 개·고정 이름·크기·text-v1·데이터 checksum·UTF-8 검사를 유지합니다. 원본 notice.txt를 덮어쓰지 않고 별도 경로에 복원합니다. bash check.sh로 손상·경로 탈출·링크·중복·형식 불일치와 원본 보존을 검사합니다. 미션에서는 같은 복원 로직을 별도 Docker 볼륨과 실제 구버전 사용자 응답 검사로 확장합니다.
실행 명령
bash check.sh
기대 결과
11개 복원 사례 통과, 잘못된 백업은 목적지 생성 전에 거부하고 원본 바이트를 유지합니다.
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 실패한 배포의 롤백 기준과 검증을 설명합니다.