SwiftUI

SwiftUI - 선언형과 명령형

j2kb 2023. 4. 10. 21:21
반응형

안녕하세요 keibi입니다.

처음으로 인사를 하고 글을 쓰려고 하는데 소개부터 한참 시간이 걸리네요

 

아무튼...

오늘부터 SwiftUI 관련 공부하며 정리를 시작합니다.

개인프로젝트를 하려고 하는데 최신 프로그래밍 언어의 흐름도 공부할 겸 SwiftUI와 Combine로 하기로 했거든요.

(SwiftUI로 preview그릴 때 맥북이 힘겨워하는 게 느껴지네요 5년 썼으니 바꿀 때가 된 듯합니다.)

 

 

맨 처음 짚고 넘어갈 것은 왜 SwiftUI인가?! 에 대해서 기존 UIKit과 비교해서 정리해보려고 합니다.

새로 나온 기술은 기존 기술과 다른 점이 있고 그 다른 점이 필요해서 나온 경우가 많으니까요

 

선언형과 명령형??? What과 How???

자료를 모으고 조사하면서 가장 먼저 정리해야겠다 싶은 것은 이 두 개념인 것 같아요.

 

먼저 선언형 프로그래밍은 명령형 프로그래밍과 대비되는 개념으로

프로그램이 수행할 동작을 순차적으로 나열하는 것이 아니라

결과적으로 구현하고자 하는 것을 '명세'하는 형태로 작성하는 프로그래밍 방법입니다.

 

WHAT(구현하고자 하는 것을 명세) vs HOW(수행할 동작을 순차적)

이게 무슨 말이죠??

 

 

예시를 들어볼게요

아내가 저에게 저녁밥을 차려야 하니 계란 10구짜리 하나 사 오라고 합니다

(아내 왈, 여보 간단하게 계란 장조림만 다시 해서 밥 묵자)

 

 

명령형 : 집으로 오는 길에 왼쪽을 확인한다

              OO마트가 문을 열었는지 확인하고 들어간다

              들어가서 왼쪽 신선식품 쪽으로 걸어간다

              신선식품 코너 옆에 있는 10구짜리 계란을 집는다

              결제할 곳으로 가지고 간다

              카드로 결제한다

              비닐에 계란을 담아서 집에 들고 간다

선언형 : 신선한 계란 10구 하나 부탁해~

 

 

차이가 보이시나요??

선언형은 무엇에 해당하는 '계란'에만 관심이 있고

명령형은 어떻게 계란을 살 수 있는지를 다 적는다는 차이가 있죠

 

저는 여기서 답답한 마음에 질문이 하나 생기더라고요.

 

아니 어쨌든 계란은 어딘가에 들려서 카드든 현금이든 내고

사 와야 하는데 필요한 다른 정보는 어디에 있는 거지??

 

답변부터 하자면 SwiftUI가 필요한 정보를 알아서 해결해 준다!입니다

선언형 방식이 동작하기 위해서는 '어떻게'에 해당하는 (마트 위치나, 결제 수단 같은 것들) 것들이 추상화되어 있어야 해요

 

아래와 같은 화면을 UIKit과 SwiftUI로 구현해서 차이점을 알아볼게요. 배경에 이미지와 글자만 있는 화면입니다.

먼저 SwiftUI

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.purple
                .ignoresSafeArea()
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundColor(.black)
                Text("Hello, world!")
                    .font(.largeTitle)
            }
        }
    }
}

그리고 UIKit

import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        view.backgroundColor = .purple
        
        let imageView = UIImageView(image: UIImage(systemName: "globe"))
        imageView.tintColor = .white
        imageView.scalesLargeContentImage = true
        imageView.translatesAutoresizingMaskIntoConstraints = false
        
        let textLabel = UILabel()
        textLabel.translatesAutoresizingMaskIntoConstraints = false
        textLabel.text = "Hello, World!"
        textLabel.font = .preferredFont(forTextStyle: .largeTitle)
        textLabel.textColor = .white
        
        view.addSubview(imageView)
        view.addSubview(textLabel)
        
        NSLayoutConstraint.activate([
            imageView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            imageView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: -20)
        ])
        NSLayoutConstraint.activate([
            textLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            textLabel.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 20)
        ])
    }
}

확실히 기존 UIKit은 어떻게까지 일일이 개발자가 쓰다 보니 코드의 양이 좀 더 많은 것을 볼 수 있고

SwiftUI는 많은 것이 미리 정의가 되어 있으니 보다 짧은 코드로 쓸 수 있는 것을 알 수 있죠

 

여기서 몇 가지 더 쓸 거 없나 끄적끄적거리다가 VStack을 뷰의 상단에 붙여보고 싶어졌어요.

그런데 VStack이 제공하는 옵션은 딱 2개뿐이더라고요 alignment, spacing

@frozen public struct VStack<Content> : View where Content : View {

    /// Creates an instance with the given spacing and horizontal alignment.
    ///
    /// - Parameters:
    ///   - alignment: The guide for aligning the subviews in this stack. This
    ///     guide has the same vertical screen coordinate for every subview.
    ///   - spacing: The distance between adjacent subviews, or `nil` if you
    ///     want the stack to choose a default distance for each pair of
    ///     subviews.
    ///   - content: A view builder that creates the content of this stack.

확실히 많은 부분이 추상화된 만큼 직접 건드릴 수 있는 부분은 적어진 것 같아요. 그럼 이럴 땐 어떻게 하냐?!

VStack {
    Image(systemName: "globe")
        .imageScale(.large)
        .foregroundColor(.white)
    Text("Hello, world!")
        .font(.largeTitle)
        .foregroundColor(.white)
    Spacer()
}

요렇게 밑에 길이가 남은 공간에 따라 줄어드는 Spacer()를 활용하면 요렇게 위에 붙일 수가 있습니다.(익숙해지려면 약간의 노하우(?)같은 지식이 필요하겠네요ㅎㅎ)

 

 

읽어주셔서 감사합니다!

언제든 잘못된 정보는 꼭 답글로 달아주시면 감사하겠습니다 ( _ _ )

반응형