병아리의 코딩 일기

[SSAFYcial] MVVM 패턴에 대해 알아보자 (Feat. Swift) 본문

SSAFYCial/기획 기사

[SSAFYcial] MVVM 패턴에 대해 알아보자 (Feat. Swift)

oilater 2024. 6. 3. 23:40

안녕하세요!

드디어 길었던 1년이 끝이 났네요 !!

정말 후련합니다 ㅎㅎ

 

11기는 관통 프로젝트를 마무리했고

10기는 2학기 3개의 프로젝트를 마무리한 후

지금은 온라인 컨설팅을 받으며 채용 박람회를 준비하고 있는데요,

 

저는 제가 만들었던 '홈트친구' 앱을 업데이트하기 위해 iOS 강의를 듣고 있어요.

포폴도 수정해야 하는데,, 얼른 수정해야겠습니다 ㅠ

 

iOS를 학습하던 중, 코드들을 깔끔하게 나누기 위해

MVVM 패턴을 적용해봐야겠다는 생각을 하게 되었습니다.

예전부터 들었던 생각인데 플젝 기간에는 기획하고 구현하기 바빠서 제대로 공부를 못했네요 ㅠ

 

 

그럼 바로 시작합니다!!

 

 

 

MVC (Model View Controller)

MVVM 아키텍처에 대해 알아보기 전에, MVC를 먼저 알아볼게요.

프로젝트를 구성하는 코드들은 크게 3가지로 나뉩니다.

 

사용자에게 보여지는 UI에 관련된 코드,

View 뒤편에 있는 비즈니스 로직,

관리할 데이터에 관련된 코드

 

이렇게 말이죠.

이 코드들은 다음과 같이 이름이 붙었습니다.

 

View

화면을 구성하는 코드

 

Controller

비즈니스 로직에 관련된 코드 (사용자의 입력을 받고 처리하는 부분)

여기서 Controller는 추가적으로 Model을 업데이트하고, 업데이트된 Model을 나타내줄 View를 선택합니다.

 

Model

데이터에 관련된 코드

 

MVC는 위의 그림과 같은 모양으로 구성됩니다.

사용자의 입력(Action)을 Controller가 받아 Model을 업데이트 한 뒤, 이를 반영할 View를 선택합니다.

이 때, 컨트롤러는 View를 선택할 뿐 직접 View를 업데이트하지는 않습니다.

 

 

MVC 패턴은 보시다시피 단순해서 많이 사용되지만,

Controller가 Model을 알아야 하고, View 또한 알아야하기 때문에 거대해진다는 단점이 존재합니다.

프로젝트 구조가 커질수록 비약적으로 거대해지죠.

 

 

MVVM (Model View ViewModel)

이러한 MVC 패턴의 단점을 보완하기 위해 나온 것이 MVVM 패턴입니다.

 

 

MVVM 패턴을 적용하면,

사용자의 입력(Action)을 더 이상 Controller가 받지 않고, View에서 받게 됩니다.

그 후 ViewModel에 Action을 전달하여 처리합니다.

ViewModel은 Model에게 데이터를 요청하고, Model은 이에 응답합니다.

Model의 데이터가 바뀌면, 별다른 코드 없이도 View에 Binding되어 화면에 나타납니다.

 

이렇게 MVVM 패턴은 거대했던 Controller의 역할을 줄이고,

비슷한 비율로 코드를 쪼갤 수 있게 됩니다.

또한  Binding을 이용해 View와 ViewModel 간의 의존성을 없애기에,

모듈화하여 개발할 수 있게 됩니다.

 

 

그럼, MVVM 패턴을 사용한 Swift 코드 예시를 들어보겠습니다.

 

 

Model

다음은 인스타그램에 올릴 포스트에 관한 데이터 Model입니다.

import Foundation

struct Post: Codable {
    let id: String // 고유 ID
    let caption: String // 내용
    var like: Int // 좋아요 수
    let imageUrl: String // 업로드 할 사진 url
    let date: Date // 등록 날짜
}

 

