firestore 요청을 하기 위해서 루트 collection의 하위 도큐먼트의 이름을 거쳐야 한다. 이 도큐먼트는 Auth.auth().currentUser?.uid로 저장한다.

대안 1. 모든 repository에서 Auth.auth().currentUser?.uid 사용

이 방식은 모든 repository에서 Auth.auth().currentUser?.uid를 사용해서 직접 uid를 가져오는 것이 편할지라도, import FirebaseAuth를 해야하기 때문에 부담이 될 수 있다.

대안 2. UserRepository를 생성

UserRepository가 getUserID메소드를 정의하는 방식이다. 이는 모든 repository에서 import FirebaseAuth를 하지 않아도 되지만, 반대로 모든 UseCase가 UserRepository를 사용해야 하는 부담이 존재한다.

대안 3. ViewModel에서 id를 담당하는 User객체를 들고 있는 형태

viewModel에서 userID를 들고 있기 때문에 위에서 언급했던 두 가지의 문제를 해결할 수 있다. 다만, 화면 전환 시, User를 전달해야 한다.

대안 4. id를 담당하는 Manager 객체를 정의하고 싱글톤 설정

repository에서 idManager객체를 사용해서 uid를 받아오는 방식이다. 해당 방식은 Manager 객체 파일에서만 import FirebaseAuth를 하면 되기 때문에 대안 1을 해결할 수 있고, 싱글톤으로 접근하기 때문에 모든 repository에서 쉽게 접근할 수 있다. 하지만 repository뿐만 아니라, 모든 객체가 쉽게 접근할 수 있는 문제가 있다.

모든 객체에서 접근할 수 있는 문제가 있지만, 대안 123을 해결할 수 있기 때문에 대안 4를 채택했다.

class FirebaseUserManager {
  static let shared = FirebaseUserManager()
  
  var userID: String? {
    Auth.auth().currentUser?.uid
  }
  
  var isAuthenticated: Bool {
    Auth.auth().currentUser != nil
  }
}

// in DateTimeRepository

func saveDateTime(date: Int, hour: Int, minute: Int) -> AnyPublisher<Void, any Error> {
    guard let userID = FirebaseUserManager.shared.userID
    else { return Fail(error: FirestoreServiceError.noUser).eraseToAnyPublisher() }
    
    let requestDTO = AlarmDTO(date: date, hour: hour, minute: minute)
    return service.setDocument(
      documentPath: FirestorePath.userID(userID: userID),
      requestDTO: requestDTO,
      merge: true
    )
  }