Swift를 이용한 효율적인 네트워크 레이어 설계: URLSession과 Codable을 이용한 API 통신 방법.

작성일 :

Swift를 이용한 효율적인 네트워크 레이어 설계: URLSession과 Codable을 이용한 API 통신 방법

네트워크 요청은 현대 애플리케이션 개발에서 필수 요소입니다. Swift를 사용하여 iOS 애플리케이션을 개발할 때, 네트워크 레이어를 효율적으로 설계하는 것이 중요합니다. 이 글에서는 URLSessionCodable을 활용하여 네트워크 요청 및 응답을 효율적으로 처리하는 방법에 대해 다루겠습니다.

URLSession이란?

URLSession은 HTTP 또는 HTTPS를 통해 데이터를 송수신할 수 있게 하는 iOS 및 macOS의 기본 프레임워크입니다. 이 프레임워크는 간단한 네트워크 요청부터 파일 다운로드, 업로드 등 다양한 작업을 지원합니다.

URLSession의 기본 구성

URLSession은 세 부분으로 구성됩니다:

  1. URLSessionConfiguration: 세션의 모든 설정이 저장되는 객체입니다. 기본 설정, 불릴 수 없는 설정, 백그라운드 설정 등 여러 가지 설정을 잡을 수 있습니다.
  2. URLSession: 네트워크 요청을 조정하고 실행합니다. 이를 통해 데이터 작업, 다운로드 작업, 그리고 업로드 작업을 관리합니다.
  3. URLSessionTask: 개별 네트워크 요청을 나타내는 객체입니다. 이를 통해 작업을 시작, 일시 중지, 취소할 수 있습니다.

기본 예제

swift
import Foundation

let url = URL(string: "https://api.example.com/data")!
var request = URLRequest(url: url)
request.httpMethod = "GET"

let session = URLSession.shared

let task = session.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }

    guard let data = data else {
        print("No data received.")
        return
    }

    // JSON 데이터 처리
    do {
        let json = try JSONSerialization.jsonObject(with: data, options: [])
        print("Response JSON: \(json)")
    } catch {
        print("Error parsing JSON: \(error)")
    }
}

task.resume()

위의 예제에서 우리는 기본 URLSession을 사용하여 네트워크 요청을 보내고 JSON 데이터를 처리합니다. 이제 이를 바탕으로 코드를 더 단순하고 효율적으로 만들기 위해 Codable과 커스텀 네트워크 레이어를 사용해보겠습니다.

Codable을 이용한 데이터 모델링

Codable 프로토콜은 Swift에서 JSON 데이터와 객체 간의 변환을 쉽게 하기 위해 도입되었습니다. 이 프로토콜을 사용하면 JSON 파싱 코드가 크게 간소화됩니다.

Codable 예제

swift
struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

// JSON 데이터
let jsonData = "{"id": 1, "name": "John Doe", "email": "john.doe@example.com"}".data(using: .utf8)!

// JSON 파싱
let user = try? JSONDecoder().decode(User.self, from: jsonData)
if let user = user {
    print("User: \(user)")
}

위의 예제를 통해 JSON 데이터를 파싱하여 User 객체로 만들 수 있습니다. 이를 바탕으로, URLSession을 사용하여 네트워크 서비스를 구성해보겠습니다.

네트워크 서비스 레이어 구현

네트워크 서비스 레이어를 구현하면, 코드의 재사용성과 유지보수성을 높일 수 있습니다. 다음은 이를 구현하는 방법입니다.

네트워크 서비스 클래스

swift
import Foundation

class NetworkService {
    static let shared = NetworkService()
    private init() {}

    private let baseURL = "https://api.example.com"

    private var defaultSession: URLSession {
        let configuration = URLSessionConfiguration.default
        return URLSession(configuration: configuration)
    }

    func fetchData<T: Codable>(endpoint: String, completion: @escaping (Result<T, Error>) -> Void) {
        guard let url = URL(string: "\(baseURL)\(endpoint)") else {
            completion(.failure(NSError(domain: "Invalid URL", code: 0, userInfo: nil)))
            return
        }

        let request = URLRequest(url: url)

        let task = defaultSession.dataTask(with: request) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }

            guard let data = data else {
                completion(.failure(NSError(domain: "No data", code: 0, userInfo: nil)))
                return
            }

            do {
                let decodedData = try JSONDecoder().decode(T.self, from: data)
                completion(.success(decodedData))
            } catch {
                completion(.failure(error))
            }
        }

        task.resume()
    }
}

위의 NetworkService 클래스는 단일 인스턴스를 제공하는 싱글톤 패턴을 사용하며, 제네릭을 활용하여 다양한 엔드포인트와 데이터 타입을 처리할 수 있습니다. 이를 통해 다양한 API 호출을 손쉽게 관리할 수 있습니다.

사용 예제

swift
NetworkService.shared.fetchData(endpoint: "/users/1") { (result: Result<User, Error>) in
    switch result {
    case .success(let user):
        print("User: \(user)")
    case .failure(let error):
        print("Error: \(error.localizedDescription)")
    }
}

위의 예제에서는 fetchData 메소드를 사용하여 사용자 데이터를 가져오는 방법을 보여줍니다. 이는 간단한 예제이지만, 이 접근 방식을 통해 여러 종류의 네트워크 요청을 효율적으로 처리할 수 있습니다.

결론

Swift에서 URLSessionCodable을 활용하여 네트워크 레이어를 설계하는 방법을 알아보았습니다. 이러한 접근 방식을 통해 코드의 가독성과 유지보수성을 높이고, 다양한 네트워크 요청을 효율적으로 관리할 수 있습니다. 앞으로도 계속해서 이러한 Best Practice를 적용하여 더 나은 애플리케이션을 개발해보세요.