[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🍎 Apple/Patterns

Clean Architecture and Design - Robert C. Martin (엉클 밥)

inu 2022. 1. 21. 15:54
반응형

해당 게시글은 Robert C. Martin님의 Clean Architecture and Design 강의를 보고 내용을 정리한 게시글입니다.

 

다만 개인적인 정리 및 확인의 용도로 작성한 게시글이기 때문에 가독성이 떨어집니다.

관심 있는 분들은 직접 영상을 감상하시는 것을 추천드립니다.

 

한글자막도 있고 길이도 1시간 정도밖에 되지 않아요. 아직 안 보신 분은 꼭 보세요!!!

https://amara.org/ko/videos/0AtjY87egE3m/url/1216370/

 

Video Subtitling, Captioning and Subtitle Translation - Amara Subtitling

The FCCChairman's AAA The Chairman's Awards for Advancement in Accessibility is an FCC program recognizing products, services, standards and other innovative developments that improve the experience of people with disabilities.

amara.org


아키텍처는 의도를 가진다

  • 아키텍처는 의도를 표현하는 것이다. (도서관 교회건물의 구조도를 보면 그 건물이 무엇을 하는지 알 수 있듯이)

  • Interactor : 비즈니스 룰에 따라 유즈케이스를 구현하고 입력값을 받아 처리한 뒤 출력 값을 출력한다.
  • Entity : 어플리케이션 비종속적인 비즈니스 룰들이 담겨있다.
  • Interactor는 입력 인터페이스와 출력 인터페이스가 존재하는데 (화살표) 입력 인터페이스는 직접 구현하고 있고 출력 인터페이스는 다른 곳에서 구현된 것을 사용하고 있다.
  • 두 인터페이스와 Interactor의 화살표 방향이 같은데, 이는 중요한 포인트이다. (추후 언급되지만 이렇게 해야 애플리케이션의 독립성이 생기기 때문)
  • 사용자가 입력을 통해 Request Model이라는 순수한 데이터구조를 Interactor에게 보내면 Interactor는 이를 해석한다.
  • 그리고 이를 Entity에 보내서 적절한 처리를 하도록 한다.
  • 그 후 Interactor는 다시 Entity를 조회해서 변경사항을 확인하고 Result Model이라는 또 다른 순수한 데이터 구조를 만들어 출력 인터페이스를 통해 유저에게 전달된다.
  • Interactor에 대한 테스트를 수행하고 싶다면, 임의의 입력 데이터자료를 생성해서 Interactor를 호출하고 출력 데이터를 확인하기만 하면 된다. 다른 부분은 안 봐도 된다. 웹서버고 뭐고 그냥 필요 없는 것이다.

MVC

  • Controller는 특정한 방법으로 사용자의 입력을 전달한다.
  • Model은 비즈니스 룰을 담당한다. Model은 자신이 어떻게 보여질지 모르고 입력이 어디서 오는지도 모른다.
  • View는 Model을 관찰하다가 변경되면 View가 변경되도록하는 역할을 담당한다. Model의 콘텐츠를 표시하거나 전달하는 것이다.
  • MVC는 GUI 환경에 적합하며, 원래는 작은 것에 사용하는게 목적이었다. (버튼, 체크박스, 텍스트 필드 등)
  • 스크린 같은 큰 장치에는 사용하지 않았다.
  • 하지만 세월이 흐르면서 MVC는 비틀어지고 변형되었다. 모방되면서 완전히 다른 것에 같은 이름을 붙이고 그 역시 좋을 것이라고 주장했다. (객체지향, 구조, 애자일 등도 다 그랬다)
  • 요즘 MVC 프레임워크가 많은데 초기에 제시된 트릭 뷔 린 스카욱의 MVC랑은 다른 것이다.

  • 요즘엔 이런식으로 생겼다.
  • WEB(Rails, Spring or Anything)은 복잡하고 끔찍한 URL을 어떻게든 Controller에게 전달한다.
  • Controller는 비즈니스 오브젝트들에게 일을 하라고 소리를 친다. (...)
  • 그리고 비즈니스 오브젝트들로부터 데이터를 모아서 View에게 알려주면 View는 비즈니스 오브젝트들에게서 데이터를 조회하고 표시한다.
  • 이때 여러 function들이 필요해지는데 적절한 위치를 찾지 못해 결국 비즈니스 오브젝트 자체에 function들이 생기면서 오염된다

Presenter

  • Interactor는 내재된 유즈케이스를 마치고 entity의 데이터를 조회한 상황이다.
  • 이제 Response Model을 생성해 출력 인터페이스를 통해 전달해야 한다.
  • 출력 인페이스를 사용하는 것은 Interactor지만 구현하는 것은 Presenter이다.
  • Presenter는 순수데이터 구조인 Response Model을 받아서 ViewModel이라는 또 다른 순수 데이터 구조로 변형시킨다.
  • ViewModel은 출력값을 표현하는 순수한 데이터 구조이다.
  • 화면에 텍스트 필드가 있으면 ViewModel도 텍스트필드가 있고, 소수점 이하 두 자리만 표현하겠다면 TrimToTwoDecimalPlaces와 ConvertIntToString과 같은 메서드가 존재함. 음수를 괄호로 표현하고 있다면 Presenter가 데이터에 괄호를 붙여서 ViewModel에 저장한 것이다. 비활성화된 메뉴 아이템은 회색으로 보여야 한다면 불린 값이 존재할 것이다.
  • 화면에 표시되는 모든 것이 ViewModel에 저장된다. (물론 추상화된 방식으로)
  • View는 그냥 ViewModel로부터 데이터를 가져올 뿐이고 아무것도 처리하지 않는다. 일반적으로는 테스트도 잘하지 않는다. (어차피 보이기 때문에)
  • Presenter는 테스트할까? 가능하다. 그저 데이터를 받아서 처리하는 게 다이기 때문이다.
  • 우리의 목표가 이것이다. 다른 것을 실행하지 않고도 가능한 많은 것이 독립적으로 테스트 가능하도록 하는 것.

  • 이게 전체적인 그림이다.
  • Interactor는 입력 인터페이스를 통해 들어온 Request Model에서 데이터를 읽은 다음, Response Model에 데이터를 저장하고 출력 인터페이스를 통해 Presenter에게 전달한다.
  • 검은색은 애플리케이션과 전달 메커니즘을 구분하는 선이다.
  • 검은색을 지나는 모든 화살표가 애플리케이션을 향한다. 이를 통해 어플케이션은 Controller나 Presenter에 대한 정보가 하나도 없음을 알 수 있다.
  • 외부의 세계는 그냥 플러그인 정도로 생각하면 된다.
  • 플러그인 개발자는 IDE 개발자를 알지만, IDE 개발자는 플러그인 개발자에 대해 모른다.
  • 누가 상대방에 피해를 줄 수 있을까? 플러그인(JetBrain) 개발자가 아무리 IDE(Visual Studio)를 해치려고 해도 IDE 개발자는 그것을 신경 쓸 필요도 없다.
  • 다른 무엇보다 비즈니스 룰을 바깥쪽으로부터 보호하는 게 중요한 것이다. I/O 메커니즘이 비즈니스 룰에는 관여할 수 없도록 해야 한다.

About Database

  • 이게 올바른 형태일까? 데이터베이스가 서비스의 중심이고 애플리케이션은 곁가지일까?
  • 아니다. 데이터베이스는 디테일이고 아키텍처적으로는 큰 의미가 없다.
  • 데이터베이스는 그냥 저장소이다. 아키텍처와도 비즈니스 룰과도 연관이 전혀 없다.
  • Stored Procedure에 비즈니스 룰이 존재하는 것은 잘못된 것이다. 그곳에는 쿼리, 무결성 검증 같은 것을 넣어야 한다.

  • 앞서 말한 방식과 똑같은 방식으로 애플리케이션을 데이터베이스로부터 보호할 수 있음
  • 중간에 존재하는 검은 선을 보면 해당 선을 지나는 모든 선이 애플리케이션 쪽을 향하고 있다
  • 데이터베이스를 애플리케이션의 플러그인처럼 만든 것이다.
  • 이제 데이터베이스를 오라클, MySQL, CouchDB 등등 맘대로 교체할 수 있다. (실제로 안 바꿔도 바꿀 수 있다는 게 좋은 거임)
  • Entity Gateway라는 인터페이스를 두었다. Entity Gateway의 메서드는 쿼리 메서드이다.
  • Entity Gateway의 구현부는 검은 선 아래에 위치한다.
  • Entity Gateway는 데이터를 모아 엔티티 오브젝트 형태로 저장한다. 검은 선을 넘어오면서 애플리케이션 입장에서 엔티티 오브젝트가 되는 것이다.
  • ORM 툴이 있다면 어디 있을까? 검은선 아래에 있다.
  • 절대 애플리케이션 영역이 데이터베이스들과 연관되어선 안된다.
  • 오브젝트란 퍼블릭 메서드의 집합이다. 그 외에는 알려져선 안된다. 그 안에 데이터가 있을 수도 있지만 모두 private이고 외부에선 알 필요가 없다.
  • 우리 관점에서는 오브젝트는 그냥 메서드 덩어리이다. 데이터 덩어리가 아니다.
  • 오브젝트는 행위에 대한 내용 정도로 보아야 한다. 오브젝트는 비즈니스 룰에 대한 내용이어야 한다. 데이터가 아니다.
  • Data Structure란 잘 알려진 데이터 요소고 누구에게나 공개된다. 메서드가 없다.
  • 오브젝트와 데이터 구조체는 완전 다른 것이다. 데이터 구조체는 공개된 데이터를 가지고 메서드가 없지만, 오브젝트는 메서드를 가지고 공개된 데이터가 없다.
  • ORM은 틀린 말이다. 오브젝트와 관계형 데이터는 매칭 할 수 없다. 왜냐면 데이터베이스에서 나온 것은 데이터 구조체이기 떄문이다. 데이터 구조체는 오브젝트에 매칭할 수가 없다. 정말 다른 것이기 때문이다.
  • 엔티티에 저장되는 데이터는 어딘가 알 수 없는 곳에서 제공되어야 한다. 어떻게 전달되는지도 중요하지 않다.

About Framework

  • 프레임워크는 물론 좋다. 특히 개발 시간을 크게 줄여준다.
  • 하지만 프레임워크는 우리가 프레임워크에 종속되도록 만듦. 베이스 클래스를 만들어서 이것을 사용하도록 만든다. 이것을 사용하면 프레임워크 자체에 강하게 엮인다. 상속 자체가 매우 강한 종속성을 생성하는 작업이기 때문이다.
  • 현명한 아키텍트는 그런 관계를 만들지 않는다. 프레임워크가 일을 더 어렵게 만들고 애플리케이션을 단단히 엮어버린다며 보수적이고 비판적으로 바라본다. 무엇보다 프레임워크 제작자는 내가 가장 중요하게 생각하는 것이 무엇인지 모르기 때문이다.

Fitnesse

  • 예전에 엉클 밥님이 아들과 함께 만든 툴

  • 위키 텍스트를 HTML로 저장하기 위한 WikiPage라는 오브젝트를 만들었다.
  • 추상 클래스인 WikiPage를 MockWikiPage가 구현하고 있다.
  • WikiPage는 Load나 Save 같은 function을 가지고 있다.
  • 하지만 MockWikiPage에서는 이를 구현하고 있지는 않고 그냥 빈 껍데기이다.
  • 이 상태로 그냥 서비스의 핵심 비즈니스 룰을 구현하는 데에 집중했다.

  • 어느 정도 구현이 마무리된 후, 이제 데이터베이스 만들까에 대한 논의가 있었다.
  • 그냥 변환된 페이지를 메모리에 저장하고 나머지 기능을 보완하자!

  • 더 구현이 마무리된 후, 또 데이터베이스 도입에 대한 논의가 있었다.
  • 그냥 파일에 저장하자!
  • 결국엔 MySQL과의 연동 기능을 플러그인으로 배포했었다.
  • 이처럼 좋은 아키텍처는 중요한 의사결정을 뒤로 미룰 수 있게 한다.
  • 아키텍처의 목표는 결정을 안 할 수 있도록 하는 것이다. 가능한 많은 정보를 가지고 결정할 수 있게 미루고 미루는 것이 가능해야 한다.
  • 상위 레벨의 결정을 미룰 수 있도록 아키텍처나 코드 구조를 설계하자.
  • 아키텍처에 대해 얘기할 때 프레임워크 이야기하지 마라. (우린 SQL 서버를 가지고 있으며 MVVM 어쩌고 저쩌고...)
  • 아키텍처는 유즈 케이스이며 유즈 케이스는 툴에 대해 전혀 몰라야 한다.
  • 웹이나 데이터베이스 등 애플리케이션 없이 돌아가야 함
  • 다음에 애플리케이션 개발할 때 어떤 결정을 미룰 수 있을지 생각해보아라.

  • 애플리케이션은 위와 같은 플러그인 구조여야 한다.
  • GUI, 데이터베이스, 프레임워크 같은 디테일은 모두 유즈 케이스의 플러그인이 되어야 한다.
반응형