YunDaeHyeon
โ† Lab

๐Ÿค” ์• ํ”Œ ์ƒํƒœ๊ณ„์˜ UI ์•„ํ‚คํ…์ฒ˜ ์›๋ฆฌ๋ฅผ ์•Œ์•„๋ณด์ž.

์Šคํ„ฐ๋””2025.03.16
  • SwiftUI
  • UIKit
  • Swift

๊ณต๋ถ€ํ• ๊ฒŒ ์‚ฐ๋”๋ฏธ

๐Ÿ”Žย ์• ํ”Œ ์ƒํƒœ๊ณ„์˜ UI ์•„ํ‚คํ…์ฒ˜ ์›๋ฆฌ

์• ํ”Œ์˜ UI ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์€ Cocoa Framework ๊ณ„์ธต ์œ„์—์„œ ๋™์ž‘ํ•˜๋ฉฐ, ๊ฐ ์šด์˜์ฒด์ œ(iOS, macOS, watchOS, tvOS)์— ๋”ฐ๋ผ ๋‹ค๋ฅธ UI ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.


๐Ÿ’กย Cocoa & Cocoa Touch

์• ํ”Œ์˜ UI๋Š” Cocoa ๋ฐ Cocoa Touch Framework ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ์ด๋Š” ์šด์˜์ฒด์ œ(OS)์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(Application) ์‚ฌ์ด์˜ ๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•˜๋Š” ํ•ต์‹ฌ ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ์‚ฌ์šฉ OS์„ค๋ช…
CocoamacOSmacOS ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ (Foundation + AppKit)
Cocoa TouchiOS / iPadOS / watchOS / tvOSiOS ์•ฑ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ (Foundation + UIKit)
  • Cocoa : macOS ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ๊ธฐ๋ณธ ํ”„๋ ˆ์ž„์›Œํฌ

โ†’ Foundation + AppKit

  • Cocoa Touch : iOS ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ

โ†’ Foundation + UIKit

์ฆ‰ iOS์—์„œ UI๋ฅผ ๊ฐœ๋ฐœํ•  ๋•Œ UIKit๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ UIKit๋Š” Cocoa Touch ์œ„์—์„œ ๋™์ž‘ํ•œ๋‹ค.


๐Ÿค”ย iOS์™€ macOS์˜ UI ํ”„๋ ˆ์ž„์›Œํฌ

์• ํ”Œ์€ ๊ฐ ์šด์˜์ฒด์ œ๋งˆ๋‹ค UI ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋”ฐ๋กœ ์ œ๊ณตํ•˜์ง€๋งŒ ์ „์ฒด์ ์œผ๋กœ ๋น„์Šทํ•œ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

๊ธฐ๊ธฐUI ํ”„๋ ˆ์ž„์›Œํฌ
iPhone / iPadUIKit (Cocoa Touch ๊ธฐ๋ฐ˜)
MacAppKit (Cocoa ๊ธฐ๋ฐ˜)
Apple WatchWatchKit
Apple TVUIKit
๋ชจ๋“  ํ”Œ๋žซํผSwiftUI (iOS, macOS, watchOS, tvOS ๊ณตํ†ต)

โœ…ย UIKit โ†’ iOS์—์„œ UI๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํ•ต์‹ฌ ํ”„๋ ˆ์ž„์›Œํฌ

โœ…ย AppKot โ†’ macOS์—์„œ UI๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํ•ต์‹ฌ ํ”„๋ ˆ์ž„์›Œํฌ

โœ…ย SwiftUI โ†’ ๋ชจ๋“  ์• ํ”Œ ํ”Œ๋žซํผ์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” UI ํ”„๋ ˆ์ž„์›Œํฌ


๐Ÿ“Œย UIKit์™€ AppKit์˜ ์—ญํ• ?

UIKit์™€ AppKit๋Š” ๊ฐ๊ฐ iOS์™€ macOS์—์„œ UI๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ์ „ํ†ต์ ์ธ ๋ฐฉ์‹์ด๋‹ค.

