🍎 iOS/iOS 심화 & 응용

[iOS/Swift] URLSession vs Alamofire

dev_zoe 2023. 7. 20. 23:11
반응형

iOS 앱을 만들 때 거의 필수적으로 네트워킹을 구현하는 경우가 많다.

URLSession, Alamofire 모두 사용해보았을 때 각각 원리가 어떻게 되고, 장단점이 어떻게 되는지 분석하여

현재 프로젝트 리팩토링이나 다음 프로젝트를 진행할 때 기술 선택 시 도움이 되고자 비교해보고자 한다.

 

URLSession vs Alamofire

URLSession은 애플 프레임워크에서 제공되는 가장 기본적인 방법이며, Alamofire/Moya는 서드파티 라이브러리이다.

Get과 Post 각 메소드에 대해 라이브러리 별 사용을 비교할 것임. (어차피 delete, put, patch는 모두 Post와 같이 body값을 보내주는 형태이기 때문에 생략)

 

먼저 URLSession, Alamofire를 비교해보자.

 

1) GET

 

URLSession

    func requestGetMethod(with urlString: String, completion: @escaping NetworkCompletionHandler) {

        // 1) urlString 
        guard let url = URL(string: urlString) else { return }

		// 2) 통신을 담당할 URLSession 생성
        let session = URLSession(configuration: .default)

		// 3) 통신 방식 정의
        let task = session.dataTask(with: url) { data, response, error in
            if error != nil {
                print(error!)
                completion(.failure(.networkingError))
                return
            }

            guard let data = data else {
                completion(.failure(.dataError))
                return
            }

			// response를 받아오는 데 성공했다면, 여기서 200번대 코드인지 한번 더 검증하여 성공적으로 불러온것인지 확인
            guard let response = response as? HTTPURLResponse, (200 ..< 299) ~= response.statusCode else {
                completion(.failure(.networkingError))
                return
            }
            
            // 여기까지 통과! 오류 없이 잘 받아옴!

            // 메서드 실행해서, 결과를 받음
            if let data = self.parseJSON(data) {
                print("Parse 실행")
                completion(.success(data))
            } else {
                print("Parse 실패")
                completion(.failure(.parseError))
            }
        }

        // 4) 통신 실행
        task.resume()
    }
    
    
     private func parseJSON(_ data: Data) -> GetResponse? {
        let decoded = try? JSONDecoder().decode(GetResponse.self, from: data)
        return decoded
    }

 

Alamofire

        AF.request(urlString)
            .validate()  //44번째 줄 라인처럼 200..<299 내에 statusCode가 있는지 확인해줌. 실패시 아래에서 error 전달
            .responseDecodable(of: GetResponse.self) { response in
                switch response.result {  // return 타입이 Result<Success, Failure>
                case .success(let data):
                    completion(.success(data))
                case .failure(let error):
                    print(error)
                    completion(.failure(.parseError))
                }
            }

 

2) POST

 

URLSession

    func postRequest(with urlString: String, postBody: UploadData, completion: @escaping (Result<Bool, NetworkError>) -> Void) {
        
        // 1. URLSession
        guard let url = URL(string: urlString) else {
            return
        }

        // 1-1)모델을 JSON data 형태로 변환 (encode)
        guard let jsonData = try? JSONEncoder().encode(postBody) else {
            return
        }

        // URL요청 생성
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type") // 헤더값 설정
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        request.httpBody = jsonData


        // 요청을 가지고 세션 작업시작
        URLSession.shared.dataTask(with: request) { data, response, error in
            // 에러가 없어야 넘어감
            guard error == nil else {
                print("Error: error calling POST")
                print(error!)
                return
            }
            // 옵셔널 바인딩
            guard data != nil else {
                print("Error: Did not receive data")
                return
            }
            // HTTP 200번대 정상코드인 경우만 다음 코드로 넘어감
            guard let response = response as? HTTPURLResponse, (200 ..< 299) ~= response.statusCode else {
                print("Error: HTTP request failed")
                return
            }
            
            completion(.success(true))
            // 여기서 response를 decode 해야한다면, get으로 api 호출할때와 동일한 절차로 디코딩하면 됨

        }.resume()   // 시작

 

Alamofire

        AF.request(urlString, method: .post, parameters: postBody)
            .validate()  // 200..<299 내에 statusCode가 있는지 확인해줌. 실패시 아래에서 error 전달
            .response { response in
                switch response.result {
                case .success(_):
                    completion(.success(true))
                case .failure(let error):
                    print(error)
                }
            }

 

코드가 눈에띄게 정말 많이 줄어든다.

 

1)URLSession을 기반으로 하되,

2) validate를 통해 data와 response.code까지 검증해주며

3) responseDecodable을 통해 decoding 해주고

4) struct를 json으로 encoding 해주며

5) 커스텀 헤더 외에는 헤더를 직접 넣을 필요가 없다.

 

추가적으로 Moya라는 라이브러리도 있는데, Alamofire를 한번 더 추상화한 라이브러리라서

이걸 직접 편리하게 추상화하는 작업도 해보면 좋을것같다.

 

❓ Moya 라이브러리

https://velog.io/@dlskawns96/iOS-Moya%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9-Swift-Http-%ED%86%B5%EC%8B%A0

 

[iOS] Moya를 사용한 네트워킹 (Swift Http 통신)

Moya를 사용한 네트워킹을 예제 프로젝트로 알아보겠습니다.

velog.io

 

 

 

반응형