๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ“ฑ Mobile/iOS

iOS - MVC(Model-View-Controller) ํŒจํ„ด์ด๋ž€ ๋ฌด์—‡์ผ๊นŒ?

iOS ๊ฐœ๋ฐœ์—์„œ๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋””์ž์ธ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์„ ๊ด€๋ฆฌํ•˜๊ณ  ๊ตฌ์กฐํ™”ํ•œ๋‹ค. 

๊ทธ ์ค‘ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ด๋ฉฐ ๋Œ€ํ‘œ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” MVC ํŒจํ„ด์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋ ค๊ณ  ํ•œ๋‹ค. 

 

MVC (Model - View - Controller)

MVC๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ด๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค. ์•ฑ์˜ ๊ตฌ์„ฑ์„ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋‚˜๋ˆ„์–ด ์„ค๊ณ„ํ•œ๋‹ค. 

Model : ์•ฑ์˜ ๋ฐ์ดํ„ฐ์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๋‹นํ•œ๋‹ค. 

View : ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. 

Controller : ๋ชจ๋ธ๊ณผ ๋ทฐ์˜ ์‚ฌ์ด๋ฅผ ์ค‘์žฌํ•ด์ค€๋‹ค. ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. 

 

 

Model

์ฃผ๋กœ struct์™€ class๋ฅผ ๋งŒ๋“ ๋‹ค. ์•ฑ์ด ๊ฐ€์ง€๋Š” ๋ฐ์ดํ„ฐ๋“ค์„ ๋‹ด๋‹นํ•œ๋‹ค. 

์˜ˆ๋ฅผ ๋“ค์–ด, ์ „ํ™”๋ฒˆํ˜ธ๋ถ€์ด๋ฉด ์ด๋ฆ„, ์ „ํ™”๋ฒˆํ˜ธ, ์†Œ์† ๋“ฑ์„ ์ €์žฅํ•˜๊ณ  ์ด๋ฅผ model์—์„œ ์ •์˜ํ•˜๊ฒŒ ๋œ๋‹ค.

Todo List๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฝ”๋“œ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด๋ณด๊ฒ ๋‹ค.  

 

// ToDo List๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” Model
struct TodoItem {
    var title: String
    var isCompleted: Bool
}

 

 

 

 

View

์ฃผ๋กœ UIKit์„ ์ƒ์†ํ•œ๋‹ค. UIButton, UIViewController, UILabel์™€ ๊ฐ™์€ ๊ฒƒ์ด๊ณ  Controller์˜ ํ†ต์ œ๋ฅผ ๋ฐ›๊ฒŒ ๋œ๋‹ค. 

ํ™”๋ฉด์„ ๊ตฌ์ƒํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. 

์ฝ˜์†” ๊ธฐ๋ฐ˜์œผ๋กœ ์ฝ”๋“œ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด๋ณด๊ฒ ๋‹ค. 

 

// ์ฝ˜์†” ๊ธฐ๋ฐ˜์˜ View
class ConsoleView {
    func displayTodos(_ todos: [TodoItem]) {
        for (index, todo) in todos.enumerated() {
            print("\(index + 1). [\(todo.isCompleted ? "โœ…" : " ")] \(todo.title)")
        }
    }
    
    func askForNewTodoTitle() -> String? {
        print("Enter a new todo title: ", terminator: "")
        return readLine()
    }
    
    func askForTodoIndexToDelete() -> Int? {
        print("Enter the index of the todo to delete: ", terminator: "")
        if let input = readLine(), let index = Int(input) {
            return index
        }
        return nil
    }
}

 

displayTodos(_:) ๋ฉ”์„œ๋“œ๋Š” ToDo ํ•ญ๋ชฉ๋“ค์„ ์ถœ๋ ฅํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค€๋‹ค. 

askForNewTodoTitle() ๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ƒˆ๋กœ์šด ToDo ํ•ญ๋ชฉ์˜ ์ œ๋ชฉ์„ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค.

askForTodoIndexToDelete() ๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์‚ญ์ œํ•  ToDo ํ•ญ๋ชฉ์˜ ์ธ๋ฑ์Šค๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค.

 

 

 

 

Controller 

Model๊ณผ View ๋‘˜ ์‚ฌ์ด๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. 

