본문 바로가기

이상/iOS

[iOS] 디자인 패턴 - MVC

반응형

iOS 개발을 처음 시작하고 2년 정도는 정말 주먹구구식으로 개발을 했던 것 같다.

지금도 '이제는 그렇지 않다'라고 딱 잘라 말할 순 없지만

 

클래스를 만들 생각조차도 못했었고 그냥 모조리 ViewController에 때려박았었다.

 

그러다 팀장님이 하시던 프로젝트를 갑자기 넘겨받게 됐는데

 

그때 처음 디자인 패턴이 이런거구나라는걸 느꼈다.

 

MVC 패턴으로 구성돼있었는데 그 패턴 그대로 베껴서

 

내가 만들었던 프로젝트들을 다시 만들어봤다.

 

처음엔 디자인 패턴? 그런게 필요한가? 그냥 돌아가면 되지라는 생각으로 개발했었는데

진짜 멍청하고 바보같은 생각이었다

 

MVC를 적용하니 정리정돈이 깔끔하게 되는 것 같은 느낌이 들었다.

 

 

이렇게 디자인 패턴은 소스를 깔끔하게 정리해 유지보수를 쉽게 할 수 있고

 

각 부분의 역할 분담이 돼있어서 테스트하기 좋다.

 

 

 

1. MVC

Model - View - Controller로 이루어져 있으며

 

가장 기본적이면서 많이 쓰이는 디자인 패턴이다.

 

iOS에는 ViewController가 있기 때문에 파일로 딱딱 나눠지지는 않아서

 

의식적으로 구분하면서 개발하면 될 것 같다.

 

 

Stanford iOS Lecture

 

 

스탠포드 iOS 강좌에서 MVC에 대해 이런 그림으로 설명을 했다.

 

Model과 View는 서로 독립적이기 때문에 중앙선으로 분리되어 있고,

 

Controller에서 Model 또는 View로만 접근할 수 있기 때문에 복선형태이다.

 

서버에서 데이터를 받아와 화면에 뿌려주는 기능을 개발할 때

 

Controller에서 데이터를 받아와 그 데이터로 Model을 만들고

 

만든 모델의 데이터를 알맞게 뷰에 꽂아넣는다.

 

Model이나 View가 독립적으로 하는 건 없고 Controller에 따라 작동한다.

 

Controller는 Model의 변경사항에 맞게 View에 대응하고

 

View의 변경사항에 맞게 Model에 대응한다.

 

 

하지만 iOS에서는 Controller가 View를 포함하고 있는 형태이기 때문에

 

LifeCycle에 대한 부분도 포함하고 있으며,

 

네트워크 통신과 같은 각종 부가적인 부분들이 들어가게 되면

 

Controller가 점점 비대해져 이러려고 MVC 패턴을 적용했나 싶은 상황이 생긴다.

 

정리

Model: 데이터

View: 말 그대로 View. 보여지는 것

Controller: 제어하는 놈

 

 

 

2. 구현

예제로 운동 목록 데이터를 CollectionView에 보여주는 것을 만들어보려고 한다.

 

Model

DB에서 index값으로 사용할 id와

 

운동에 대한 정보 title, sets, exercise, rest, description이 있다.

1
2
3
4
5
6
7
struct Exercise: Codable {
    var id: Int
    var title: String
    var sets: Int
    var exercise: Int
    var rest: Int
}
cs

 

 

 

View

화면에 보여줄 것은 CollectionView 다.

 

CollectionView의 Cell마다 운동 데이터가 들어갈 것이므로

 

Model에 맞게 Cell을 만든다.

 

 

View

 

1
2
3
4
5
6
7
class ExerciseCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var setsLabel: UILabel!
    @IBOutlet weak var exerciseLabel: UILabel!
    @IBOutlet weak var restLabel: UILabel!
    var id: Int!
}
cs

 

 

Controller

서버에서 받아온 운동 목록 데이터를 Exercise Model로 만들고

 

CollectionView에 뿌려준다.

 

viewDidLoad()에서 CollectionView에 대한 설정을 해준 후

 

getExerciseList()를 호출하여 데이터를 받아온다.

 

받아온 데이터를 exerciseList에 넣어주고 프로퍼티 옵저버 didSet에서 reloadData()를 호출한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class ViewController: UIViewController {
    
    // View를 포함
    @IBOutlet weak var exerciseCollectionView: UICollectionView!
    
    var exerciseList = [Exercise]() {
        didSet {
            // [Exercise]가 Set되면 CollectionView reloadData()
            self.exerciseCollectionView.reloadData()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        exerciseCollectionView.dataSource = self
        exerciseCollectionView.collectionViewLayout = self.getCollectionViewLayout()
        getExerciseList()
    }
    
    func getExerciseList() {
        let url = Constants.BASE_URL+Constants.EXERCISE_GET_LIST
        // 데이터 요청
        ApiManager.shared.selectData(from: url) { (data: [Exercise]?, error) in
            guard let data = data else {
                print("error: \(error?.debugDescription)")
                return
            }
            // 데이터 Set
            self.exerciseList = data
        }
    }
}
cs

 

실행하면 이렇게 나온다.

 

 

결과

 

 

전체 소스는 여기에.

반응형