Skip to content

Conversation

@513sojin
Copy link
Collaborator

@513sojin 513sojin commented Dec 5, 2023

🌱 작업한 내용

  • 네트워크 함수 리팩토링해보았습니다 (개인적인 버킷리스트 😇)
  • 피드백이나 질문 받고 코스 그리기 부분(제가 현재 작업하는 뷰)부터 추가된 함수로 변경해보려고 합니다 !
  • 급한 부분은 아니니 시간 남을때 ⭐️⭐️천~~~천히⭐️⭐️ 읽어주시면 감사하겠습니다!

사용 방법

현재는 Proveiders를 타입 프로퍼티로 선언하여 사용해주고 있는데

struct Providers {
  static let departureSearchingProvider = MoyaProvider<DepartureSearchingRouter>(withAuth: false)
  static let authProvider = MoyaProvider<AuthRouter>(withAuth: true)
등    등 등 
}

제가 만든 NetworkProvider 내부에서 MoyaProvider의 request 함수를 호출하고 있으므로, 아래와 같이 선언해주면 됩니다

private let networkProvider = NetworkProvider<DepartureSearchingRouter>(withAuth: false)

그 후 TargetType 프로토콜을 채택하는 provider(우리 플젝에서는 Router 친구들)의 case와 (ex .getLocationTmapAddress )
decoding을 위한 dto, viewController를 전달해주면 됩니다.

아래 코드는 같은 서버 통신 로직인데 사용 전과 후의 코드입니다

사용 전

private func searchLocationTmapAddress(latitude: Double, longitude: Double) {
        departureSearchingProvider
            .request(.getLocationTmapAddress(latitude: latitude, longitude: longitude)) { [weak self] response in
                guard let self = self else { return }
                switch response {
                case .success(let result):
                    let status = result.statusCode
                    if 200..<300 ~= status {
                        do {
                            let responseDto = try result.map(TmapAddressSearchingResponseDto.self)
                            self.updateData(model: responseDto.toDepartureLocationModel(latitude: latitude, longitude: longitude))
                        } catch {
                            print(error.localizedDescription)
                        }
                    }
                    if status >= 400 {
                        print("400 error")
                    }
                case .failure(let error):
                    print(error.localizedDescription)
                    self.showToast(message: "네트워크 통신 실패")
                }
            }
    }

사용 후

private func searchTest(latitude: Double, longitude: Double) {
        networkProvider.request(target: .getLocationTmapAddress(latitude: latitude, longitude: longitude), instance: TmapAddressSearchingResponseDto.self, vc: self) { result in
            switch result {
            case .success(let data):
                self.updateData(model: data.toDepartureLocationModel(latitude: latitude, longitude: longitude))
            }
        }
    }

코드 설명

응답 코드를 체크하는 부분 (200~300 사이인 경우 / 400이면 에러로 분기) 
디코딩 하는 부분
서버 통신에 아예 실패한 경우 toast를 띄우는 부분

위의 부분이 api 연결하는 함수마다 써있는걸 발견했고,
서버 통신에 성공해서 데이터를 활용하는 부분에만 차이가 있음을 확인했습니다.

그래서 위의 중복되는 부분들을 하나로 묶어주는 함수를 작성했고,
기존 MoyaProvider의 request 함수는 아래의 리턴 타입을 escaping으로 전달해주는데

public typealias Completion = (_ result: Result<Moya.Response, MoyaError>) -> Void

error에 대한 분기처리가 api 함수마다 동일하므로, error 분기처리는 제가 작성한 request 함수에서 진행하고
아래의 리턴타입(ResponseResult)을 새롭게 만들어주었습니다.
그래서 서버 통신에 성공한 경우만 실제 뷰컨에서 처리하도록 ‼️‼️‼️‼️

enum ResponseResult<T> {
    case success(T)
}

아래는 핵심이 되는 함수입니다

class NetworkProvider<Provider : TargetType> : MoyaProvider<Provider> {
    func request<Model : Codable>(target : Provider, instance : Model.Type , vc: UIViewController, completion : @escaping(ResponseResult<Model>) -> ()){
        self.request(target) { result in
            switch result {
            /// 서버 통신 성공
            case .success(let response):
                if (200..<300).contains(response.statusCode) {
                    if let decodeData = try? JSONDecoder().decode(instance, from: response.data) {
                        completion(.success(decodeData))
                    } else{
                        /// decoding error
                        vc.showNetworkFailureToast()
                    }
                } else {
                    /// 응답 코드 400인 경우
                    vc.showNetworkFailureToast()
                }
            /// 서버 통신 실패
            case .failure(let error):
                if let response = error.response {
                    if let responseData = String(data: response.data, encoding: .utf8) {
                        print(responseData)
                    } else {
                        print(error.localizedDescription)
                    }
                } else {
                    print(error.localizedDescription)
                }
                vc.showNetworkFailureToast()
            }
        }
    }
}

viewController를 매개변수로 전달해주는 이유는,
서버 통신 실패시 토스트 메세지를 띄워줘야하는데 이때 해당 뷰컨에 대한 정보가 있어야 뷰를 붙여줄 수 있기 때문입니다

그리고 서버 연결에 실패한 경우 에러메세지를 출력해주는 코드가 필요함을 느껴서 이 부분도 추가해주었습니다 !

궁금한 점, 수정되었으면 하는 부분 자유롭게 리뷰 남겨주시면 감사하겠습니다. 꾸벅 꾸벅

📮 관련 이슈

@513sojin 513sojin requested a review from thingineeer December 5, 2023 16:08
@513sojin 513sojin self-assigned this Dec 5, 2023
@513sojin 513sojin added the Refactor 전면 수정 label Dec 5, 2023
@thingineeer thingineeer changed the title [Refactor] #207 서버 통신 함수 리팩토링 [Refactor] #207 - 서버 통신 함수 리팩토링 Dec 9, 2023
Copy link
Collaborator

@thingineeer thingineeer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

재사용 굿굿

Comment on lines +503 to 511
private func searchTest(latitude: Double, longitude: Double) {
networkProvider.request(target: .getLocationTmapAddress(latitude: latitude, longitude: longitude), instance: TmapAddressSearchingResponseDto.self, vc: self) { result in
switch result {
case .success(let data):
self.updateData(model: data.toDepartureLocationModel(latitude: latitude, longitude: longitude))
}
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확실하게 짧아지긴 했네요,
꽤 꼼꼼하게 봤는데도, 고칠 부분은 찾지 못했습니다.
따로 NetworkProvider 클래스를 재사용하여 중복되는 코드들을 없애는 거는 초창기에 언급했던 거 같은데, 대부분 작업 끝나면 모두 바꿔봅시다~

@513sojin 513sojin merged commit 17bd5f9 into Runnect:develop Dec 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] #207 - 서버 통신 함수 리팩토링

2 participants