-
안녕하세요, 2023년 루키 세미나 청강중인 우현민입니다 (기존 스택: 프론트엔드). ios hw0을 진행하던 중 궁금한 게 생겨 질문드립니다. 배경지금까지 튜토리얼이나 문서, 블로그 등을 찾아본 바로는, 가령 label을 만드는 경우 아래와 같이 ui를 셋업하면 된다고 이해했습니다. // WafflestudioViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
let title = UILabel()
title.text = "와플스튜디오"
title.font = UIFont.boldSystemFont(ofSize: 24)
view.addSubView(title);
NSLayoutConstraint.activate([
title.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20)
])
} 아무래도 코드 줄 수가 많아지고 반복되는 로직이 많아지는 점, 하나의 객체를 생성한 다음 계속 속성을 변경해야 해서 mutable한 코드가 되는 점 등등 때문에 UI 속성들을 조금 더 함수형 / 선언형으로 추상화할 수 있으면 좋겠다고 생각했습니다. 가령 // Typography.swift
import UIKit
class Typography: UILabel {
convenience init(text: String, style: TextStyle) {
self.init()
self.text = text
setup(style: style)
}
func setup(style: TextStyle) {
font = style.font
textColor = style.textColor
textAlignment = .left
numberOfLines = 1
lineBreakMode = .byTruncatingTail
}
// 스타일 정의를 위한 내부 구조체
struct TextStyle {
let font: UIFont
let textColor: UIColor
}
// 미리 정의된 스타일 예제
static let titleStyle = TextStyle(
font: UIFont.boldSystemFont(ofSize: 24),
textColor: UIColor.black
)
} // WafflestudioViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
let title = Typography("와플스튜디오", style: Typography.titleStyle)
view.addSubiew(title)
NSLayoutConstraint.activate([
title.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20)
])
} 공통 컴포넌트를 분리해내는 대신 이런 방식들도 고민해봤지만,
혹시 가능하다면, 조금 더 함수형/선언적으로 아래와 같은 신택스도 시도해보고 싶습니다. // WafflestudioViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(Typography("와플스튜디오", style: Typography.titleStyle, topAnchorConstant: 20))
} 그런데 이런 공통 컴포넌트를 만들다 보니 추후 추가될 수 있는 특정 속성을 처리하기 어려워진다거나, 컴포넌트의 실행 순서가 맞지 않아 오류가 발생한다거나, 레이아웃을 잡기 어려워진다거나 등등의 상황이 발생할 수도 있지 않을까? 하는 걱정이 들었습니다. iOS 진영의 문화와 맞지 않을 수도 있을 것 같았어요. 아직 경험이 한참 부족하여 어떤 문제가 있을지는 잘 모르겠습니다 😅 막연한 걱정입니다 질문배경 설명이 너무 길었는데, 그래서 본 질문은: 보통 ui를 선언적으로 작성하고자 하는 니즈가 있는지, 있다면 ui를 선언적으로 작성하기 위해 어떤 패턴이나 기법이 추가로, 혹시 위에 제가 만들어둔 코드에 네이밍이나 등등 조언해주실 부분이 있으시다면 그 부분들도 조언해주시면 정말 감사드리겠습니다..! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
UIKit으로 선언적 UI를 작성하는 것은 간단한 일은 아니긴 합니다. 예를 들어 FlexLayout & PinLayout 이라는 것을 사용하면 아래와 같이 웹스럽게(?) 레이아웃을 지정해줄 수 있다고 합니다. 전 안써봤지만요 😅 init(frame: CGRect) {
super.init(frame: frame)
self.addSubView(self.flexContainer)
self.flexContainer.flex
.direction(.row)
.justifyContent(.start)
.alignItems(.center)
.define { flex in
flex.addItem(self.label1)
.marginEnd(6.0)
flex.addItem(self.label2)
}
} 개인적으로 저는 (언제 유지보수가 종료될지 모르는) 이런 서드파티 라이브러리를 신뢰하지는 않아요. 비슷한 예시로 Texture라는 것도 있는데, 스타가 7k개나 되고 핀터레스트와 텔레그램이 사용하고 있지만 제대로 된 메인테이너가 없어서 issue가 쌓여만 가고 있는 걸 볼 수 있죠..ㅋㅋ 따라서 UI를 선언적으로 작성하고 싶다면 퍼스트파티 프레임워크인 SwiftUI를 추천해요. 참고로 SwiftUI도 내부적으로 UIKit 위에서 돌아가고, 그렇기 때문에 이런 식으로 UIKit과 SwiftUI를 함께 사용할 수도 있습니다. 다만 SwiftUI는 비교적 최근에 나온 프레임워크라서, 최신 트렌드가 반영된 깔끔한 코드를 작성할 수는 있지만 요구사항이 복잡해질수록 SwiftUI만으로 구현하기 어려운 경우가 많아요. 저희 회사 코드도 거의 100% UIKit으로 이루어져 있고, 향후 몇 년 동안은 이대로 유지될 가능성이 높아보이네요. 기타 피드백view 관련 코드를 선언할 때에는 아래와 같이 import UIKit
import SnapKit
class ViewController: UIViewController {
private lazy var titleLabel = {
let label = UILabel()
label.text = "와플스튜디오"
label.font = .boldSystemFont(ofSize: 24)
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
setupLayout()
}
private func setupLayout() {
view.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide.snp.top).inset(20)
make.leading.bottom.trailing.equalToSuperview()
}
}
}
대신 라이브러리 추가할 때는 Cocoapods 말고 Swift Package Manager 써주세요...
view.addSubview(Typography("와플스튜디오", style: Typography.titleStyle, topAnchorConstant: 20)) 신선한 시도이지만, 과제0에서는, |
Beta Was this translation helpful? Give feedback.
UIKit으로 선언적 UI를 작성하는 것은 간단한 일은 아니긴 합니다.
하지만 말씀하신대로 선언적 UI에 대한 니즈가 꾸준히 있어왔고, 몇 가지 서드파티 대안들이 나와 있긴 해요.
예를 들어 FlexLayout & PinLayout 이라는 것을 사용하면 아래와 같이 웹스럽게(?) 레이아웃을 지정해줄 수 있다고 합니다. 전 안써봤지만요 😅
개인적으로 저는 (언제 유지보수가 종료될지 모르는) 이런 서드파티 라이브러리를 신뢰하지는 않아요. 비슷한 예시로 Texture라는 것도 있는데, 스타가 7k개나 되고 핀터레스트와 텔레그램이 사용하고 있지만 제대로 된 메인테이너가 없어서 issue가 쌓여만 가고 있는 걸 볼 수 있…