참고로 Codable을 사용한 이유는 이 Model이 현재는 Swift 내에서만 쓸 수 있지만, Encodable, Decodable을 붙여주면 Firebase 등으로 내보내고 받을 수 있도록 인코딩, 디코딩 기능을 탑재해주기 때문입니다. Encodable, Decodable을 합쳐 Codable로 사용할 수 있습니다.

 

View

다음은 화면에 관련된 UI 코드입니다.

필요한 부분만 적어보았습니다.

struct NewPostView: View {
    
    @Binding var tabIndex: Int
    @State var viewModel = NewPostViewModel()
    
    var body: some View {
        VStack {
            TextField("문구를 작성하거나 설문을 추가하세요", text: $viewModel.caption)
                .padding()
            Spacer()
            Button {
                print("사진 공유")
                Task {
                    await viewModel.uploadPost()
                    viewModel.clearData()
                    tabIndex = 0
                }
            } label: {
                Text("공유")
                    .frame(width: 363, height: 42)
                    .foregroundStyle(.white)
                    .background(.blue)
                    .clipShape(RoundedRectangle(cornerRadius: 10))
            }
            .padding()
        }
    }
}

}

 

코드 상단에 ViewModel을 생성해주었습니다. 

사용자가 버튼을 누를 때 View에서는 ViewModel에 있는 함수를 호출하여 Action을 전달하는 것을 볼 수 있습니다.

 

ViewModel

사용자의 입력을 처리하는 ViewModel 코드입니다.

역시나 불필요한 부분은 생략했습니다.

@Observable
class NewPostViewModel {
    var caption = ""
    var selectedItem: PhotosPickerItem?
    var postImage: Image?
    var uiImage: UIImage?

    
    func uploadPost() async {
        guard let uiImage else { return }
        guard let imageUrl = await uploadImage(uiImage: uiImage) else { return }
        
        let postReference = Firestore.firestore().collection("posts").document()
        let post = Post(id: postReference.documentID, caption: caption, like: 0, imageUrl: imageUrl, date: Date())
        
        do {
            let encodedData = try Firestore.Encoder().encode(post)
            try await postReference.setData(encodedData)
        } catch {
            print("DEBUG: Failed to upload post with error \(error.localizedDescription)")
        }
    }
    
    func clearData() {
        caption = ""
        selectedItem = nil
        postImage = nil
        uiImage = nil
    }
}


이런 식으로 ViewModel은 View에서 넘겨받은 사용자의 Action을 처리합니다.

 


 

여기까지 MVC 패턴과 MVC의 단점을 보완하기 위해 등장한 MVVM 패턴에 대해 알아보았습니다.

 

사실 SSAFY 프로젝트를 하다보면,

구현해야 할 것들이 너무 많아서 시간에 쫓겨 View에 코드들을 전부 몰아넣는 경우가 많습니다.

저도 그랬고, 대부분 그렇지 않을까 생각합니다.

 

앞으로의 프로젝트에는 이런 MVVM 패턴을 적용하면 조금 더 결합도가 낮고 깔끔한 구조를 가진 코드를 짜보면 더 좋을 것 같습니다!

또한 대부분 기업들의 우대사항에 MVVM 패턴 적용 경험이 적혀있더라구요.

 

그럼 5월 기획기사는 여기서 마무리하겠습니다.

자율 기사에서 만나요 ! 

 

 

참고 자료

https://inf.run/tgXBM

 

Part2: 초중급 iOS 인스타그램 클론(SwiftUI, MVVM, Firebase, 2024) | 애구마(agmma) - 인프런

애구마(agmma) | 인스타그램 앱을 따라만들면서 배우는 실전 SwiftUI강의, Instgram Clone강의 출시!!!!지난 강의 이후 많은 분들이 기다려주셨던 MVVM, Firebase를 이용한Instagram Clone강의를 드디어 출시했습

www.inflearn.com

 

 

https://beomy.tistory.com/43

 

[디자인패턴] MVC, MVP, MVVM 비교

웹 개발자로 일을 하면서 가장 먼저 접한 디자인패턴이 바로 MVC 패턴이었습니다. 그만큼 유명하고 많이 쓰이는 디자인패턴인 MVC 패턴과 MVC 패턴에서 파생되어져 나온 MVP 패턴과 MVVM 패턴을 이야

beomy.tistory.com

 

 

728x90
반응형
LIST