
어렸을 때 유치원에서 그림을 그리고 나면 부모님은 항상 그 그림을 클리어화일이라고 부르던 물건에 담아 보관하시곤 했다.
초중고 때는 나도 서류철(폴더)을 사용해 학업과 관련한 서류(파일)를 정리한 기억이 있다.
그렇다면 iOS에서는 파일을 어떻게 관리할까?
The file system is an important part of any operating system. After all, it’s where users keep their stuff.
OS의 중요한 부분으로 유저의 파일을 보관하는 곳이 파일 시스템이라고 한다.
A file system handles the persistent storage of data files, apps, and the files associated with the operating system itself. Therefore, the file system is one of the fundamental resources used by all processes.
그리고 이 파일 시스템은 파일의 영구 저장을 처리하기 때문에 모든 프로세스에서 사용되는 기본 리소스라고 한다.
iOS의 기본 파일 시스템은 iOS 10.3 이상일 때는 APFS이다. 그 이전에는 HFS+라는 파일 시스템이 기본 파일 시스템이었던 것 같은데 오늘 알아볼 주제는 아니므로 패스.
iOS와 macOS의 기본 디렉터리 구조는 유사하지만, 각 시스템이 앱과 사용자 데이터를 구성하는 방식에는 차이가 있기 때문에 오늘은 iOS의 파일 시스템에만 초점을 맞춰서 알아보도록 하자.


우선 앱은 적절한 보안 권한이 있는 디렉터리에만 파일을 작성할 수 있다.

또, 앱은 파일을 적절한 위치에 배치해야 한다.
파일을 저장하는 정확한 위치는 플랫폼에 따라 다르지만 가장 중요한 목표는 사용자의 파일을 쉽게 검색할 수 있도록 하고 코드에서 내부적으로 사용하는 파일이 사용자의 방해가 되지 않도록 하는 것이다.

The iOS file system is geared toward apps running on their own. To keep the system simple, users of iOS devices do not have direct access to the file system and apps are expected to follow this convention.
시스템의 단순화를 위해 사용자가 직접 파일 시스템에 접근할 수 없다.

앱에는 샌드박스라고 하는 디렉터리가 있다. 보안을 위해 iOS 앱과 파일 시스템의 상호 작용은 앱의 샌드박스 디렉터리 내부 디렉터리로 제한된다.
새 앱을 설치하는 동안 설치 프로그램은 샌드박스 디렉터리 내에 앱에 대한 여러 컨테이너 디렉터리를 생성한다.
앞서 말한 것처럼 앱은 일반적으로 컨테이너 디렉터리 외부의 파일에 액세스하거나 파일을 생성하는 것이 금지되지만 앱이 공개 시스템 인터페이스를 사용하여 사용자의 연락처나 음악과 같은 항목에 액세스하는 경우는 예외가 된다. 이러한 경우 시스템 프레임워크는 도우미 앱을 사용하여 적절한 데이터 저장소를 읽거나 수정하는 데 필요한 파일 관련 작업을 처리한다.

각 컨테이너 디렉터리에는 특정 역할이 있다.
데이터 컨테이너 디렉터리는 앱이 데이터를 정렬하고 구성하는 데 사용할 수 있는 여러 하위 디렉터리로 더 나뉜다.
앱은 런타임 시 사진의 iCloud 컨테이너처럼 추가 컨테이너 디렉터리에 대한 액세스를 요청할 수도 있다.
iOS 앱은 Documents, Library 및 tmp 디렉터리에 추가 디렉터리를 생성할 수 있다.
그야말로 앱 그 잡채
AppName.app은 앱의 번들이다. 이 디렉터리에는 앱과 해당 리소스가 모두 포함되어 있다.

