기존에 사용하던 방식

struct NetworkConstant {
    static let noTokenHeader = ["Content-Type": "application/json"]
    static let hasTokenHeader = [
        "Content-Type": "application/json",
        "Authorization": "Bearer \\(KeychainService.readKeychain(of: .access))"
    ]
    static let platformTokenHeader = [
		    "Content-Type": "application/json",
		    "Platform-token": KeychainService.readKeychain(of: .socialAuth)
		]
}

원래는 header 를 넣을 때 그냥 Keychain 에서 읽은 값을 static 으로 선언해 둔 변수에 할당했었다

하지만 static 때문에 처음 Keychain 에서 읽어온 값으로 platformTokenHeader 가 결정될거고, 소셜로그인을 했다가 뒤로가기를 하고 다시 로그인을 하게 되면 기존에 받아왔던 authToken 값으로 header 통신을 하기 때문에 오류가 발생했다

그러면 어떻게 해야 하나 !

headeraccessToken 이나 refreshToken 을 넣기 위해 Alamofire 에서 제공하는 RequestInterceptor 라는게 있다 ! (Moya 는 Alamofire 를 wrapping 하기 때문에 Moya 에서도 사용 가능)

Untitled

adapt() 함수는 request 를 보내기 전 중간에 intercept 하여 추가적인 작업을 할 수 있게 하고

func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
    guard urlRequest.url?.absoluteString.hasPrefix(Config.baseURL) == true
    else { return }
    
    var request = urlRequest
    request.setValue(KeychainService.readKeychain(of: .socialAuth), forHTTPHeaderField: "Platform-token")
    completion(.success(request))
}
  1. 지금 서버에 보내는 request 인지 확인하고
  2. request 에 추가적인 작업을 한 뒤
  3. completion 을 통해 전달한다

이렇게 하게 되면 위에 적어둔 상황처럼 왔다갔다 해도 상관 없게 된다 !

최종적으로는 대부분의 API 에다가 accessTokenrefreshToken 값들도 header 에 추가해두도록 해야 할 듯 !

retry() 함수는 response 를 받은 후 중간에 intercept 하여 추가적인 작업을 할 수 있게 한다

func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
        
    guard request.response?.statusCode == 401
    else {
        completion(.retry)
        return
    }
    isAvailable = false
    
    AuthAPI.shared.getTokenRefresh { response in
        guard let response = response else { return }
        switch response.code {
        case 200:
            guard !self.isAvailable else { return }
            completion(.retry)
        default:
            Utils.sceneDelegate?.changeRootViewControllerToOnboardingViewController()
            print("❌ 토큰이 만료되었습니다 ❌")
        }
    }
}

현재 이렇게 구현해두었는데, 여기서 문제점.

HomeVC 에서는 한 번에 여러개의 API 가 호출되는데, 유효하지 않은 AT 를 갖고 있는 경우, 동시에 호출되는 API 에서 모두 401 에러가 뜨고, 위와 같은 retry 코드에서, 다 guard 문을 지나간다..

이게 문제가 되는 이유는, getTokenRefresh 라는 API 가 호출 됐을 때, ATRT 를 전달하는데, 유효한 AT 를 해당 API 에 전달하면, 200이 오지 않고 401 에러가 뜬다

즉, AT 가 유효한지 확인하는 API 가 있어야 하거나, 유효한 AT 를 보냈을 때의 에러 코드를 401 말고 다른걸로 해야한다

이거에 대한 해결 방법은…. 언젠가….