SwiftUI ๊ฐ€ ๋“ฑ์žฅํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์ด ๋‘๊ฐœ์˜ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์• ํ”Œ ์ƒํƒœ๊ณ„์˜ UI๋ฅผ ๋‹ด๋‹นํ–ˆ๋‹ค.

โœ…ย UIKit (iOS & iPadOS)

  • iOS์™€ iPadOS์—์„œ UI๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํ•ต์‹ฌ ํ”„๋ ˆ์ž„์›Œํฌ

  • ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ(UIViewController) ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘

  • ์Šคํ† ๋ฆฌ๋ณด๋“œ(Storyboard) ๋˜๋Š” ์ฝ”๋“œ ๊ธฐ๋ฐ˜ UI ๊ฐœ๋ฐœ ๊ฐ€๋Šฅ

  • ์ฝ”๋“œ ์˜ˆ์‹œ

    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let button = UIButton(type: .system)
            button.setTitle("ํด๋ฆญํ•˜์„ธ์š”", for: .normal)
            button.frame = CGRect(x: 50, y: 150, width: 200, height: 50)
            button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
            
            view.addSubview(button)
        }
    
        @objc func buttonTapped() {
            print("๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์Šต๋‹ˆ๋‹ค!")
        }
    }
    
    

๐Ÿ‘‰ UIViewController ๊ธฐ๋ฐ˜์œผ๋กœ UI๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜๋Š” ๋ช…๋ นํ˜•(Imperative UI) ๋ฐฉ์‹์ด๋‹ค.


โœ…ย AppKit (macOS)

  • macOS ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ UI๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ

  • **์œˆ๋„์šฐ ๊ธฐ๋ฐ˜(NSWindow)**์œผ๋กœ ๋™์ž‘

  • UIKit๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ macOS์˜ ์ „ํ†ต์ ์ธ UI ํŒจํ„ด์„ ๋”ฐ๋ฆ„

  • ์ฝ”๋“œ ์˜ˆ์‹œ

    import Cocoa
    
    class ViewController: NSViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let button = NSButton(title: "ํด๋ฆญํ•˜์„ธ์š”", target: self, action: #selector(buttonTapped))
            button.frame = NSRect(x: 50, y: 150, width: 200, height: 50)
    
            view.addSubview(button)
        }
    
        @objc func buttonTapped() {
            print("๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์Šต๋‹ˆ๋‹ค!")
        }
    }
    
    

๐Ÿ‘‰ AppKit์—์„œ๋Š” NSButton ์„ ์‚ฌ์šฉํ•˜๊ณ  macOS์˜ UI ๊ตฌ์กฐ์— ๋งž๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.

๐Ÿ‘‰ UIKit๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ ์œˆ๋„์šฐ ๊ธฐ๋ฐ˜(NSWindow)์ด๋ผ๋Š” ์ ์ด ๋‹ค๋ฅด๋‹ค!


๐Ÿ“Œย ์• ํ”Œ ์ƒํƒœ๊ณ„ ํ†ตํ•ฉ UI ํ”„๋ ˆ์ž„์›Œํฌ SwiftUI

UIKit์™€ AppKit๋Š” ์„œ๋กœ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์• ํ”Œ ์•ฑ์ด๋ผ๋„ ํ”Œ๋žซํผ๋งˆ๋‹ค UI๋ฅผ ๋”ฐ๋กœ ๊ฐœ๋ฐœํ•ด์•ผ ํ•˜๋Š” ์†Œ์š”๊ฐ€ ๋ฐœ์ƒ์ด ๋˜์–ด ์• ํ”Œ์€ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด SwiftUI๋ฅผ ๋„์ž…ํ–ˆ๋‹ค.

๐ŸŽย SwiftUI์˜ ํŠน์ง•

  • ๋ชจ๋“  ์• ํ”Œ ํ”Œ๋žซํผ(iOS, macOS, watchOS, tvOS)์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ณตํ†ต UI ํ”„๋ ˆ์ž„์›Œํฌ

  • ์„ ์–ธํ˜•(Declarative UI) ๋ฐฉ์‹ ์‚ฌ์šฉ

  • ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด

  • ํ•˜์ง€๋งŒ ๐Ÿ’กย ๋ชจ๋“  UIKit ๊ธฐ๋Šฅ์„ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†๋‹ค! (UIKit & AppKit๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋จ)

  • ์ฝ”๋“œ ์˜ˆ์‹œ

    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
            Button("ํด๋ฆญํ•˜์„ธ์š”") {
                print("๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์Šต๋‹ˆ๋‹ค!")
            }
            .padding()
        }
    }
    
    

