Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- clean architecture
- uiscrollview
- rxswift
- Clean Code
- HIG
- ios
- 클린 코드
- collectionview
- 스위프트
- swiftUI
- combine
- Protocol
- swift documentation
- Refactoring
- Human interface guide
- Xcode
- tableView
- Observable
- UITextView
- 리펙터링
- SWIFT
- UICollectionView
- 리팩토링
- MVVM
- ribs
- uitableview
- 애니메이션
- RxCocoa
- map
- 리펙토링
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] Protocol 활용하여 모델 구성하는 방법 (프로토콜로 중복모델 막기) 본문
Protocol 활용하여 모델 구성하는 방법
- 프로토콜의 기능이 여러가지 있지만 그중에 모델을 구성할 때 유용하게 사용이 가능
- 한 프로젝트에서 여러명의 개발자들이 동시에 일을 진행할때, 모델에 대한 구성을 어떻게 할 것인지 의사결정을 할때도 프로토콜을 활용하면 중복 모델 최소화가 가능
- 사용하는 쪽에서 필요한 정보들을 Protocol로 정의하고 공통 모델에 이 Protocol을 준수하는 방법
ex) Cafe라는 정보를 가지고 있는 모델과 API가 아래와 같은 경우
struct Cafe {
/// 카페 이름
let name: String
/// 카페 위치 (주소)
let location: String
/// 영업 시간 (예: "08:00 AM - 10:00 PM")
let openingHours: String
/// 연락처 (옵션)
let contactNumber: String
/// 카페의 메뉴 리스트
let menu: [MenuItem]
/// 평균 평점 (1.0 ~ 5.0)
let rating: Double
/// 반려동물 동반 가능 여부
let isPetFriendly: Bool
/// Wi-Fi 제공 여부
let hasWifi: Bool
/// 주차 가능 여부
let hasParking: Bool
}
/// 메뉴 항목을 나타내는 구조체
struct MenuItem {
/// 메뉴 이름
let name: String
/// 메뉴 가격 (단위: 원)
let price: Double
/// 현재 판매 가능 여부
let isAvailable: Bool
}
- 이 API를 활용하여 "카페에 관한 정보"를 Home화면과 Detail화면에 표현해주는 경우 아래처럼 각각 모델 설계가 가능
- 보통은 아래처럼 필요한 곳에서 관심있는 프로퍼티를 선언하여 struct모델을 만들어서 관리
class HomeViewController: UIViewController {
struct CafeHome {
let name: String
let location: String
let openingHours: String
let contactNumber: String
let rating: Double
}
}
class DetailViewController: UIViewController {
struct Menu {
let name: String
let price: Double
let isAvailable: Bool
}
}
- 하지만 이 방법의 단점은 API에서 받은 모델을 각 뷰에 필요한 모델로 컨버팅이 각각 필요하다는 단점이 있다는 것
extension Cafe {
var asCafeHome: HomeViewController.CafeHome {
.init(
name: name,
location: location,
openingHours: openingHours,
contactNumber: contactNumber,
rating: rating
)
}
}
extension [MenuItem] {
var asDetailMenu: [DetailViewController.Menu] {
self.map { .init(name: $0.name, price: $0.price, isAvailable: $0.isAvailable) }
}
}
let cafe = API.requestCafe()
let homeViewController = HomeViewController(cafeHome: cafe.asCafeHome)
let detailViewController = DetailViewController(menus: cafe.menu.asDetailMenu)
프로토콜로 모델 구성하기
- 프로토콜은 필요한 정보들을 나열한 것으로 해당 프로토콜만 보아도 getter 전용인지 setter 전용인지까지 알 수 있음
- 아래처럼 필요한 정보를 protocol로 선언하고 이것을 공통 모델(Cafe)에만 선언해 준다면 별도의 컨버팅 로직 없이 더욱 구조화가 용이
protocol CafeHomeable {
var name: String { get }
var location: String { get }
var openingHours: String { get }
var contactNumber: String { get }
var rating: Double { get }
}
class HomeViewController: UIViewController {
let cafeHome: CafeHomeable
}
protocol Menuable {
var menu: [MenuItem] { get }
}
class DetailViewController: UIViewController {
let menu: Menuable
}
struct Cafe: CafeHomeable, Menuable {
...
}
- 프로토콜로 설계하면 모델들의 컨버팅 중복 코드가 줄어드는 장점이 존재
ex) 만약 프로토콜 없이 Detail, Home도 서로 주고 받아야 하는게 있다면 아래처럼 4개가 필요
- 여기서 setting 화면이 추가된다면 convert는 9개로 추가됨
- 즉 모델들이 늘어날수록 중복코드가 n^n만큼 늘어나므로 프로토콜로 만들어서 그 프로토콜을 각 모델에 준수하게하여 설계를 하는것이 좋은 코드 구조
'iOS 응용 (SwiftUI)' 카테고리의 다른 글
[iOS - SwiftUI] 부모 뷰와 자식 뷰 사이의 애니메이션 동작 원리, geometryGroup(), transformEffect(.identity) (0) | 2025.03.19 |
---|---|
[iOS - SwiftUI] 뷰 주입받는 방법 (Generics, AnyView) (0) | 2025.03.12 |
[iOS - SwiftUI] Spacer(minLength:)를 사용할때 주의할 점 (0) | 2025.03.05 |
[iOS - SwiftUI] 그라데이션 넣는 방법 (Linear Gradation) (0) | 2025.02.26 |
[iOS - SwiftUI] 뷰에서 if, else 구분해야할때 id 활용하는 방법 (SwiftUI의 id) (0) | 2025.02.19 |
Comments