차트에 표시할 항목 하나를 설정 화면에 추가했다. 체크박스를 바꾸면 화면도 바로 반응했고 앱을 닫기 전까지는 아무 문제가 없었다. 그런데 다시 실행하면 새 옵션만 기본값으로 돌아왔다. 분명 저장 버튼을 눌렀고 기존 설정은 그대로 남아 있어서 처음에는 UI 초기화 문제라고 생각했다.
저장 파일을 직접 열어 보니 새 필드가 없었다. 설정 클래스에는 값을 추가했지만 실제 저장용 객체를 만드는 코드에는 옮기지 않았던 것이다. 읽는 쪽과 쓰는 쪽이 서로 다른 모델을 쓰고 있었다.
화면 상태와 저장 상태는 달랐다
체크박스의 값이 바뀌었다는 건 메모리 안의 현재 상태가 바뀌었다는 뜻이었다. 파일에 기록됐다는 뜻은 아니었다. 흐름을 나누어 적으니 빠진 단계가 보였다.
클릭 -> 화면 상태 변경 -> 저장 모델 생성 -> JSON 직렬화 -> 파일 기록
실행 -> 파일 읽기 -> JSON 역직렬화 -> 기본값 보정 -> 화면 반영
저장과 복원은 서로 반대 방향처럼 보이지만 실제 코드는 별도로 관리되고 있었다.
새 필드에는 이전 파일도 생각해야 했다
새 버전에서 필드를 추가해도 사용자의 기존 JSON에는 값이 없다. bool은 값이 없으면 false가 되기 때문에 의도한 기본값이 true라면 구분하기 어려웠다. 설정 버전이나 nullable 값을 활용해 이전 데이터와 사용자가 직접 끈 값을 나눌 필요가 있었다.
[Serializable]
public class ChartSettings
{
public int version = 2;
public bool? showGuideLine;
}
bool showGuide = saved.showGuideLine ?? true;
실제 구조에서는 사용 중인 JSON 라이브러리가 nullable을 어떻게 처리하는지도 확인해야 했다.
저장 직후 다시 읽어 봤다
버튼을 눌렀다는 사실만으로 성공을 판단하지 않고 저장된 파일의 내용과 재실행 결과를 확인했다. 새 파일, 이전 버전 파일, 일부 필드가 빠진 파일을 각각 준비해 보니 기본값 처리가 어디에서 필요한지도 분명해졌다.
JSON이 깨졌을 때 전체 설정을 초기화할지, 정상인 필드는 살릴지도 별도 결정이었다. 무조건 새 객체를 만들면 사용자의 다른 설정까지 사라질 수 있었다.
필드 하나가 데이터 변경이었다
처음에는 설정 옵션 추가를 체크박스 하나를 만드는 UI 작업으로 봤다. 실제로는 저장 모델, 직렬화, 이전 버전과의 호환, 복원 시점까지 이어지는 데이터 변경이었다.
그 뒤로 저장되는 값을 수정할 때는 쓰는 코드와 읽는 코드를 함께 찾게 됐다. 화면에서 지금 잘 보이는지만 확인하지 않고 앱을 껐다 켜도 남는지, 이전 파일을 읽어도 안전한지를 체크했다. 작은 설정 하나 덕분에 상태의 수명은 화면보다 길다는 걸 배웠다.