핀수로그
  • Clean Architecture를 이해하기 위해 알아보는 SOLID 원칙
    2023년 03월 07일 14시 44분 16초에 업로드 된 글입니다.
    작성자: 핀수
    728x90
    반응형
     

    들어가며

    Clean Architecture와 함께 등장하는 MVP, MVVM 패턴

    나는 이전에 MVVM 패턴을 적용하면 클린 아키텍처를 구현한 것이라고 착각했었다.

    클린 아키텍처 == MVVM 패턴 이렇게 생각했다는 의미다.

    그리고 앱을 만들어서 그냥 돌아가기만 하면 되는데 왜 굳이 초기 비용을 들여가면서

    좋은 설계를 해야만 하는가에 대한 이유를 찾아다녔다.

    그런데 생각해보면 이는 당연하다. 다들 내진 설계 잘된 집에서 살고 싶겠지?

    냅다 빨리 지은 건물에서 살고 싶겠냐구... 무슨 일이 생길 줄 알고 ㅋㅋ

     

    각설하고, MVP, MVVM 패턴들은 클린 아키텍처 구현을 구현하는 방법 중 하나이지 그 자체로 클린 아키텍처라고 볼 수 없다.

    클린 아키텍처를 이해하기 위해 필수로 선행되어야 하는 SOLID 원칙에 대해 알아볼 것이다.

    *SOLID 원칙은 객체 지향 설계 원칙으로 개발을 입문하거나, 정보처리기사 시험을 준비했다면 들어본 적 있을 것이다.

    SOLID 원칙

    • 기본적으로 중간 규모(모듈)에 대한 원칙임을 기억하면 이해하기 더 쉽다.
    • 중간 규모의 소프트웨어 구조가 아래와 같은 요구를 만족하도록 하는 것이 목표
      • 유지보수성 : 변경에 유연해야 함
      • 가독성 : 이해하기 쉬워야 함
      • 낮은 결합도, 높은 응집도 : 여러 소프트웨어 시스템에 사용될 수 있는 큰 컴포넌트의 기반이 되어야 함
    • 클래스 단위에서도 유용하게 사용된다.

    단일 책임 원칙 Single Responsibility Principle

    • 1974년 다익스트라에 의해 제안된 개념인 관심사 분리의 다른 표현
    • 응집도에 대한 기준
    • 각 소프트웨어 모듈은 변경의 이유가 단 하나여야만 한다. == 하나의 모듈은 오직 하나의 액터에 대해서만 책임져야 한다.
    • 하나의 클래스가 하나의 일만 해야하는 것을 의미하는 것이 아니다. (메소드는 그래야 한다.)

    예시

    class Image {
        private val buffer: Buffer
        fun loadFromServer()
        fun drawToScreen()
        fun cropByShape()
    }

    Image 라는 클래스가 있다.

    이 클래스는 단일 책임 원칙에 의하면 잘못된 설계로 볼 수 있다.

    무엇때문일까?

     

    그냥 보면 ‘이미지를 가지고 할 수 있는 어떠한 행위’ 로 보여지기 때문에 잘된 설계로 착각할 수 있다.

    그러나 하나씩 짚어본다면

     

    loadFromServer 메소드의 주체는 누구인가? 이미지가 서버에서 이미지를 로드하나?

    drawToScreen 메소드의 주체는 누구인가? 이미지가 화면에 이미지를 그리나?

    cropByShape 메소드의 주체는 누구인가? 이미지가 어떠한 모양으로 이미지를 자르나?

     

    Usecase 다이어그램에서 사용자 또는 주체와 상호작용하는 다른 시스템이 수행하는 역할을 액터라고 하는데,

    위의 메소드는 서로 다른 액터를 책임지고 있다. ⇒ 단일 책임 원칙에 위배된다.

    세 메소드에서 이미지는 주어가 아닌 목적어를 담당한다.

     

    이를 해결하기 위해서는 세개의 클래스로 분리하면 된다.

    하지만 그러면 사용성을 떨어트릴 수도 있으므로 Facade 패턴을 통해 해결한다.

    *Facade Pattern

    어떤 소프트웨어의 다른 커다란 코드 부분에 대하여 간략화된 인터페이스를 제공해주는 디자인 패턴

    참고 : https://lktprogrammer.tistory.com/42

    개방-폐쇄 원칙 Open Close Principle

    • 1988년 버트란트 마이어에 의해 제안되었다.
    • 소프트웨어 모듈은 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.
      • 의미있는 정보만 열어주어야 한다.
    • 데이터 구조에 필드를 추가하거나, 함수에 새로운 요소를 추가하는 것이 가능해야한다.
    • 내부 코드를 변경해도 이를 사용하는 외부 모듈에는 영향을 미쳐선 안된다.

    리스코프 치환 원칙 Liskov Subsititution Principle

    • 1988년 바바라 리스코프에 의해 제안되었다.
    • 대체 가능한 컴포넌트들을 이용해 시스템을 만들 수 있으려면, 이들의 서브타입들은 반드시 서로 치환 가능해야 한다.

    예시

    Repository가 DataSource의 자식들 중 어떤 것을 사용해도 동일한 역할을 한다.

    → 부모가 정한 행위의 원칙을 자식에서 그대로 지키고 있기 때문에 행위 상속이라고도 부른다.

    상속보다 조합 Composition over inheritance

    어떤 부가적인 개념이 있을 때, 상속을 통해 처리하기 보다는 멤버변수처럼 가지고 있으면

    이후 예기치 못한 확장에 일어났을 때도 멤버변수를 추가하거나 변경하는 형태로 다른 영향을 끼치지 않도록 할 수 있다.

    • 상속으로 인한 부작용을 방지한다.
      • 자식은 부모가 가지고 있는 행위를 정확히 이해하고, 이 행위를 깨지지 않도록 해야한다.

    인터페이스 분리 원칙 Interface Segregation Principle

    • 각 소프트웨어 모듈은 자신이 사용하는 것에 의존하지 않아야 한다.
    • → 자신이 사용하는 것에만 의존해야 한다.

    왜 인터페이스가 필요한가?

    • 추이 종속성을 막기 위함이다. (A가 B를 의존하고, B가 C를 의존한다면 A도 C를 의존하게 되는 것)
    • 의도하지 않은 종속성이 생기지 않도록 하기 위해

    의존성 역전 원칙 Dependency Inversion Principle

    • 높은 수준의 코드는 낮은 수준의 세부사항 구현에 절대로 의존해서는 안되며, 그 반대여야 한다.

    References

    아래 글을 참고하여 작성 되었습니다.

     

    패스트캠퍼스 온라인 강의 - The RED : 강사룡의 앱 안정성 및 확장성 강화를 위한 Android 아키텍처

     

    fastcampus.co.kr

     

    728x90
    반응형

    'Android' 카테고리의 다른 글

    GPS 보정하기 - 03  (0) 2023.11.22
    GPS 보정하기 - 02  (0) 2023.11.20
    GPS 보정하기 - 01  (0) 2023.11.02
    GPS 보정하기 - 프롤로그  (0) 2023.11.01
    [Android] Hilt와 Room  (0) 2023.09.29
    댓글