iOS - Swift

[iOS/Swift] Clean Architecture 의 이해

개발자 수니 2024. 5. 16. 17:02
728x90
반응형

Clean Architecture 의 이해

의존성 규칙

The Clean Architecture의 다이어그램

  • 원 : 소프트웨어의 각기 다른 영역
  • 외부에서 안쪽을 향해서만 의존한다. 내부에서 외부로는 종속성이 없다. ( -> 화살표가 의존성 규칙 )

 

Entities

  • Enterpise Business Rules : 대규모 프로젝트 레벨의 비즈니스 규칙 캡슐화, Application의 비즈니스 객체
  • 메서드를 갖는 객체, 데이터 구조, 함수의 집합
  • Application의 동작에 관한 변경(페이지 내비게이션의 변경이나 보안 사항)에 영향을 받지 않아야 한다.
  • 다른 계층의 어느 것도 포함하면 안된다.(의존성 규칙)
// iOS Clean Architecture MVVM Example 의 Entities
// GitHub: https://github.com/kudoleh/iOS-Clean-Architecture-MVVM
import Foundation

struct Movie: Equatable, Identifiable {
    typealias Identifier = String
    enum Genre {
        case adventure
        case scienceFiction
    }
    let id: Identifier
    let title: String?
    let genre: Genre?
    let posterPath: String?
    let overview: String?
    let releaseDate: Date?
}

 

Use Cases

  • Application Business Rules : Application 고유 비즈니스 규칙을 포함, 시스템의 모든 Use Cases를 캡슐화하고 구현
  • Entities 흐름을 조합
  • Use Cases의 변경이 Entities에 영향을 주지 않을 것을 기대하며 DataBase, UI 또는 공통 Framework의 변경으로부터 영향받지 않을 것을 기대한다. (의존성 규칙)
  • 하지만, Application의 조직에 대한 변경은 Use Cases 영향이 있다. Use Cases의 상세가 바뀐다면 이 계층의 코드는 확실히 영향을 받는다.
  • Entities를 제외한 다른 계층의 어느 것도 포함하면 안된다. (의존성 규칙)
// iOS Clean Architecture MVVM Example 의 Use Cases
// GitHub: https://github.com/kudoleh/iOS-Clean-Architecture-MVVM
import Foundation

protocol SearchMoviesUseCase {
    func execute(requestValue: SearchMoviesUseCaseRequestValue,
                 cached: @escaping (MoviesPage) -> Void,
                 completion: @escaping (Result<MoviesPage, Error>) -> Void) -> Cancellable?
}

final class DefaultSearchMoviesUseCase: SearchMoviesUseCase {

    private let moviesRepository: MoviesRepository
    private let moviesQueriesRepository: MoviesQueriesRepository

    init(moviesRepository: MoviesRepository,
         moviesQueriesRepository: MoviesQueriesRepository) {

        self.moviesRepository = moviesRepository
        self.moviesQueriesRepository = moviesQueriesRepository
    }

    func execute(requestValue: SearchMoviesUseCaseRequestValue,
                 cached: @escaping (MoviesPage) -> Void,
                 completion: @escaping (Result<MoviesPage, Error>) -> Void) -> Cancellable? {

        return moviesRepository.fetchMoviesList(query: requestValue.query,
                                                page: requestValue.page,
                                                cached: cached,
                                                completion: { result in

            if case .success = result {
                self.moviesQueriesRepository.saveRecentQuery(query: requestValue.query) { _ in }
            }

            completion(result)
        })
    }
}

 

Controllers, GateWays, Presenters

  • Interface Adapters
  • Data : Entities나 Use Cases에 용이한 형식 > 사용하고 있는 Frame Work(Datatbase, Web 등)에 용이한 형식으로 변환
  • 이 계층 내부(원 안)계층의 코드는 Database에 관해 아는 것이 없어야 한다. 

 

Devices, Web, UI, DB, External Interfaces

  • Frameworks & Driver
  • Frame Work 도구로 구성 : Database, Web 등
  • 내부(원 안)계층과 통신할 연결 코드 이외에는 별다른 코드를 작성하지 않는다.

 

Clean Architecture의 주의할 점

  • 원의 경계를 넘나드는 Data는 단순한 구조로 이루어지게 한다.
  • Entities와 Database Row을 그대로 전달하는 것은 의존성 규칙 위반이다. 안쪽의 원이 강제로 바깥쪽 원에 관한 것을 알아버리기 때문이다.
  • 경계를 넘나드는 Data는 항상 안쪽의 원이 다루기 쉬운 형식이어야 한다.

 

Clean Architecture의 핵심

  • 원의 가지수와 종류가 중요한 것이 아니다.
  • 의존 규칙이 가장 중요! : 소스 코드의 의존성은 항상 안쪽으로 향해야 한다.
  • 안쪽으로 향해감 : 추상회 수준은 올라간다. 캡슐화한다.
  • 가장 바깥쪽의 원 : 저수준의 구체적인 상세 정보를 담는다.

 

 

 By separating the software into layers, and conforming to The Dependency Rule, you will create a system that is intrinsically testable, with all the benefits that implies.
소프트웨어를 계층으로 나누고 의존성 규칙을 따름으로써 본질적으로 테스트하기 쉬운 시스템을 만들 수 있고 의존성 규칙이 가져오는 이점을 얻을 수 있다.

 

 

 

 

 

 

🙋🏻‍♀️ 참고

Github : iOS-Clean-Architecture-MVVM

The Clean Architecture

728x90
반응형