👨‍🎓
Today I Learned
  • Today-I-Learend
  • 🍎WWDC
    • Developer Tools
      • Testing in Xcode
    • UIKit
      • UIDiffableDataSource
        • [WWDC 19] Advances in UI Data Sources
      • [WWDC2019] Advances in CollectionView Layout
  • 자료구조
    • Heap 자료구조
  • Clean code
    • 네이밍
    • 주석과 포맷팅
    • 함수
    • 클래스
    • 에러 핸들링
    • 가독성 높이기
    • 객체지향
  • Network
    • RestAPI
  • Swift
    • DateType
    • ARC
    • Availablity
    • KeyPath
    • Network
    • Never타입
    • Result
    • Selector
    • 검증함수
    • 메타타입
    • 동시성 프로그래밍
    • 메모리 안전
    • 에러처리
    • 접근제어 (Access Control)
    • 제네릭
    • 주요 프로토콜
  • 알고리즘
    • 그래프
    • 기초 알고리즘
    • 누적합(Prefix)
    • 복잡도
    • 비트마스킹
  • 운영체제
    • 운영체제의 개요
    • 프로세스와 스레드
    • CPU 스케줄링
    • 프로세스 동기화
    • 교착상태
    • 07. 메모리
    • 08.가상 메모리
    • 입출력 장치
    • 파일 시스템
  • UIKit
    • UITableView xib으로 만들어보기
  • 🖊️정보 기록
    • 코코아팟 배포하는 방법
  • iOS Project
    • 채팅 앱 만들기
      • Trouble shooting
      • 1. 디자인
      • 2. AutoLayout
    • 날씨 조회 어플리케이션
      • Figma를 이용한 UI 설계
      • TableView 연결하기
      • Networking
    • MVC -> MVVM으로 구조 변경해보기
      • MVC
      • MVVM
    • OAuth Project
      • 로컬 호스트를 이용한 로그인 페이지 제작
      • Github의 OAuth App 설정
    • Rest API 프로젝트
      • UI설계 (with Figma)
      • Network Model
      • MVVM 구조 전환
  • 🕶️UIKit
    • Compositional Layout
Powered by GitBook
On this page
  • 공통 코드
  • 모델
  • 네트워크 통신
  1. iOS Project

MVC -> MVVM으로 구조 변경해보기

MVVM은 무엇이고, 왜 사용해야할까?

많은 글들을 보고, 코드를 봤지만 나는 아직도 왜 MVVM이 필요한지 모르겠다..

그래서 MVC를 MVVM으로 리팩토링해보며 왜 필요한 지 공부해보고자 한다.

우선 내가 만들고자 하는 앱은 iTunes API를 이용해 음악 정보를 받아오는 아주 단순한 앱이다.

MVVM, MVC에서 공통적으로 사용하는 코드는 다음과 같다.

공통 코드

모델

import Foundation

struct MusicData: Decodable {
    let resultCount: Int
    let results: [Music]
}

struct Music: Decodable {
    
    let albumImage: String
    let musicTitle: String
    let artist: String
    let albumName: String
    let releaseDate: String
    
    enum CodingKeys: String, CodingKey {
        case albumImage = "artworkUrl100"
        case musicTitle = "trackName"
        case artist = "artistName"
        case albumName = "collectionName"
        case releaseDate = "releaseDate"
    }
}

네트워크 통신

import Foundation

enum NetworkError: Error {
    case urlError
    case networkError
    case dataError
    case parseError
}

final class NetworkManager {
    
    static let shared = NetworkManager()
    private init() {}
    
    func requestData(term: String, completion: @escaping (Result<[Music], NetworkError>) -> Void) {
        
        let baseURLString = "https://itunes.apple.com"
        
        guard var urlComponents = URLComponents(string: baseURLString) else {
            completion(.failure(.urlError))
            return
        }
        
        let mediaQueryItem = URLQueryItem(name: "media", value: "music")
        let termQueryItme = URLQueryItem(name: "term", value: term)
        
        urlComponents.path = "/search"
        urlComponents.queryItems = [mediaQueryItem, termQueryItme]
        
        guard let url = urlComponents.url else {
            completion(.failure(.urlError))
            return
        }
        
        fetchData(url: url) { result in
            completion(result)
        }
    }
    
    private func fetchData(url: URL, completion: @escaping (Result<[Music], NetworkError>) -> Void) {
        
        let session = URLSession(configuration: .default)
        
        let task = session.dataTask(with: url) { data, response, error in
            
            if let error {
                print(error.localizedDescription)
                completion(.failure(.networkError))
                return
            }
            
            guard let data else {
                completion(.failure(.dataError))
                return
            }
            
            if let musics = self.parseJSON(data) {
                completion(.success(musics))
            } else {
                completion(.failure(.parseError))
            }
        }
        
        task.resume()
    }
    
    private func parseJSON(_ data: Data) -> [Music]? {
        do {
            let musicData = try JSONDecoder().decode(MusicData.self, from: data)
            return musicData.results
        } catch {
            return nil
        }
    }
}
PreviousNetworkingNextMVC

Last updated 2 years ago