Cheondi
개발 · 알고리즘·CS

깨진 JSON의 장애 격리

부분적으로 손상된 로컬 설정을 필드별로 검증하고 복구 범위를 줄인 기록입니다.

  • #json
  • #recovery
  • #validation

로컬 설정 JSON 일부가 잘린 상태에서 앱이 시작 화면을 넘지 못했다. 파싱 예외를 잡아 전체 설정 파일을 삭제하면 앱은 켜졌지만 사용자의 정상 설정까지 모두 사라졌다. 파일 하나 안에 여러 기능의 값이 섞여 있어 실패 범위가 너무 컸다.

무조건 성공하거나 전부 초기화하는 두 선택 사이에 부분 복구가 필요했다.

JSON 구조와 값 검증의 분리

먼저 JSON 문법을 읽고, 그다음 각 영역의 스키마와 값 범위를 검증했다.

var document = JsonDocument.Parse(raw);
var appearance = TryReadAppearance(document) ?? Appearance.Default;
var chart = TryReadChart(document) ?? ChartSettings.Default;
var alarms = TryReadAlarms(document) ?? AlarmSettings.Default;

문법 자체가 깨졌으면 마지막 정상 백업을 시도하고, 특정 영역만 잘못됐으면 그 영역만 기본값으로 바꿨다.

JSON 복구 결과의 사용자 안내

조용히 초기화하면 나중에 설정이 사라진 이유를 알 수 없다. 복구한 영역과 백업 위치를 민감하지 않은 표현으로 안내하고 다시 설정할 수 있는 화면으로 연결했다.

로그에는 원본 JSON이나 사용자 값을 남기지 않고 형식 버전, 실패 영역, 복구 방식만 기록했다.

복구 안내가 반복되지 않도록 정상 형식으로 다시 저장된 뒤에는 해당 상태를 끝냈다. 아직 복구되지 않은 백업을 사용자가 덮어쓰지 않게 설정 화면의 저장 시점도 조정했다.

정상 JSON 파일의 원자적 교체

저장 중 앱이 종료돼 반쪽 파일이 생기지 않도록 임시 파일에 쓴 뒤 검증하고 교체했다.

새 내용 -> temp 저장 -> 재읽기 검증
 -> 기존 파일 백업 -> temp를 활성 파일로 교체

WebGL처럼 저장 구현이 다른 플랫폼에서도 같은 완료 의미를 제공하도록 저장소 인터페이스에서 처리했다.

손상 입력 기반 복구 검증

필드 누락, 잘못된 타입, 범위 밖 숫자, 중간에서 잘린 JSON, 알 수 없는 새 필드를 생성해 확인했다. 알 수 없는 필드를 무조건 오류로 보지 않아 앞으로의 형식 확장도 고려했다.

이 작업 뒤 예외를 잡는 것만으로 복구됐다고 말하지 않는다. 정상 데이터를 얼마나 보존했고 다음 저장이 다시 정상 형식이 되는지 확인한다. 견고함은 오류를 숨기는 게 아니라 영향 범위를 줄이는 일이었다.

후속 확인 항목

작업 당시에는 눈앞의 오류를 먼저 고쳤지만, 이후 기술 문서와 맞춰 보며 확인 순서를 조금 더 구체화했다.

Unity의 JsonUtility 문서를 다시 읽어 보니, JSON을 자유로운 key-value 저장소처럼 다루기보다 직렬화 가능한 클래스와 필드에 대응시키는 도구라는 점이 더 분명했다. 모르는 필드는 무시되고 빠진 필드는 생성된 객체의 기본값으로 남을 수 있다. 따라서 파싱에 성공했다는 사실과 지금 화면에서 써도 되는 데이터라는 판단은 같지 않다.

RFC 8259도 객체 멤버의 순서를 상호운용 가능한 계약으로 기대하지 않는다. 배열 순서가 의미를 가져도 객체 필드가 적힌 순서까지 로직에 사용하면 다른 생성기나 마이그레이션에서 쉽게 깨진다.

다음에 깨진 JSON의 장애 격리 같은 문제를 보면 아래 순서부터 확인하려고 한다.

  • schema version과 마이그레이션 경로
  • 필수 필드·기본값·범위 검증
  • 깨진 항목만 격리하는 단위
  • 이전 버전으로 되돌릴 수 있는지

형식이 올바른 JSON이어도 필수 식별자, 범위, 버전이 맞지 않으면 화면 모델로 넘기지 않는 편이 안전하다.

공식 참고 자료