[ios] FileManager 사용법! Data를 어떤 Directory에 저장해야 할까?

Oxong·2022년 3월 17일
0

iOS 개발 관련 모음

목록 보기
7/8

개발에 참고하려고 작성한 글이당 🙃🙃🙃🙃🙃
정리하지 않고 되는대로 쓸것이므로 참고하시면 안됩니당!
                                            ._. Oxong❣️






모든 ios 앱은 샌드박스(SandBox)라는 자신만의 공간을 갖는다.
샌드박스는 폐쇄적이어서 외부에서 함부로 침범할 수 없고, 다른 앱의 샌드박스도 침범할 수 없다.

App SandBox란?

커널 수준에서 강제 적용되는 맥 OS의 접근 제어 기술.
App이 손상될 경우, 시스템과 사용자 데이터의 손상을 억제하도록 설계되어있다.
App Store에서 유통되는 App들은 모두 App SandBox를 적용시켜야만 한다.
+ 애플 개발자 계정으로 App Store가 아닌 다른곳에서 유통된 App들 또한 App SandBox를 적용시켜야 한다. (

Apple 공식 문서 - About App SandBox

물론 유저의 허락 아래에 외부의 침범을 허용할 수도 있는데, 앱 최초 실행 시 물어보는 접근 권한에 대한 설정이 그것이다.

앱 개발자 앱을 개발하면서 앱에서 사용되는 데이터를 기기에 저장해야 할 필요가 생길 수 있다.
하지만 위에서 말했듯이 SandBox를 벗어날 수 없기 때문에 내부 특정 디렉터리에 저장해야 한다.



앱 개발자는 저장할 데이터의 보안 수준, 저장 목적에 따라서 데이터를 저장할 디렉토리를 정해야한다.

저장할 수 있는 디렉터리는 아래와 같다.
/Documents
/Library/Application Support
/Library/Caches
/tmp



🔹 Documents

유저가 생성한 파일, 다운로드한 파일같은 것을 저장해주는 디렉터리로 icloud 백업이 된다.

import 'package:path_provider/path_provider.dart' // 경로 path
Directory supportDirectory = await getApplicationDocumentsDirectory()

🔹 Application Support

이 디렉터리에는 앱 구동을 위해 반드시 필요하나, 유저에게 공개하고 싶지 않은 민감한 데이터를 저장할 때 사용면 좋다.
예를 들어 어플을 구동하기 위해 필요한 데이터들. 즉, 어플을 사용하는 유저에 대한 정보, 앱 설정 데이터가 저장될 수 있다.

import 'package:path_provider/path_provider.dart' // 경로 path
Directory supportDirectory = await getApplicationSupportDirectory()

🔹 tmp

Tmp 디렉터리에는 임시 데이터가 저장되므로, 잠깐 쓰고 버릴 데이터들을 이곳에 저장해서 활용한다.
삭제되어도 큰 문제가 없는 데이터들이 주로 저장되며 OS 혹은 유저가 비울 수 있다.

경로는 path_provider 패키지가 아닌, io 패키지를 사용하면 얻을 수 있다.

import 'dart:io';
Directory tmpDirectory = Directory.systemTemp;



FileManager ?


위에서 말했듯이, ios는 앱마다 자기만의 공간을 가지고 있다. FileManager는 이 공간을 관리하는 매니저라 생각하면 된다.

foundation framework에 들어있으며, 데이터를 저장하거나 찾는 것에 사용된다.


경로 접근

사용하기 위해 FileManager인스턴스를 생성해한다.
default는 FileManager의 싱글톤 인스턴스를 만들어 준다.

let fileManager = FileManager.default


let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

  • urls 메소드 : 요청된 도메인에서 지정된 공통 디렉토리에 대한 URL배열을 리턴해주는 메소드.

  • 첫번째 파라미터 : 검색 경로 (폴더를 정해주는 요소)

  • 두번째 파라미터 : Domain을 나타내는 파라미터로, 제한을 걸어주는 요소이다.


이 아래부터는 Swift - FileManager 글을 참고했다.

글도 잘 쓰시고, 정리도 잘 되어있어 이해가 쉬웠다 😀👍



파일 추가

// 1. 인스턴스 생성 - 동일
let fileManager = FileManager.default

// 2. 도큐먼트 URL 가져오기 - 동일
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

// 3. 파일 저장할 Directory 설정
let directoryURL = documentsURL.appendingPathComponent("NewDirectory")

// 4. File 이름 설정
let fileURL = directoryURL.appendingPathComponent("test.txt")

// 5. File 내용
let text = NSString(string: "Hello world")

do {
    // 6-1. 파일 생성
    try text.write(to: fileURL, atomically: true, encoding: String.Encoding.utf8.rawValue)
} catch let e {
    // 6-2. 오류 처리
    print(e.localizedDescription)
}

폴더 추가

// 1. 인스턴스 생성
let fileManager = FileManager.default
// 2. 도큐먼트 URL 가져오기
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
// 3. 생성할 폴더 이름 추가해주기
let directoryURL = documentsURL.appendingPathComponent("NewDirectory")
// 4. 생성하기
do {
    try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: false, attributes: nil)
} catch let e {
    print(e.localizedDescription)
}

불러오기

// 1. 인스턴스 생성 - 동일
let fileManager = FileManager.default

// 2. 도큐먼트 URL 가져오기 - 동일
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

// 3. 파일이 있는 Directory 설정
let directoryURL = documentsURL.appendingPathComponent("NewDirectory")

// 4. 불러올 파일 설정
let helloPath = directoryURL.appendingPathComponent("test.txt")

// Try Catch
do {
    // 5-1. 불러오기
    let text = try String(contentsOf: helloPath, encoding: .utf8)
    print(text) // Hello world
} catch let e {
    // 5-2. 에러처리
    print(e.localizedDescription)
}

파일 삭제

// 1. 인스턴스 생성 - 동일
let fileManager = FileManager.default

// 2. 도큐먼트 URL 가져오기 - 동일
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

// 3. 파일이 있는 Directory 설정
let directoryURL = documentsURL.appendingPathComponent("NewDirectory")

// 4. 삭제할 파일 설정
let helloPath = directoryURL.appendingPathComponent("test.txt")

// Try Catch
do {
    // 5-1. 삭제하기
    try fileManager.removeItem(at: fileURL)
} catch let e {
    // 5-2. 에러처리
    print(e.localizedDescription)
}

### 파일 존재 여부 검사

let fileManager = FileManager.default
 
guard ( fileManager.fileExists( atPath: path )==true ) else {
  retrun
}




Reference

IOS 앱 개발 시에 로컬 데이터는 어떤 디렉터리에 저장해야 할까? | Flutter

Apple 공식 문서 - About App SandBox

iOS ) FileManager를 이용해 파일/폴더 만드는 법

Swift - FileManager

0개의 댓글