이 디렉터리에는 쓸(write) 수 없다. 변조를 방지하기 위해 번들 디렉터리는 설치 시 서명되는데, 이 디렉터리에 써버리면 서명이 변경되어 앱이 실행되지 않는다. 하지만 앱 번들에 저장된 모든 리소스에 대한 읽기 전용(read-only) 액세스 권한은 얻을 수 있다.
이 디렉터리의 콘텐츠는 iTunes나 iCloud에 의해 백업되지는 않지만 iTunes는 App Store에서 구입한 모든 앱의 초기 동기화를 수행한다.
Documents 디렉터리를 사용하여 사용자 생성 콘텐츠를 저장한다. 이 디렉터리의 내용은 파일 공유를 통해 사용자에게 공개될 수 있다. 따라서 이 디렉토리에는 사용자에게 공개하려는 파일만 포함되어야 한다.
이 디렉터리의 내용은 iTunes와 iCloud에 의해 백업된다.
외부 엔터티에서 앱을 열도록 요청한 파일에 액세스하려면 Documents/Inbox 디렉터리를 사용한다. 특히 메일 프로그램은 앱과 관련된 이메일 첨부 파일을 이 디렉터리에 배치한다. 문서 상호작용 컨트롤러는 파일을 여기에 배치할 수도 있다.
앱은 이 디렉터리의 파일을 읽고 삭제할 수 있지만 새 파일을 만들거나 기존 파일에 쓸 수는 없다. 사용자가 이 디렉터리의 파일을 편집하려고 하면 앱은 변경하기 전에 해당 파일을 디렉터리 밖으로 자동으로 이동해야 한다.
이 디렉토리의 내용은 iTunes와 iCloud에 의해 백업된다.
Library는 사용자 데이터 파일이 아닌 모든 파일의 최상위 디렉터리이다. 일반적으로 여러 표준 하위 디렉터리 중 하나에 파일을 저장합니다. iOS 앱은 보통 Application Support 및 Caches 하위 디렉터리를 사용한다. 커스텀 하위 디렉터리를 만들 수도 있다.
사용자에게 노출되기를 원하지 않는 파일은 Library 하위 디렉터리를 사용한다. 앱은 사용자 데이터 파일에 이러한 디렉터리를 사용해서는 안 된다.
Caches를 제외한 Library 디렉터리의 콘텐츠는 iTunes 및 iCloud에 의해 백업된다.
tmp 디렉터리를 사용하여 앱 실행 간에 유지될 필요가 없는 임시 파일을 쓴다. 더 이상 필요하지 않은 파일은 이 디렉터리에서 제거해야 한다. 앱이 실행되지 않을 때 시스템은 이 디렉터리를 제거할 수 있다.
이 디렉터리의 콘텐츠는 iTunes나 iCloud에 의해 백업되지 않는다.

iOS 장치의 동기화 및 백업 프로세스에 시간이 오래 걸리지 않도록 하려면 파일을 저장할 위치를 선택해야 한다.

대용량 파일을 저장하는 앱은 iTunes 또는 iCloud에 백업하는 과정을 느리게 할 수 있고, 이러한 앱은 사용자의 사용 가능한 저장 공간을 많이 소모할 수 있으며, 이로 인해 사용자가 앱을 삭제하거나 해당 앱의 데이터를 iCloud에 백업하지 못하게 할 수도 있다.
Documents/에 사용자 데이터를 넣는다.
사용자 데이터에는 일반적으로 사용자에게 공개하려는 모든 파일, 즉 사용자가 생성, 가져오기, 삭제 또는 편집하기를 원하는 모든 파일이 포함된다.

그리기 앱의 경우 사용자 데이터에는 사용자가 만들 수 있는 모든 그래픽 파일이 포함된다. 텍스트 편집기의 경우 텍스트 파일이 포함된다. 비디오 및 오디오 앱에는 사용자가 나중에 보거나 듣기 위해 다운로드한 파일이 포함될 수도 있다.
앱에서 생성한 지원 파일을 Library/Application support/ 디렉터리에 넣는다.
일반적으로 이 디렉터리에는 앱을 실행하는 데 사용하지만 사용자에게는 숨겨져 있어야 하는 파일이 포함된다. 이 디렉터리에는 앱 번들에서 로드된 리소스의 데이터 파일, 구성 파일, 템플릿 및 수정된 버전도 포함될 수 있다.
Documents/ 및 Application Support/의 파일은 기본적으로 백업된다.
NSURLIsExcludedFromBackupKey 키를 사용하여 [NSURL setResourceValue:forKey:error:]를 호출하면 백업에서 파일을 제외할 수 있다. 다시 생성하거나 다운로드할 수 있는 파일은 모두 백업에서 제외해야 한다.

