[RxSwift] - Generic 을 활용한 리펙터링

Shawn·2022년 4월 21일
0

RxSwift

목록 보기
8/8

지난 포스트에서 Generic을 활용하여 코드를 단축하는 방법에 대해 연구해보았다.
그렇다면 이번엔 정말로 긴, 긴 코드를 줄여보자. 단순히 Decode정도가 아닌.

Problem

"피플"은 Single, Observable을 정말 많이 리턴한다.

코드를 살펴보자

    func fetchFive() -> Single<[CalendarModel]> {

        
        return Single.create() { observable in
            
            
            let urlString = "\(self.baseUrl)/api/v1/account/calendar/after/test?minusDay=5&accountUuid=\(UserDatabaseManager.shared.myUserModel!.uuid)"
            
            guard let url = URL(string: urlString) else {
                observable(.error(DatabaseFetchingErrorType.urlFailedError))
                return Disposables.create()
            }
            
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            request.setValue(UserDatabaseManager.shared.jwtToken, forHTTPHeaderField: "X-AUTH-TOKEN")
            request.timeoutInterval = 10

            AF.request(request).responseData { response in
                switch response.result {
                case .success(let data):
                    if let calendarModelArray = self.decode(jsonData: data, type: [CalendarModel].self) {
                        observable(.success(calendarModelArray))
                        print("[Calendar 5] fetching 성공")
                    } else {
                        observable(.success([]))
                    }

                case .failure(let err):
                    print("🚫[Calendar 5] 에러 \(err)")
                    observable(.error(DatabaseFetchingErrorType.fetchingFailedError))
                }
            }
            
            return Disposables.create()
        }
    }

Calendar Manager의 fetchFive라는 함수이다.
최근 5개의 CalendarModel을 리턴한다. Single 로 리턴한다.

다른 코드들 또한 이러한 형식을 많이 따른다.
request에 필요한 파라미터를 담고, 리퀘스트를 디코딩해서 결과를 얻어 Bind한다.

그런데, 벌써 코드가 30~40줄 정도가 되는 것 같다.

이러한 함수가 20 ~ 30개가 되니 코드의 양은 너무 방대해져버렸다.

Param과 Path를 인자로 받아 원하는 타입의 Single을 리턴하는 함수를 만들어보자.

func single<T: Codable>(path: String, type: T.Type, params: [String: Any]?) -> Single<T>

선언은 이렇게한다.
path 와 type, 그리고 파라미터는 없을 수도 있으니까 옵셔널로 받는다.

            var queryParams = ""
            if let params = params {
                queryParams = params.map { k, v in "\(k)=\(v)" }.joined(separator: "&")
            }

            var fullPath = path.hasPrefix("http") ? path : self.baseUrl + path
            if queryParams.count > 0 {
                fullPath += "?" + queryParams
            }

파라미터에대한 처리는 위처럼 해준다.

&로 key=value를 묶어 마지막에 path 뒤에 ? 를 붙여 fullPath를 완성한다.

            var request = URLRequest(url: url)
            request.httpMethod = "GET"
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            request.setValue(UserDatabaseManager.shared.jwtToken, forHTTPHeaderField: "X-AUTH-TOKEN")
            request.timeoutInterval = 10
            
            AF.request(request).responseData { response in
                switch response.result {
                case .success(let data):
                    if let returnData = self.decode(jsonData: data, type: type.self) {
                        observable(.success(returnData))
                        print("[\(type)] fetching 성공")
                        
                    } else {
                        observable(.error(DatabaseFetchingErrorType.encodingFailedError))
                    }
                    
                case .failure(let err):
                    print("🚫[\(type)] 에러 \(err)")
                    observable(.error(DatabaseFetchingErrorType.fetchingFailedError))
                }
            }
            return Disposables.create()

그리고 나서는 똑같이 함수를 적어 리턴해주면 제네릭 함수가 완성된다.

결론

    func fetchFive() -> Single<[CalendarModel]> {
        return single(path: fivePath, type: [CalendarModel].self, params: ["accountUuid": UserDatabaseManager.shared.myUserModel!.uuid])
    }

세 줄로 줄었다.

하지만 지금당장은 Single 만 사용을 해보았고, 다른 복잡한 형태의 제네릭 함수구현을 위해서는 조금 더 공부를 해보아야겠다.

profile
iOS 개발, Flutter 개발, Swift, Dart, 42 Seoul 3기

0개의 댓글