Clean Architecture는 모바일 개발을 어떻게 도와주는가?

Image for post

Credit: Shutterstock

개발자라면 클린 아키텍처라는 단어와, 클린 아키텍처 다이어그램(과녁 그림)에 대해 한 번쯤은 들어본 적이 있을 겁니다. 저는 다양한 개발자들을 만나면서 Uncle Bob이 “Clean”라는 상표명(?)을 붙여서 만들어낸 브랜드일 뿐 어디까지나 상술이라고 얘기하는 분도 봤고, 정반대로 신앙에 가까운 믿음을 가지고 지나치게 철저히 적용하려는 분도 봤습니다.
앞으로 4번에 걸쳐서 클린 아키텍처가 실제로 Android / iOS 개발에 어떤 도움을 주는지, 내가 지금 개발하고 있는 프로젝트와는 어떤 의미가 있을 지 함께 생각해보고자 합니다.

클린 아키텍처란 무엇인가?

클린 아키텍처는 Uncle Bob이 2012년 엔터프라이즈 아키텍처에서 논의 되던 내용을 집약시킨 개념입니다.(한글 번역 링크) 클린 아키텍처는 두 가지 관점에서 볼 수 있습니다.

하나는 아키텍처 설계의 철학과 원칙입니다. SOLID 원칙 — 단일 책임 원칙(Single Responsibility Principle)을 시작으로 한 다섯 가지 원칙 — 등을 중심으로 이제까지 SW 설계에서 중요하게 거론되어온 다양한 원칙들을 일목요연하게 정리하고 있습니다.

두번째는 아래 과녁 그림(?)으로 유명한 아케텍처의 청사진입니다. 이는 Hexagonal Architecture, Onion Architecture 등 당시 널리 알려진 아키텍처들의 공통된 성과물을 정리한 것입니다. 모바일부터 백엔드까지 모든 소프트웨어에 일반적으로 필요한 내용을 담고 있으며, 각 계층을 어떻게 나누고 어떤 요소로 구성할 것인가에 대한 원칙들을 알려줍니다.
가운데로 갈 수록 높은 수준, 바깥으로 갈 수록 낮은 수준의 컴포넌트로, 이에 대한 효율적인 분리로 효과적인 설계가 가능하다는 점을 설명하고 있습니다.(이에 대한 자세한 설명은 최근 번역 출간된 책을 참고 바랍니다.)

Image for post

Image for post

Credit: 도서출판 인사이트

클린 아키텍처는 이후 2018년에 책으로 정리되어 출간되었지만, 그전부터도 이미 아키텍처 분야에서 가장 입에 잘 오르내리는 buzzword가 되었고, 다양한 SW의 설계에 영감을 주었습니다. 모바일 관점에서는 아래 네 가지 부분에서 큰 영향을 주었다고 생각합니다.

  1. 경계선(Boundaries): 계층 구조의 개념이 널리 적용됨
  2. 유스케이스(Use Case): 도메인 계층의 분리로 소스코드 변경 안정성(stability)이 높아짐
  3. 험블 객체(Humble Object): 프리젠테이션 계층의 테스트 가능성, 가독성, 유지보수성을 향상
  4. 의존성 역전(DIP): modular한 프로젝트 구조의 확산

이 글에서는 1.경계선에 대한 생각을 나눠볼까 합니다.

Part 1. 경계선: 계층 나누기

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

암흑시대 이야기

모바일 SW 아키텍처에 대해 어느 정도 집약된 지식이 공유되기 전 시절에는 대략 아래와 같은 시도들이 패턴화 되고 있었습니다.

위의 Service들은 일부 UI에 관련된 것도 있고 (애니메이션 혹은 레이아웃을 위한 좌표 계산 등을 포함), 대부분은 업무 로직과 데이터 로직이 뒤섞여진 형태로 묶이게 마련입니다. 클린 아키텍처는 이들을 근본적으로 분리시켜주는 단초를 제공합니다.

모바일 클린 아키텍처

2012년 이후, 어떻게 하면 모바일 설계에서 클린 아키텍처의 도움을 받을 수 있을까에 대한 많은 논의와 시도가 있었는데, 그중 가장 중요한 영향은 경계(Boundaries)에 대한 것이었습니다. 즉 모듈의 변경이 다른 모듈에 영향을 미치지 않도록, 그리고 같은 모듈 내에서는 일관되고 응집력 있는 결합을 제공할 수 있도록 계층을 구분하는 것입니다.

그 결과, 원래 네 개인 계층을 재구성해서 세 개의 계층으로 분리하는 것으로 일반화되었습니다. 아래의 그림은 모바일 앱에서 전체적으로 받아들여지는 모바일 클린 아키텍처를 설명한 그림들 중, 제가 본 것들 중 가장 직관적으로 정리된 그림입니다.

