본문 바로가기

Project/HiddenGem

🤔 MVVM 패턴에서 앱 실행 시 자동으로 데이터 가져오는 함수를 꼭 viewDidLoad()에서 호출해야 하나?

✅ 현재 구조 분석

Task {
    await eateriesViewModel.fetchEateries()
}

 

  • fetchEateries()를 호출하지 않으면 @Published var eateries는 아무 데이터도 없고, Combine 구독도 반응하지 않음 → UI 업데이트도 안 됨
  • 따라서 데이터 fetch는 반드시 필요한 동작이고, UIKit에서는 보통 viewDidLoad() 또는 viewWillAppear()에서 호출하는 게 일반적입니다.

 

✅ "꼭 viewDidLoad에서만 해야 하나요?"에 대한 답

꼭 viewDidLoad()에서 할 필요는 없습니다.
하지만 UIKit에서 앱이 시작될 때 ViewController가 메모리에 올라오고 초기화되는 시점viewDidLoad()입니다.
따라서 “처음 한 번만” 실행되기를 원한다면 적절한 위치는 다음 중 하나예요:

 

🔹 1. viewDidLoad()

가장 일반적인 위치. 초기 설정, 초기 데이터 fetch에 적합.

override func viewDidLoad() {
    super.viewDidLoad()
    bindViewModel()
    fetchCategories() // 여기에 있음
}

 

 

🔹 2. ViewModel 초기화 시점에서 자동 호출

이 방법은 MVVM의 철학에 더 가까운 방식입니다. 즉, ViewModel이 생성되면 곧바로 데이터를 가져오게 하는 것입니다.

class EateryViewModel: ObservableObject {
    @Published var eateries: [EateryItem] = []
    
    init() {
        Task {
            await fetchEateries()
        }
    }

    func fetchEateries() async {
        // ...
    }
}

 

🔸 이 방식의 장점:

  • ViewModel만 만들어지면 자동 fetch됨 → ViewController에서 따로 호출할 필요 없음
  • 더 깔끔한 MVVM 구조

🔸 단점:

  • ViewController에서 제어가 어려워질 수 있음 (예: 특정 조건에서만 fetch해야 하는 경우)

✅ 그래서 이 방법은 항상 데이터를 fetch해야 하는 단순한 ViewModel에는 적합합니다.

 

 

결론: 어떻게 하는 게 좋을까?

  • viewDidLoad(): UIKit 일반적인 초기화 지점, fetch 시점 명확함 
  • ViewModel의 init()에서 fetch: MVVM 철학에 더 가까움. 단, 제어 어렵고 예외 처리 복잡
  • viewWillAppear(): 화면이 다시 등장할 때마다 fetch. 반복 fetch 원할 때 적합 
✅ 지금처럼 viewDidLoad()에서 Task로 fetch 호출하는 방식은 가장 일반적이고 안정적입니다.
만약 "MVVM 철학상 ViewModel에서 처리하고 싶다"면 init에서 fetch 하는 방식도 고려해볼 수 있다. 

 

 

 

 

🌟 bindViewModel()을 먼저 실행

이렇게 해야 하는 이유:

  1. @Published var eateries는 Combine 기반으로 동작하므로,
  2. fetchEateries()에서 데이터가 @Published 변수에 할당될 때,
  3. 이미 바인딩이 되어 있어야 View가 그 변화를 감지하고 UI를 업데이트할 수 있음
override func viewDidLoad() {
    super.viewDidLoad()
    
    bindViewModel()       // ✅ 먼저 ViewModel의 publisher를 View에 바인딩하고
    fetchCategories()     // ✅ 그 다음 데이터를 fetch해서 배열을 채움
}

 

반대로 할 경우에는 데이터가 이미 세팅된 후에 bind 하게 되기 때문에, 최초 값에 대한 업데이트 이벤트를 놓칠 수 있습니다.