아까 본 하얀 코끼리처럼 대용량 미디어 파일의 경우 특히 중요하다. 앱이 비디오나 오디오 파일을 다운로드하는 경우 해당 파일이 백업에 포함되지 않았는지 확인해야 한다.
임시 데이터를 tmp/ 디렉터리에 넣는다.
임시 데이터는 장기간 유지할 필요가 없는 모든 데이터로 구성된다. 사용자 기기의 공간을 계속 소모하지 않도록 작업이 끝나면 해당 파일을 삭제하는 것을 잊지 말아야 한다.

앱이 실행되지 않을 때 시스템은 주기적으로 tmp 디렉터리의 파일을 제거하기 때문에 앱이 종료된 후에는 tmp의 파일이 남아있을지 보장할 수 없다.
데이터 캐시 파일을 Library/Caches/ 디렉터리에 넣는다.
캐시 데이터는 임시 데이터보다 오래 지속되어야 하지만 지원 파일만큼 오래 지속되지는 않는 모든 데이터에 사용할 수 있다. 일반적으로 응용 프로그램이 작동하는 데에 캐시 데이터가 필요하지 않지만 캐시 데이터를 사용하여 성능을 향상시킬 수 있다.
캐시 데이터의 예시로는 데이터베이스 캐시 파일 및 임시 다운로드 가능한 콘텐츠 등이 있다.

시스템은 디스크 공간을 확보하기 위해 Caches/ 디렉터리를 삭제할 수 있으므로 앱은 필요에 따라 이러한 파일을 다시 생성하거나 다운로드할 수 있어야 한다.
앞선 설명을 보면 iCloud 백업이나 저장에 대한 이야기가 왕왕 있다. iCloud로 파일을 저장할 필요가 있는 앱들이 있다는 것이다.
그러한 앱들이 iCloud를 어떻게 쓰는가?
iCloud provides a structured system for storing files for apps that make use of iCloud
앱은 로컬 파일 및 디렉터리를 생성하는 것과 똑같은 방식으로 iCloud 컨테이너 디렉터리에 파일 및 디렉터리를 생성합니다. 그리고 파일의 모든 속성이 저장된다. 파일에 확장 속성을 추가하면 해당 속성이 iCloud 및 사용자의 다른 장치에도 복사된다.
iCloud 컨테이너를 사용하면 문서 형식을 만들지 않고도 쉽게 액세스할 수 있는 키-값 쌍을 저장할 수 있다.
앞서 보안을 위해 iOS 앱과 파일 시스템의 상호 작용은 앱의 샌드박스 디렉터리 내부 디렉터리로 제한된다고 했는데, 그럼 그 보안은 어떻게 동작할까?
이러한 제한사항은 앱의 보안이 침해되는 경우 발생할 수 있는 잠재적 피해를 제한하기 때문에 개발자는 앱을 샌드박스에 배치하는 것이 좋다고 한다.

iOS 앱 개발자는 설치 시 시스템에서 자동으로 앱을 샌드박스에 넣기 때문에 명시적으로 앱을 샌드박스에 넣을 필요가 없다.
오늘은 iOS의 파일 시스템과 샌드박스에 대해 알아보았다.

하나의 큰 모래사장이 아니라 앱별 샌드박스를 통해 파일을 관리하는 것은 파일 시스템이 추구하는 사용자의 파일을 쉽게 검색할 수 있도록 하는 것에 최적화된 것 같았다.
또한 샌드박스 내부의 디렉터리 구분을 통해 다른 하나의 목표마저도 달성한 것 같다.
앱 내부에 파일을 저장할 일이 있다면 이러한 파일 시스템을 고려해보면 어떨까?