[Kotlin] MVP, MVVM, 클린 아키텍쳐

신민준·2024년 11월 21일
1

아키텍처 패턴이란

아키텍처 패턴은 소프트웨어 시스템의 구성 요소와 그 요소들 간의 관계를 정의하는 설계 원칙으로 소프트웨어의 구조와 동작을 정의하기 위한 고수준의 설계 청사진이다.

아키텍처 패턴 장점

  • 코드 재사용성 증가
    - 이미 검증된 패턴을 사용하여 새로운 시스템을 개발할 때 시간과 비용을 절약할 수 있고 잘 정의된 컴포넌트는 재사용 가능성을 높인다.
  • 코드 가독성 향상
    - 표준화된 구조를 제공하여 다른 개발자도 쉽게 이해할 수 있어 협업을 용이하게 한다.
  • 개발 속도 향상
    - 설계 표준화로 인해 팀이 설계 방식을 빠르게 이해하고 개발에 착수할 수 있다.
  • 확장성 향상
    - 모듈 간 결합도가 낮아 시스템의 기능을 추가하거나 변경하는 것이 용이하게 설계되어 시스템의 수명을 연장시킨다.

아키텍처 패턴의 단점

  • 남용의 위험
    - 간단한 문제에 대해서도 아키텍처 패턴을 적용하려는 것은 오히려 시스템을 복잡하게 만들 수 있다.
  • 특정 패턴에 너무 의존하게 되면 오히려 아키텍처 패턴의 장점인 유연성을 저하시킬 수 있다.
  • 초기 비용
    - 아키텍처 설계 및 패턴 적용에 시간과 노력이 필요하고 팀원들이 해당 패턴에 대한 이해가 있어야 한다.

-> 단점이 기술적인 부분이 아닌 단순 사용자의 역량에 달려있다는 점에서 디자인 패턴의 유의미한 단점이 없다고 생각한다.

디자인 패턴과 아키텍처 패턴의 차이점

아키텍처 패턴은 시스템의 전체적인 설계를 담당하고, 디자인 패턴은 코드의 세부적인 구현을 담당한다.

구분아키텍처 패턴디자인 패턴
수준시스템 전체코드의 특정 부분
목적시스템 구조 정의코드 품질 향상
예시MVC, MVP, MVVMSingleton, Observer, Adatper

MVP


MVP 패턴은 Model, View, Presenter로 구성된 아키텍처 패턴으로 MVC 패턴에서 Controller 대신 Presenter가 존재한다.

구성요소

View : 사용자 인터페이스를 담당. 사용자와 직접 상호작용하는 부분이며, 사용자 입력을 받고 결과를 표시
Model : 애플리케이션의 데이터를 표현하고, 데이터 처리 로직을 담당. 비즈니스 로직을 담당하는 부분
Presenter : ModelView 사이의 중개자 역할. 사용자의 입력을 받아 Model에 전달하고, Model에서 처리된 결과를 View에 전달. ViewModel 사이의 의존성을 줄여 테스트를 용이하게 만들고, 비즈니스 로직을 View로부터 분리.

MVC와의 차이점

MVC 패턴과의 차이점은 MVC 패턴에서는 View에서 Model을 직접 control할 수 있었지만 MVP 패턴에서는 View가 직접 Model을 Control할 수 없어 ViewModel 서로 의존하지 않게 되었으나 여전히 ViewPresenter 사이의 강한 의존성이 존재한다.

작동 방식

  1. 사용자 이벤트 발생: 사용자가 View에 있는 버튼을 클릭하거나 입력을 하는 등의 이벤트 발생
  2. View에서 Presenter로 전달: 발생한 이벤트는 View에서 Presenter로 전달
  3. Presenter에서 Model 처리: Presenter는 전달받은 이벤트에 따라 Model에 필요한 작업을 요청
  4. Model 처리 결과: Model은 요청된 작업을 수행하고 결과를 Presenter에게 반환
  5. Presenter에서 View 업데이트: PresenterModel에서 받은 결과를 바탕으로 View를 업데이트