Image for post

Image for post

Credit: koutalou

**프리젠테이션 계층 (Presentation Layer)
**화면의 표시, 애니메이션, 사용자 입력 처리 등 UI에 관련된 모든 처리를 갖고 있습니다.

도메인 계층 (Domain Layer)

데이터 계층 (Data Layer)

도메인 계층의 유스케이스와 프리젠테이션 계층의 프리젠터는 어떻게 구별하나?

많은 경우, 유스케이스의 비즈니스 로직과 프리젠터의 로직은 명확히 구별이 되지만, 가끔은 매우 헷갈리는 경우가 있습니다.

이럴 경우, 가장 도움이 되는 질문은, “개발팀 외부의 사업 부서의 사람도 알고 있어야 하는 로직인가?” 여부라고 생각합니다. 비즈니스 로직은 문자 그대로 앱의 사용자 상호작용이 아닌 업무 요구사항을 담고 있는 것이기 때문입니다.

다른 케이스로, 앱의 특성상 각 프리텐터에서 자주 사용되는 공통의 로직이 꽤 발생하는 경우가 있습니다. 이 경우, 엄밀히 얘기하면 도메인 로직이라고 할 수는 없지만, ViewUseCase 형태의 클래스로 분리해서 프리젠테이션 계층에 추가하는 것은 좋은 방법이라고 생각합니다.

그렇게 계층을 나누면 뭐가 좋은가?

이렇게 계층을 분리함으로 인해 얻을 수 있는 가장 큰 이점은, 상당히 분량이 많은 앱이더라도 소스코드 전반을 쉽게 장악할 수 있다는 점입니다.

복잡한 수정 사항이 생겼을 때라도, 어떤 부분들을 고치면 되는지 금방 파악할 수 있습니다. 모듈 구성, 그리고 패키지/폴더 구성이 자연스럽게 각 계층별로 일목요연한 트리구조를 이루기 때문에(이 부분은 마지막 글에서 다뤄보겠습니다), 다른 개발자나 혹은 (다른 개발자나 다름없는) 몇 달 뒤의 내가 다시 코드를 들여봐도 금방 코드를 이해하고 수정할 수 있습니다. 정확히 얘기하면, 굳이 지금 수정할 필요가 없는 코드를 보지 않고도 필요한 부분만 보면 됩니다.
그리고 무엇보다 좋은 점은, 특정 계층에 대한 수정이 다른 계층에 거의 영향을 주지 않는다는 점입니다.

저의 경우, 전 직장에서 회원제 서비스 앱을 개발한 적이 있는데, 회원가입을 하지 않으면 아주 기본적인 소개와 튜토리얼 등 간단한 화면만 볼 수 있는 앱이었습니다. 그런데 출시를 단 이틀 남겨놓은 시점에서 기획자가 (사장님 보고 자리에서 한 소리 듣고 와서..) 다급히 Airbnb처럼 로그인 없이도 대부분의 화면을 볼 수 있게 앱을 수정해달라는 요청을 해왔습니다.
그것은 상당히 큰 변화라, 클린 아키텍처 형태의 구조가 아니었다면 구현과 리그레션 테스트/디버깅까지 포함해서 몇 일 밤을 새야할 수도 있는 수정사항이었지만, 단 3시간만에 완료해서 기획자를 놀래켜준 경험이 있습니다.
REST API를 통해 받은 정보를 보여주는 몇 개의 유스케이스를 로그인 하지 않은 유저에게도 (제한된 정보로) 값을 주도록 수정하고, 데이터 소스에서 API 호출 시 파라미터를 변경하고, 비로그인 유저가 회원관리 모드로 들어갈 수 없도록 프리젠터를 수정하고 반대로 나머지 페이지는 다 들어갈 수 있도록 네비게이션 로직을 바꾸는 걸로 모든 수정이 끝났기 때문입니다. 급격한 기획 변경에도 불구하고, 소스코드 관점에서는 변경되는 부분들이 제한되어 있었기 때문에 버그가 발생할 여지도 많지 않았습니다.

저 많은 클래스들을 꼭 다 만들어야하나요?

클린 아키텍처는 많은 장점이 있는 반면, 부작용으로 간단한 로직을 구현할 때도 상당히 많은 양의 클래스를 만들어줘야 한다는 부담이 있습니다. 이 경우의 해결책으로 몇 가지 대안을 생각해 볼 수 있겠습니다.

다음 주에는 모바일 개발에서 자주 거론되지 않은 도메인 계층에 대해서 나눠보고자 합니다.(이번엔 소스코드도..)
그리고 최신 모바일 개발 소식이 알고 싶은 분들은 아래 링크들을 눌러누세요~ =)