Cheondi
개발 · Unity

macOS 저장 경로 차이

Windows 기준으로 만든 저장 경로가 macOS에서 실패하며 플랫폼 경로와 권한을 배운 기록입니다.

  • #unity
  • #macos
  • #filesystem

Windows에서 잘 저장되던 설정 파일을 macOS 빌드에서 찾지 못하는 문제가 있었다. 파일 이름도 같고 JSON 내용도 같아서 경로 문자열의 구분자만 바꾸면 될 줄 알았다. 실제로는 앱이 쓸 수 있는 위치, 패키지 안의 읽기 전용 리소스, 사용자 데이터 위치가 플랫폼마다 달랐다.

개발 PC의 프로젝트 폴더를 기준으로 만든 상대 경로가 빌드 뒤에도 존재할 거라는 가정부터 잘못됐다.

플랫폼 API 기반 경로 생성

"/""\\"를 직접 넣는 대신 플랫폼 API와 Path.Combine을 사용했다.

string settingsPath = Path.Combine(
    Application.persistentDataPath,
    "settings",
    "user.json");

Directory.CreateDirectory(Path.GetDirectoryName(settingsPath));

실행 중 수정할 파일은 영구 데이터 경로에 두고, 앱과 함께 배포되는 초기 파일은 스트리밍 리소스에서 읽어 첫 실행에 복사했다.

파일명 대소문자 검증

개발 환경에서는 우연히 동작하던 Settings.jsonsettings.json 차이가 다른 파일 시스템에서 문제를 만들 수 있었다. 코드의 경로와 실제 배포 파일 이름을 같은 규칙으로 맞췄다.

저장 실패 로그에는 전체 사용자 경로를 그대로 남기지 않고 파일 종류, 작업 단계, 예외 종류를 기록했다. 개발 빌드에서만 필요한 경우 안전하게 경로를 확인했다.

쓰기 이후 읽기 검증

예외가 없었다고 저장된 것으로 끝내지 않았다. 임시 파일에 쓴 뒤 교체하고, 다시 열어 JSON 헤더와 버전을 확인했다. 앱 종료 후 재실행, 사용자 계정 변경, 이전 파일이 있는 상태도 시험했다.

파일이 깨졌으면 원본을 바로 덮지 않고 복구 가능한 사본을 남긴 뒤 기본 설정으로 시작했다. 복구 정책은 데이터 중요도에 맞춰 정했다.

같은 시나리오를 Windows와 macOS에서 반복해 플랫폼별 결과를 나란히 비교했다.

외부 환경으로서의 파일 시스템

API 서버만 외부 의존성이라고 생각했지만 파일 시스템도 플랫폼과 권한에 따라 행동이 달랐다. 코드가 같은 경로 문자열을 만들었다고 같은 장소를 의미하진 않았다.

이 경험 이후 파일 기능을 만들 때 목표 플랫폼의 쓰기 가능 위치와 수명부터 확인한다. Windows에서 저장됐다는 증거는 macOS 저장의 증거가 아니었다. 작은 경로 문제로 플랫폼 추상화의 이유를 제대로 느꼈다.

유사 문제 대응 기준

이 문제를 고친 뒤 관련 공식 자료를 찾아 읽으면서, 당시 코드에서 우연히 맞았던 부분과 규칙으로 남겨야 할 부분을 나눠 봤다.

Unity 실행 순서 문서는 Awake, OnEnable, Start, Update 같은 엔진 이벤트가 어느 구간에서 호출되는지 설명한다. 하지만 로딩·성공·빈 결과·실패 같은 업무 상태의 순서까지 대신 정해 주지는 않는다. 두 종류의 순서를 섞어 생각하면 콜백이 한 프레임 늦게 왔다는 이유만으로 이전 화면 상태가 다시 살아날 수 있다.

그래서 수명주기 메서드는 상태 전이를 직접 흩어 놓는 장소보다, 한 곳에 모인 전이 함수를 호출하는 경계로 쓰는 편이 추적하기 쉬웠다.

다음에 macOS 저장 경로 차이 같은 문제를 보면 아래 순서부터 확인하려고 한다.

  • 입력 조건과 현재 상태를 한 줄로 기록
  • 성공·빈 값·실패·취소를 구분
  • 늦은 응답과 중복 이벤트 처리
  • 실제 대상 환경에서 회귀 확인

새 응답을 적용하기 전에 요청 식별자와 현재 선택 조건이 여전히 같은지 확인해야 오래된 응답을 버릴 수 있다.

공식 참고 자료