SwiftUI API 통신: 외부 라이브러리 없이 모듈화해보기

작성일 :

SwiftUI API 통신: 외부 라이브러리 없이 모듈화해보기

SwiftUI는 사용자 인터페이스를 작성하는 현대적인 방법을 제공하지만, 네트워크 요청을 처리하고 데이터를 관리하는 방법에 대한 별도의 라이브러리는 제공하지 않습니다. 하지만 Swift의 강력한 CodableURLSession을 활용하면 외부 라이브러리 없이도 네트워크 통신을 효과적으로 모듈화할 수 있습니다. 이 글에서는 그 구체적인 방법을 설명합니다.

1. 모델(Model) 정의하기

먼저, 네트워크 요청에서 받을 데이터를 표현할 모델을 정의합니다. Swift의 Codable 프로토콜을 사용하여 JSON 데이터를 손쉽게 변환할 수 있습니다.

swift
struct Post: Codable, Identifiable {
    let id: Int
    let title: String
    let body: String
}

위의 모델은 id, title, body라는 세 가지 속성을 가진 Post 구조체를 정의합니다.

2. 네트워크 레이어 만들기

다음으로, 네트워크 요청을 처리할 클래스를 만듭니다. 모듈화를 위해 이 클래스를 별도의 파일에 정의하는 것이 좋습니다. 여기서는 URLSession을 사용해 보겠습니다.

swift
import Foundation

class NetworkManager {
    static let shared = NetworkManager()
    private let baseURL = "https://jsonplaceholder.typicode.com"

    private init() {}

    func fetchPosts(completion: @escaping ([Post]?) -> Void) {
        guard let url = URL(string: "\(baseURL)/posts") else {
            completion(nil)
            return
        }

        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else {
                completion(nil)
                return
            }

            let posts = try? JSONDecoder().decode([Post].self, from: data)
            completion(posts)
        }

        task.resume()
    }
}

네트워크 매니저 클래스는 싱글톤 패턴을 사용하여 인스턴스를 관리합니다. fetchPosts 메서드는 네트워크 요청을 보내고, 결과를 디코딩한 후 완료 핸들러를 통해 반환합니다.

3. ViewModel 정의하기

네트워크에서 받아온 데이터를 SwiftUI에서 사용하려면 ViewModel을 정의해야 합니다. 이 ViewModel은 네트워크 매니저를 사용하여 데이터를 가져옵니다.

swift
import Combine

class PostViewModel: ObservableObject {
    @Published var posts = [Post]()
    private var cancellables = Set<AnyCancellable>()

    init() {
        fetchPosts()
    }

    func fetchPosts() {
        NetworkManager.shared.fetchPosts { [weak self] posts in
            guard let self = self else { return }
            DispatchQueue.main.async {
                self.posts = posts ?? []
            }
        }
    }
}

ViewModel 클래스는 ObservableObject를 채택하여 뷰와 데이터를 연결합니다. 네트워크 요청이 완료되면 UI가 업데이트됩니다.

4. SwiftUI View에서 ViewModel 사용하기

이제 최종적으로 SwiftUI View에서 ViewModel을 사용하여 데이터를 표시해 봅시다.

swift
import SwiftUI

struct ContentView: View {
    @StateObject private var viewModel = PostViewModel()

    var body: some View {
        NavigationView {
            List(viewModel.posts) { post in
                VStack(alignment: .leading) {
                    Text(post.title)
                        .font(.headline)
                    Text(post.body)
                        .font(.subheadline)
                }
            }
            .navigationTitle("Posts")
        }
        .onAppear {
            viewModel.fetchPosts()
        }
    }
}

ContentViewPostViewModel 인스턴스를 생성하고, List 뷰에서 포스트 데이터를 표시합니다. 네트워크 요청은 onAppear 이벤트에서 호출됩니다.

5. 결론

이 글에서는 SwiftUI에서 외부 라이브러리를 사용하지 않고 API 통신을 모듈화하는 방법을 다뤘습니다. 네트워크 매니저, ViewModel, 그리고 뷰를 분리하여 각 부분의 역할을 명확히 하고 유지보수가 용이하게 만들었습니다. Swift의 강력한 내장 기능을 활용하면 이러한 작업을 쉽게 수행할 수 있습니다.