[iOS] AppGroup을 켜면 어디까지 공유가 될까? - 1

유인호·2024년 5월 21일
1

iOS

목록 보기
48/64

0. 서론

watchOS라던가, Widget같은 녀석들은 iOS 어플이 있어야만 만들 수 있도록 의존이 되어있고 (워치는 단독이 되긴 하지만), 사람들은 설치할땐 똑같은 앱을 설치한 것 처럼 보이지만, 실상은 그렇지 않다.

Xcode에서는 사실상 다른 앱 취급을 받기 때문에 각각 다른 Sandbox을 가지게 된다. 그러나, Xcode에서 AppGroup 옵션을 켜주어 서로 데이터를 공유할 수 있게 되는데, 이게 어디까지 공유가 되는건지, 어떤 원리로 공유가 되는건지 궁금해서 한번 실험해보았음.

1. 조건

App SandBox System에서 공유할만한건 Realm이나 SwiftData 같은 데이터나 UserDefaults, 사진같은걸 저장시킬 수 있다.

실험 구성은 다음과 같다.

  1. AppGroup을 켜지 않은채로 데이터를 저장시킨다.
  2. Appgroup을 키면 데이터가 남아있는지 확인한다.
  3. watchOS앱을 만들어 공유해본다.
  4. 아에 다른 프로젝트에 iOS앱을 만들어 데이터를 공유해본다.

2. AppGroup을 켜지 않은채로 데이터를 저장시킨다.

일단 데이터는 총 3개로 잡았다.

  • SwiftData
  • UserDefatuls
  • 사진 저장

대충 간단하게 코드를 구현해보았다.

struct ContentView: View {
	@Query var test: [TestModel]
	@Environment (\.modelContext) var modelContext
	@State private var show = false
	@State private var image: UIImage?
    var body: some View {
        VStack {
			  Text(test.first?.content ?? "no data")
			  Text(UserDefaults.standard.string(forKey: "test") ?? "no user")

			  if let saveImage = loadImageFromDirectory() {
				  Image(uiImage: saveImage)
					  .resizable()
					  .frame(width: 100, height: 100)
			  }

			  Button("저장임") {
				  modelContext.insert(TestModel(content: "Test"))
				  try? modelContext.save()
				  UserDefaults.standard.setValue("Test", forKey: "test")
				  if let image {
					  saveImageToDirectory(image: image)
				  }
			  }

			  Button("image") {
				  show.toggle()
			  }
			  .sheet(isPresented: $show, content: {
				  ImagePicker(image: $image)
			  })
        }
        .padding()
    }

	func saveImageToDirectory(image: UIImage) {
		 let documentsDirectory = FileManager.default.urls(for: .documentDirectory,in: .userDomainMask).first!
		 let imageName = "test"
		 // 이미지의 경로 및 확장자 형식 (conformingTo: 확장자)
		 let fileURL = documentsDirectory.appendingPathComponent(imageName, conformingTo: .jpeg)

		 // Directory 경로라고 했죠? 파일이 저장된 위치를 확인하고 싶을 때, 단순히 경로를 프린트해서 확인이 가능합니다.
		 print(fileURL)

		 do {
			  // 파일로 저장하기 위해선 data 타입으로 변환이 필요합니다. (JPEG은 압축을 해주므로 크기가 줄어듭니다. PNG는 비손실)
			  if let imageData = image.jpegData(compressionQuality: 1) {
					// 이미지 데이터를 fileURL의 경로에 저장시킵니다.
					try imageData.write(to: fileURL)
					print("Image saved at: \(fileURL)")
			  }

		 } catch {
			  print("Failed to save images: \(error)")
		 }
	}

	func loadImageFromDirectory() -> UIImage? {
		 let fileManager = FileManager.default
		 // 파일 경로로 접근
		 let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
		 let fileURL = documentsDirectory.appendingPathComponent("test", conformingTo: .jpeg)

		 // 이미지 파일이 존재한다면, 이미지로 변환 후 리턴
		 guard fileManager.fileExists(atPath: fileURL.path) else { return nil }

		 return UIImage(contentsOfFile: fileURL.path)
	}
}

일단 데이터 저장

사진도 정상적으로 잘 들어와 있는걸 알 수 있다.

3. Appgroup을 키면 데이터가 남아있는지 확인한다.

AppGroup을 켜면 App SandBox가 이동할까? 라는 의문에서 시작된 실험 내용이다.

일단 데이터가 살아있다.

이미지를 바꾸면? 이전에 저장되어 있던 곳에 덮어 씌워지게 될까? 아니면 아에 새로 생겨버릴까?

그 자리에서 이미지가 바뀌는걸 볼 수 있다.

4. watchOS앱을 만들어 공유해본다.

아무것도 공유되지 않았다.

CloudKit같이 원격으로 데이터를 저장하지 않는 이상 데이터가 공유되기는 어려운 것 같다.

5. 아에 다른 프로젝트에 iOS앱을 만들어 데이터를 공유해본다.

실험결과 SwiftData는 공유가 되었지만 UserDefaults, 사진은 공유가 되질 않았다.

6. 실험결과

App Group을 켜준다고 같은 Sandbox를 공유하는게 아니라는걸 알 수 있었다.

다음 포스팅은 같은 Sandbox가 아님에도 SwiftData는 왜 다른 iOS 프로젝트와 데이터를 공유할 수 있었는지, 저장 방식에 어떤 차이가 있는지 알아보는 포스팅이 될 것 같다.


후속편: [iOS] AppGroup을 켜면 어디까지 공유가 될까? - 2

profile
🍎Apple Developer Academy @ POSTECH 2nd, 🌱SeSAC iOS 4th

0개의 댓글