본문 바로가기
Swift

Swift로 구현하는 Clean Architecture 예제

by mr.conan 2023. 7. 20.
728x90
반응형

Clean Architecture(클린 아키텍처)의 개념을 이해했다면, 이제 Swift를 활용하여 실제로 Clean Architecture를 적용하는 예제를 살펴보겠습니다.

Step 1: 프로젝트 설정과 기본 환경 구성

  1. Xcode를 열고 새로운 프로젝트를 생성합니다.
  2. "Single View App" 템플릿을 선택하고, 프로젝트 이름을 "CleanArchitectureExample"로 지정합니다.

Step 2: Clean Architecture 디렉토리 구조

  1. 프로젝트 내에 아래와 같이 Clean Architecture 디렉토리 구조를 만듭니다.
- CleanArchitectureExample
    - Entities
    - UseCases
    - InterfaceAdapters
        - Controllers
        - Presenters
    - FrameworksAndDrivers

 

 

Step 3: Entity 구현

  1. 프로젝트 내에 Todo.swift 파일을 생성합니다.
import Foundation

struct Todo {
    let id: UUID
    var title: String
    var isCompleted: Bool
}

 

 

Step 4: Use Case 구현

  1. 프로젝트 내에 TodoUseCase.swift 파일을 생성합니다.
import Foundation

protocol TodoUseCase {
    func fetchTodos() -> [Todo]
    func addTodo(title: String)
    func toggleCompletion(for todo: Todo)
}

class DefaultTodoUseCase: TodoUseCase {
    private var todos: [Todo] = []

    func fetchTodos() -> [Todo] {
        return todos
    }

    func addTodo(title: String) {
        let todo = Todo(id: UUID(), title: title, isCompleted: false)
        todos.append(todo)
    }

    func toggleCompletion(for todo: Todo) {
        if let index = todos.firstIndex(where: { $0.id == todo.id }) {
            todos[index].isCompleted.toggle()
        }
    }
}

 

 

Step 5: Interface Adapters 구현

  1. Controllers 디렉토리에 TodoViewController.swift 파일을 생성합니다.
import UIKit

class TodoViewController: UIViewController {
    private let todoUseCase: TodoUseCase

    init(todoUseCase: TodoUseCase) {
        self.todoUseCase = todoUseCase
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // View 구현은 생략합니다.
    }
}

 

 

Presenters 디렉토리에 TodoPresenter.swift 파일을 생성합니다.

import Foundation

protocol TodoPresentable {
    func presentTodos(_ todos: [Todo])
}

class TodoPresenter: TodoPresentable {
    private weak var viewController: TodoViewController?

    init(viewController: TodoViewController) {
        self.viewController = viewController
    }

    func presentTodos(_ todos: [Todo]) {
        // View에 Todo 리스트를 표시하는 로직을 작성합니다. (생략)
    }
}

 

 

Step 6: Frameworks & Drivers 구현

  1. FrameworksAndDrivers 디렉토리에 TodoFramework.swift 파일을 생성합니다.
import Foundation

class TodoFramework {
    static let shared = TodoFramework()

    private init() {}

    func makeTodoViewController() -> TodoViewController {
        let todoUseCase: TodoUseCase = DefaultTodoUseCase()
        let todoPresenter: TodoPresenter = TodoPresenter(viewController: viewController)
        let viewController = TodoViewController(todoUseCase: todoUseCase)
        viewController.presenter = todoPresenter
        return viewController
    }
}

 

 

Step 7: 앱 델리게이트 수정

  1. AppDelegate.swift 파일을 열고, didFinishLaunchingWithOptions 메서드를 아래와 같이 수정합니다
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        let viewController = TodoFramework.shared.makeTodoViewController()
        window?.rootViewController = viewController
        window?.makeKeyAndVisible()
        return true
    }
}

 

 

이제 Clean Architecture의 기본적인 구조를 갖춘 예제가 완성되었습니다. Entities, UseCases, InterfaceAdapters, 그리고 Frameworks & Drivers를 독립적으로 구성하여 각각의 책임을 명확히 할당하고, 결합도를 낮추었습니다. 이제 각각의 레이어를 개발하거나 테스트할 때 독립적으로 진행할 수 있게 되었습니다.

 

추가적으로 UI, 데이터베이스, 네트워크와 같은 외부 환경과의 결합을 InterfaceAdapters 레이어에서 관리하고, UseCase와 Entity는 순수한 비즈니스 로직에 집중할 수 있도록 설계했습니다. 이를 통해 유연하고 테스트 가능한 앱을 만들 수 있게 되었습니다.

이상으로, Swift를 활용하여 구현한 Clean Architecture 예제에 대해 설명드렸습니다. Clean Architecture의 장점을 최대한 활용하여 유지보수성과 확장성이 뛰어난 소프트웨어를 개발할 수 있기를 바랍니다.

728x90
반응형