MVP 패턴의 장점

  • UI와 비즈니스 로직의 분리
    - ViewModel 간 결합도가 낮아 각 컴포넌트를 독립적으로 변경하거나 테스트 가능
  • 테스트 용이성
    - Presenter가 UI와 독립적이기 때문에 View를 대체하여 비즈니스 로직을 단위 테스트하기가 쉬움.
  • 유지보수성 향상
    - UI 로직(View)과 애플리케이션 로직(Model)을 명확히 분리하여 코드를 쉽게 이해하고 수정 가능
  • 재사용성 증가
    - PresenterModelView와 독립적이기에 다른 View에서 동일한 PresenteModel 재사용 가능
  • 확장성
    - 새로운 기능을 추가할 때 기존 코드를 최소한으로 수정하며 확장 가능

MVP 패턴이 적합한 경우

  • UI 로직이 복잡하고, 유지보수성이 중요한 프로젝트
  • 다양한 UI와 복잡한 사용자 상호작용을 처리해야 하는 경우
  • 단위 테스트를 통해 비즈니스 로직의 안정성을 보장하려는 경우

MVVM

MVVM 패턴은 UI와 비즈니스 로직을 분리하여 애플리케이션의 유지보수성, 테스트 용이성, 확장성을 높이는 높이기 위해 설계된 아키텍처 패턴이다.
특히, 데이터 바인딩을 활용하여 UI와 데이터를 연결하는 방식으로 사용자 인터페이스 개발 생산성을 향상시키는 데 중점을 두고 있다.

구성요소

View : 사용자 인터페이스를 담당. 사용자와 직접 상호작용하는 부분이며, 사용자 입력을 받고 결과를 표시
Model : 애플리케이션의 데이터를 표현하고, 데이터 처리 로직을 담당. 비즈니스 로직을 담당하는 부분
ViewModel : ViewModel 사이의 중개자 역할. View에 노출될 데이터 관리. 사용자의 입력을 Model에 전달. Model에서 처리된 결과를 View에 반영. 데이터 바인딩을 통해 ViewViewModel 사이의 데이터를 자동으로 동기화.

MVP와의 차이점

MVP 패턴은 ViewPresenter가 일대일 관계라면 MVVM은 ViewViewModel간의 관계가 1대 N으로 하나의 ViewModel을 다양한 View에 사용할 수 있다.
또한 ViewModelPresenter에 비해 상대적으로 View와 느슨하게 결합되어 있다.

ViewModelView에 표시될 데이터를 준비하고 사용자 입력을 처리하여 Model에 전달하는 역할을 수행하고 View의 구체적인 구현에 대한 지식이 필요하지 않다.
그에 비해 PresenterView의 상태를 관리하고 사용자 입력을 처리하는 등 다양한 책임을 수행하여 View에 대한 의존도가 높다.

작동방식

  1. 사용자 이벤트 발생: 사용자가 View에 있는 버튼을 클릭하거나 입력하는 등의 이벤트가 발생
  2. View에서 ViewModel로 전달: 발생한 이벤트는 View에서ViewModel로 전달
  3. ViewModel에서 Model 처리: ViewModel은 전달받은 이벤트에 따라 Model에 필요한 작업 요청
  4. Model 처리 결과: Model은 요청된 작업을 수행하고 결과를 ViewModel에게 반환
  5. ViewModel에서 View 업데이트: ViewModelModel에서 받은 결과를 바탕으로 ViewModel의 속성을 업데이트하고 데이터 바인딩을 통해 View가 자동으로 업데이트됨

MVVM 패턴의 장점

  • 데이터 바인딩
    - 데이터 바인딩을 통해 UI와 데이터를 자동으로 동기화하여 개발 생산성을 높임
  • 테스트 용이성
    - ViewModel을 독립적으로 테스트할 수 있어 테스트 커버리지를 높이고 버그 조기 발견 가능
  • 유지보수성
    - 각 구성 요소의 역할이 명확하게 분리되어 있어 코드의 변경 용이. 시스템의 유지보수 쉬움
  • 확장성
    - 새로운 기능을 추가하거나 기존 기능을 변경할 때 다른 구성 요소에 미치는 영향 최소화 가능
  • UI와 비즈니스 로직 분리
    - UI와 비즈니스 로직을 분리하여 각각 독립적으로 개발하고 테스트 가능