Model์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ view์— ๋ณด์—ฌ์ฃผ๊ธฐ๋„ ํ•˜๋ฉฐ, ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€ํ•˜๋ฉด ์ด๋ฅผ view์— ๋‹ค์‹œ ์ ์šฉํ•˜๊ธฐ๋„ ํ•œ๋‹ค. 

view์—์„œ ์–ด๋– ํ•œ ์ผ์ด ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฅผ model์—๊ฒŒ ์ „๋‹ฌํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜๋„ ์žˆ๋‹ค. 

 

// Controller
class TodoListController {
    private var todos: [TodoItem] = []
    private let consoleView = ConsoleView()
    
    func start() {
        print("To-Do List App")
        while true {
            consoleView.displayTodos(todos)
            print()
            print("1. Add Todo  2. Delete Todo  3. Quit")
            if let choice = readLine() {
                switch choice {
                case "1":
                    addTodo()
                case "2":
                    deleteTodo()
                case "3":
                    exit(0)
                default:
                    print("Invalid choice. Please try again.")
                }
            }
            print()
        }
    }
    
    private func addTodo() {
        if let title = consoleView.askForNewTodoTitle() {
            let newTodo = TodoItem(title: title, isCompleted: false)
            todos.append(newTodo)
        }
    }
    
    private func deleteTodo() {
        if let index = consoleView.askForTodoIndexToDelete() {
            if index >= 0 && index < todos.count {
                todos.remove(at: index)
            } else {
                print("Invalid index. Please try again.")
            }
        }
    }
}

 

start() ๋ฉ”์„œ๋“œ๋Š” ์•ฑ์„ ์‹œ์ž‘ํ•˜๊ณ , ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, View๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์ฃผ์š” ๋กœ์ง์„ ๋‹ด๊ณ  ์žˆ๋‹ค. 

addTodo() ๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ƒˆ๋กœ์šด ToDo ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

deleteTodo() ๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์‚ญ์ œํ•  ToDo ํ•ญ๋ชฉ์˜ ์ธ๋ฑ์Šค๋ฅผ ์ž…๋ ฅ ๋ฐ›๊ณ , ํ•ด๋‹น ํ•ญ๋ชฉ์„ ์‚ญ์ œํ•˜๋Š” ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

 

 

 

 

๊ฐ„๋‹จ ์ •๋ฆฌ

Model์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ณ€๊ฒฝ์„ ์ถ”์ ํ•˜๋ฉฐ ๋ฐ์ดํ„ฐ์™€ ๊ด€๋ จ๋œ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. View์™€ Controller์™€ ์ง์ ‘์ ์œผ๋กœ ์ƒํ˜ธ์ž‘์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. 

 

View๋Š” ํ™”๋ฉด์„ ํ‘œ์‹œํ•˜๋ฉฐ model์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•˜๊ณ  Controller์—๊ฒŒ ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ์ „๋‹ฌํ•œ๋‹ค. ์ง์ ‘์ ์œผ๋กœ Model์— ๋Œ€ํ•œ ์ •๋ณด๋Š” ๋ฐ›์ง€ ๋ชปํ•˜๋ฉฐ Controller๋ฅผ ํ†ตํ•ด ๋ฐ›๋Š”๋‹ค. 

 

Controller๋Š” Model๊ณผ View ์‚ฌ์ด์—์„œ ์ค‘๊ฐœ์ž ์—ญํ• ์„ ํ•˜๊ณ  ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์•ก์…˜์— ๋ฐ˜์‘ํ•˜์—ฌ View์™€ Model์— ์—…๋ฐ์ดํŠธํ•œ๋‹ค. 

 

MVC ํŒจํ„ด์€ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ๊ฐ•๋ ฅํ•œ ๊ฒฐํ•ฉ์„ ํ”ผํ•˜๊ณ , ์•ฑ์„ ๋” ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•˜๊ณ  ํ™•์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ๋˜ํ•œ, ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ˆ˜์ •ํ•˜๋”๋ผ๋„ ๋‹ค๋ฅธ ๊ตฌ์„ฑ ์š”์†Œ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค. ์ด๋กœ ์ธํ•ด ์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•˜๋‹ค. 

 

728x90