SwiftUI의 선언적 구문
UIKit과 인터페이스 빌더를 사용하여 사용자 인터페이스 레이아웃을 설계하고 필요한 동작을 구현하는 것과는 완전히 다른 방법인 선언적 구문이 SwiftUI에 도입되었다.
화면을 구성하는 컴포넌트들의 레이아웃과 모양에 대한 복잡한 세부 사항을 직접 설계하는 대신, SwiftUI는 단순하면서도 직관적인 구문을 이용해 화면을 기술할 수 있게 한다. 다시 말해, SwiftUI를 사용하면 레이아웃이 실제록 구축되는 방식의 복잡함에 대해 고민할 필요 없이 사용자 인터페이스가 어떤 모양이어야 하는지를 선언하는 방식으로 레이아웃을 생성할 수 있다.
- 레이아웃에 포함될 컴포넌트들을 선언하고, 그것들이 포함될 레이아웃 매니저 종류를 명시하고, 속성(버튼의 텍스트, 레이블의 포그라운드 색상, 탭 제스처시 호출될 메서드 등)을 설정하기 위해 수정자를 사용한다.
- 이렇게 선언하고 나면 레이아웃의 위치와 컨스트레인트 그리고 렌더링 방법에 대한 모든 복잡한 세부사항은 SwiftUI가 자동으로 처리한다.
- SwiftUI 선언은 계층적으로 구조화되어 있다. 따라서 작고 재사용이 가능한 사용자 정의 하위 뷰와 함께 구성하면 복잡한 뷰를 쉽게 생성할 수도 있다.
SwiftUI는 데이터 주도적이다
SwiftUI가 데이터 주도적이라고 말했지만, 그렇다고 사용자에 의해 생성되는 이벤트(다시 말해, 사용자와 앱의 사용자 인터페이스 간의 상호작용)를 더이상 처리할 필요가 없다는 말은 아니다. 예를 들어, 사용자가 버튼을 눌렀을 때를 알아야 하며 어떤 반응을 하도록 하는 것은 여전히 필요하다. 데이터 주도라는 것은 앱 데이터와 앱의 사용자 인터페이스 및 로직 사이의 관계에 대한 의미다.
SwiftUI 이전에는 앱 내에 있는 데이터의 현재 값을 검사하려면 그에 대한 코드를 앱에 포함해야 했다. 시간이 지나 데이터가 변한다면, 사용자 인터페이스가 데이터의 최신 상태를 항상 반영하도록 하는 코드도 작성해야 할 것이다.
사용자 인터페이스 상태를 일관적으로 유지하거나 토글 버튼 설정이 적절하게 저장되었는지와 같은 문제를 확인할 때도 비슷한 문제가 발생한다. 동일한 데이터 소스를 앱의 여러 영역에서 사용할 경우엔 소스코드의 복잡도가 증가할 수 있다.
- SwiftUI는 앱의 데이터 모델과 사용자 인터페이스 컴포넌트, 그리고 기능을 제공하는 로직을 바인딩하는 여러 방법을 통해 이러한 복잡도를 해결한다.
- 데이터 주도로 구현하면 데이터 모델은 앱의 다른 부분에서 구독(subscribe)할 수 있는 데이터 변수를 게시(publish)하게 된다. 이러한 방법을 통해 데이터가 변경되었다는 사실을 모든 구독자에게 자동으로 알릴 수 있다.
- 만약 사용자 인터페이스 컴포넌트와 데이터 모델 간에 바인딩이 된다면, 추가적인 코드를 작성하지 않아도 모든 데이터의 변경 사항을 SwiftUI가 사용자 인터페이스에 자동으로 반영할 것이다.
[!note] 대충 감이 오는 듯 하면서도 깔끔하게 머리에 들어오진 않는다. 번역 문제인가? GPT에게 조금 더 쉽게 풀어달라고 요청했다.
UIKit의 방식
- 버튼 레이블, 이미지 같은 UI 요소를 하나씩 만들고
- 위치 잡고, 크기 정하고, 제약(Constraints)설정하고
- 이벤트 처리 코드까지 직접 다 연결해야 했다.
- 예를 들어 이런 느낌이다.
let button = UIButton() button.setTitle("누르세요", for: .normal) button.frame = CGRect(x: 100, y:200, width: 200, height: 50) view.addSubView(button) SwiftUI의 방식
- 어떤 UI를 어떻게 생기게 할 건지 선언하면 된다.
- 세부적인 배치나 렌더링은 SwiftUI가 알아서 해준다.
Button("누르세요") { print("버튼 눌림") } .padding() .background(Color.blue) .foregroundColor(.white) - 그냥 "이런 버튼이 있고, 파란 배경에 하얀 글씨야"라고 선언하면, SwiftUI가 알아서 배치하고 그려준다.
핵심은, UIKit은 "어떻게 만들지"를 하나하나 명령하는 명령형 방식, Swift는 "이렇게 생겼으면 좋겠다"를 선언하는 선언형 방식이라는 것.
Swift의 데이터 주도성
- UIKit에서는 데이터가 바뀌면 UI도 바꿔주는 코드를 직접 써야 했다.
- 예: label.text = "새로운 값"
- SwiftUI에서는 데이터와 UI를 연결(바인딩)해두면, 데이터가 바뀔 때 UI가 자동으로 업데이트된다.
struct ContentView: View { @State var count = 0 var body: some View { VStack { Text("카운트: \(count)") Button("증가") { count += 1 } } } } - 여기서 count 값이 바뀌면 Text도 자동으로 업데이트됨.
- UI를 다시 그리라고 하는 코드(label.text = ...)를 쓸 필요가 없음.
핵심: SwiftUI는 데이터 - UI 자동 연결. 데이터만 바꾸면 화면이 알아서 최신 상태로!
정리
- 선언적 구문: 어떤 화면을 만들 건지를 말하면 SwiftUI가 세부 구현을 대신함.
- 데이터 주도: 데이터와 UI를 바인딩해두면 데이터가 변할 때 UI도 자동으로 갱신됨.
SwiftUI는 데이터의 변화가 앱의 동작과 모양을 주도한다는 점에서 데이터 주도적이다. 이것은 게시자와 구독자 모델을 통해 이뤄진다.