MVVM 패턴이 적합한 경우

  • 복잡한 UI와 상태 관리를 요구하는 애플리케이션
  • ViewModel과 데이터 바인딩 라이브러리를 활용하여 실시간 데이터 업데이트가 필요한 경우
  • 테스트 가능하고 유지보수하기 쉬운 아키텍처가 중요한 프로젝트
  • 확장성과 재사용성이 중요한 중대형 프로젝트

클린 아키텍처


클린 아키텍처는 외부 프레임워크나 UI, 데이터베이스 등의 변화에 유연하게 대응할 수 있도록 시스템의 내부와 외부를 명확하게 분리하는 것을 목표로 하는 아키텍처 패턴이다.

클린 아키텍처는 시스템의 구성을 4가지로 나눈다. 먼저 각 구성에 대해 알아보면

시스템의 구성

  • 엔티티(Entities)
    - 핵심 비즈니스 로직을 캡슐화
    - 메서드를 가지는 객체, 일련의 데이터 구조와 함수의 집합
    - 가장 변하지 않으며 외부로부터 영향을 받지 않는 영역
    ex) 사용자, 상품, 주문 등 실제 세계의 개념을 모델링한 객체
  • 유즈 케이스(Use Cases)
    - 애플리케이션의 특화된 비즈니스 로직을 포함한다.
    - 시스템의 모든 유즈 케이스를 캡슐화하고 구현한다.
    - 엔티티로 들어오고 나가는 데이터 흐름을 조정하고 조작한다.
    - 사용자가 시스템에 요구하는 기능을 구현하는 부분
    ex) 사용자 등록, 상품 조회, 주문 생성 등
  • 인터페이스 어댑터(Interface Adapter)
    - 일련의 어댑터들로 구성한다.
    - 외부 인터페이스에서 들어오는 데이터를 유즈 케이스와 엔티티에서 처리하기 편한 방식으로 변환하며, 유즈 케이스와 엔티티에서 나가는 데이터를 외부 인터페이스에서 처리하기 편한 방식으로 변환
    ex) 컨트롤러, 프레젠터, 게이트웨이 등
  • 프레임워크와 드라이버(Frameworks & Drivers)
    - 시스템을 실행하기 위한 환경을 제공
    - 시스템의 핵심 업무와는 관련 없는 세부 사항
    ex) 프레임워크나, 데이터베이스, 웹 서버 등

소프트웨어 아키텍처는 선을 긋는 기술이며, 나는 이러한 선을 경계(boundary)라고 부른다.
경계는 소프트웨어 요소를 서로 분리하고, 경계 한편에 있는 요소가 반대편에 있는 요소을 알지 못하도록 막는다. - Robert C. Martin, Clean Architecture

Android에서의 적용

프리젠테이션 계층(Presentation Layer)

  • 사용자와 직접 상호작용하는 계층으로 UI를 구성하고, 사용자의 입력을 받아 도메인 계층으로 전달

View, UI: 직접적으로 플랫폼 의존적인 구현으로 UI 화면 표시와 사용자 입력 담당
Presenter가 명령하는 일만 수행
Presenter: ViewModel과 유사한 역할, 사용자 입력이 왔을 때 어떤 반응을 해야 하는지에 대한 판단을 하는 영역으로 View가 단순히 명령만 수행하도록 함

도메인 계층(Domain Layer)

  • 앱의 핵심 비즈니스 로직과 규칙이 포함된 계층으로 프레젠테이션 계층이나 데이터 계층과 독립적

Use Case: 비즈니스 로직이 들어 있는 영역
Entity: 앱의 실질적인 데이터

데이터 계층(Data Layer)

  • 애플리케이션의 데이터 관리 및 영속성을 담당
  • 외부 데이터 소스(API, 데이터베이스 등)와 상호작용하며, 도메인 계층에서 요구하는 데이터를 제공

Repository: 유즈 케이스가 필요로 하는 데이터의 저장 및 수정 등의 기능을 제공하는 영역으로 데이터 소스를 인터페이스로 참조하여, 로컬 DB와 네트워크 통신을 자유롭게 가능
Data Source: 실제 데이터의 입출력이 실행되는 영역

상위 계층은 기본적으로 하위 계층을 참고하지만 실제로 도메인 계층은 데이터 계층을 참고하고 있지 않다.
-> 리포지터리에서 이루어지는 의존성 역전 법칙 때문

