GitHub - minnnidev/Wote at refactoring
refactor/#5
브랜치에서 삽질을 확인 가능!
<오늘의 목차>
1. Apple Login → 서버에 authoriazation code 포함하여 request → 토큰 받기까지는 완료 (아키텍처 구조 설계는 너무 어렵다!)
2. Clean Architecture에서 Error Handling은 어떻게 해야 할까?
swinject로 필요한 객체를 register하기
final class AuthAssembly: Assembly {
func assemble(container: Container) {
container.register(LoginViewModel.self) { res in
LoginViewModel(authUseCase: res.resolve(AuthUseCaseType.self)!)
}
container.register(AuthUseCaseType.self) { res in
AuthUseCase(authRepository: res.resolve(AuthRepositoryType.self)!)
}
container.register(AuthRepositoryType.self) { _ in AuthRepository() }
}
}
case let .appleLoginHandler(result):
switch result {
case let .success(authorization):
authUseCase.loginWithApple(authorization)
.sink { completion in
print(completion)
} receiveValue: { _ in
print("헿")
}
.store(in: &cancellables)
case let .failure(error):
print(error.localizedDescription)
}
func loginWithApple(_ authorization: ASAuthorization) -> AnyPublisher<Void, CustomError> {
let code = getCredential(authorization)
return authRepository.loginWithApple(code)
.map { _ in }
.eraseToAnyPublisher()
}
extension AuthUseCase {
func getCredential(_ authorization: ASAuthorization) -> String {
guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return "" }
guard let authorizationCode = credential.authorizationCode else { return "" }
guard let authoriazationCodeString = String(data: authorizationCode, encoding: .utf8) else { return "" }
return authoriazationCodeString
}
}
// SwiftUI에서 Preview와 테스트를 위해 StubUseCase도 만들어 줬고, 내용은 추가 필요....
final class StubAuthUseCase: AuthUseCaseType {
func loginWithApple(_ authorization: ASAuthorization) -> AnyPublisher<Void, CustomError> {
Empty()
.eraseToAnyPublisher()
}
}
final class AuthRepository: AuthRepositoryType {
private let provider = MoyaProvider<AuthAPI>()
func loginWithApple(_ authorizationCode: String) -> AnyPublisher<Tokens, CustomError> {
let object: AppleUserRequestObject = .init(code: authorizationCode, state: "APPLE")
return provider.requestPublisher(.loginWithApple(object))
.tryMap { try JSONDecoder().decode(GeneralResponse<AppleUserResponseObject>.self, from: $0.data) }
.compactMap { $0.data }
.map { $0.jwtToken }
.map { $0.toToken() }
.mapError { CustomError.error($0) }
.eraseToAnyPublisher()
}
}
아니 아쉬운 점만 길고 좋았던 점이 없는데요…
처음 든 생각은 당연히 Repository에서는 NetworkError를 처리해 준다.
Domain 계층에서는 따로 DomainError(가제?)을 정의해 준다. (유저가 마주하는 가장 직접적인 에러. 개발적으로는 표현하면 안 되지 않을까?)
이 과정을 계속해서 고민하고, 많은 포스팅을 읽어보고 있는데 아직 해결 방법을 생각해 보는 중이다.
자동로그인, 토큰 갱신 등등 할일이 산더미지만...
클린 아키텍처... 무습고도 재밋는 넘이다
고민하다가 머리 빠질 거 같다.