๐Ÿ‘‰ย UIKit๊ณผ AppKit ์—†์ด ํ•˜๋‚˜์˜ ์ฝ”๋“œ๋กœ iOS/macOS UI๋ฅผ ๊ฐœ๋ฐœ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ‘‰ UI๊ฐ€ ์ƒํƒœ(State)์— ๋”ฐ๋ผ ์ž๋™ ์—…๋ฐ์ดํŠธ๋œ๋‹ค.


๐Ÿ‘Šย UIKit vs AppKit vs SwiftUI ๋น„๊ต

UIKit (iOS/iPadOS)AppKit (macOS)SwiftUI (๊ณตํ†ต)
๊ฐœ๋ฐœ ๋Œ€์ƒiOS, iPadOSmacOSiOS, macOS, watchOS, tvOS
ํ”„๋ ˆ์ž„์›Œํฌ ๊ธฐ๋ฐ˜Cocoa TouchCocoaUIKit + AppKit์„ ํ†ตํ•ฉ
UI ๋ฐฉ์‹๋ช…๋ นํ˜• (Imperative)๋ช…๋ นํ˜• (Imperative)์„ ์–ธํ˜• (Declarative)
์ง€์› ๊ธฐ๊ธฐiPhone, iPadMaciPhone, iPad, Mac, Watch, TV
์ฝ”๋“œ ์Šคํƒ€์ผUIViewController ์‚ฌ์šฉNSViewController ์‚ฌ์šฉView ๊ตฌ์กฐ์ฒด ์‚ฌ์šฉ
๊ธฐ์—… ์‚ฌ์šฉ๋Œ€๋ถ€๋ถ„์˜ iOS ์•ฑ์—์„œ ์‚ฌ์šฉ๋Œ€๋ถ€๋ถ„์˜ macOS ์•ฑ์—์„œ ์‚ฌ์šฉ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ์—์„œ ์ ์ง„์  ๋„์ž…
์žฅ์ ๋” ์„ธ๋ฐ€ํ•œ UI ์ปจํŠธ๋กค ๊ฐ€๋ŠฅmacOS ์ „์šฉ UI ๊ธฐ๋Šฅ ์ œ๊ณต์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ ์‰ฌ์›€
๋‹จ์ ์ฝ”๋“œ๊ฐ€ ๋งŽ์•„์งˆ ์ˆ˜ ์žˆ์ŒUIKit๊ณผ UI ๊ตฌ์กฐ๊ฐ€ ๋‹ค๋ฆ„์ผ๋ถ€ UIKit ๊ธฐ๋Šฅ ๋ฏธ์ง€์›

๐Ÿคงย ํ•œ๋ˆˆ์— ์ •๋ฆฌํ•˜๊ธฐ

  1. Cocoa Touch (iOS)์™€ Cocoa (macOS)๊ฐ€ ์• ํ”Œ UI ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๊ธฐ๋ฐ˜
  2. UIKit์€ iOS & iPadOS์—์„œ UI๋ฅผ ๋‹ด๋‹น, AppKit์€ macOS์—์„œ UI๋ฅผ ๋‹ด๋‹น
  3. SwiftUI๋Š” ๋ชจ๋“  ์• ํ”Œ ๊ธฐ๊ธฐ์—์„œ UI๋ฅผ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๊ณตํ†ต ํ”„๋ ˆ์ž„์›Œํฌ
  4. UIKit๊ณผ AppKit์ด ์™„์ „ํžˆ ์‚ฌ๋ผ์ง€์ง„ ์•Š์œผ๋ฉฐ SwiftUI์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ

๋‹ค๋ฅธ ๊ณ„์ธต์€ ๋‚˜์ค‘์— ๊ณต๋ถ€ํ•ด์•ผ์ง€..