의존성 역전이란?
객체 지향 프로그래밍에서 의존 관계 역전 원칙은 소프트웨어 모듈들을 분리하는 특정 형식을 지칭한다. 이 원칙을 따르면, 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존 관계를 반전(역전)시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있다.
https://meetup.nhncloud.com/posts/345

클린 아키텍처의 장점

  • 유지보수성 증가
    -비즈니스 로직과 구현 세부사항이 분리되어, 한 계층의 변경이 다른 계층에 영향을 최소화
    -> 데이터베이스를 변경해도 유스케이스와 엔티티는 영향을 받지 않음.
  • 확장성 향상
    - 새로운 기능이나 기술 스택을 추가하거나 교체하는 것이 용이
  • 테스트 용이성
    - 비즈니스 로직이 UI나 데이터베이스와 독립적이므로, 테스트가 쉽고 빠름
    - 단위 테스트 작성 시 Mocking을 통해 외부 의존성을 최소화
  • 재사용성 증가
    - 엔티티와 유스케이스는 특정 애플리케이션에 종속되지 않으므로, 여러 프로젝트에서 재사용 가능
  • 기술 독립성
    - 특정 프레임워크나 도구에 종속되지 않으므로, 기술 스택 변경이 자유로움

클린 아키텍처의 단점

  • 초기 설계 비용이 높고 숙련된 개발자가 아니라면 구조를 이해하고 적용하는 데 시간이 필요하다.

참고자료

https://doosicee.tistory.com/entry/Architecture-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80
https://velog.io/@kyeun95/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-MVP-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80
https://velog.io/@kyeun95/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-MVVM-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80
https://velog.io/@toma/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%B0%A8%EC%9D%B4%EC%A0%90
https://meetup.nhncloud.com/posts/345
https://medium.com/@justfaceit/clean-architecture%EB%8A%94-%EB%AA%A8%EB%B0%94%EC%9D%BC-%EA%B0%9C%EB%B0%9C%EC%9D%84-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%84%EC%99%80%EC%A3%BC%EB%8A%94%EA%B0%80-1-%EA%B2%BD%EA%B3%84%EC%84%A0-%EA%B3%84%EC%B8%B5%EC%9D%84-%EC%A0%95%EC%9D%98%ED%95%B4%EC%A4%80%EB%8B%A4-b77496744616

용어 정리

  • 비즈니스 로직 : 컴퓨터 프로그램에서 실세계의 규칙에 따라 데이터를 생성·표시·저장·변경하는 부분
  • ViewModel에서의 데이터바인딩 : ViewModel에 있는 데이터가 변경되면 이 변경 사항이 자동으로 View에 반영되고, 반대로 View에서 사용자가 입력한 데이터가 ViewModel에 자동으로 반영되는 것
  • 테스트 커버리지 : 시스템 및 소프트웨어에 대해 충분히 테스트가 되었는지를 나타내는 정도
  • DTO(Data Transfer Object, 데이터 전송 객체) : 프로세스 간에 데이터를 전달하는 객체
  • 의존성 역전
    - 의존성 역전 원칙은 객체지향 프로그래밍에서 고수준 모듈이 저수준 모듈의 구체적인 구현에 의존하지 않고, 추상적인 인터페이스에 의존하도록 설계하는 원칙입니다. 쉽게 말해, 상위 계층이 하위 계층에 의존하는 것이 아니라, 둘 다 추상적인 개념에 의존하도록 만드는 것입니다.
  • 왜 의존성 역전을 하는가?
    유연성 증가: 시스템의 특정 부분을 변경해야 할 때, 다른 부분에 미치는 영향을 최소화할 수 있습니다.
    테스트 용이성 향상: 의존성이 적은 모듈은 독립적으로 테스트하기 쉽습니다.
    재사용성 증가: 추상적인 인터페이스에 의존하기 때문에, 다양한 구체적인 구현체와 함께 사용할 수 있습니다.
    확장성 증가: 새로운 기능을 추가하거나 기존 기능을 변경하기 쉽습니다.
profile
안드로이드 외길

2개의 댓글

comment-user-thumbnail
2024년 11월 23일

왜 이렇게 GPT가 작성한 것 같죠

1개의 답글