어떻게 하면 안드로이드 프로젝트의 설계를 잘할 수 있을까요?

wonseok·2023년 1월 12일
1
post-custom-banner

1) 패키징 잘하기

바깥쪽은 feature 별로 패키징하고, 그 안쪽은 layer 별로 패키징을 하면 뭐가 좋을까요?

  • high cohesionloose coupling 원칙을 지킬 수 있습니다.
  • 각 레이어를 다룰 때 인지적 과부하를 줄일 수 있습니다. 예를 들어 한 feature의 도메인 레이어를 변경하고자 할 때, 인터페이스의 경계로 인해 프레젠테이션 및 데이터 레이어를 대부분 무시하면서 작업할 수 있습니다.
  • 다른 레이어 종속성을 가짜(fake)로 대체하여 전체 레이어를 테스트합니다.
  • 다른 레이어를 건드리지 않고 레이어의 구현을 쉽게 리팩터링합니다.
  • 패키지들의 이름을 보는 것만으로도 앱이 어떤 일을 하는지 대강 알게 됩니다.

잘못된 패키징 (클린 아키텍처 관점)
만약 data 레이어에 1000개의 클래스가 존재한다고 생각해보면 어떨까요? 복잡하지 않을까요?

적절한 패키징 (클린 아키텍처 관점)

2) 도메인 완전히 이해하기

다음은 위키피디아에서 가져온 소프트웨어공학에 있어서 도메인의 정의입니다.

즉, 도메인은 요구 사항을 추출하는 영역이며, 앱의 기능이 작동하는 곳이라고 볼 수 있습니다.

그래서 보통 어떤 프로젝트를 설계하고자 할 때, 요구사항 별로 앱의 굵직한 Featrue 들을 구분하는 것이 중요합니다.

또한 안드로이드 프로젝트에서의 entity를 잘 정의하기 위해서는 도메인을 잘 분석해야 합니다.

왜 설계하고자 하는 앱의 도메인을 잘 알아야 하는지 다시 한 번 설명하도록 하겠습니다.

  • 모든 요구 사항을 충족하는 기능을 제대로 구현하려면 도메인을 이해해야 합니다. 요구 사항에 대한 명확한 경계를 설정하지 않는 경우, 가능한 모든 사용 사례를 다루고 있다고 어떻게 확신할 수 있을까요? 개발자가 무엇을 작업 하고 있는지와 왜 그것을 작업하고 있는지를 이해하지 못한다면 실수를 저지르기 마련이라고 생각합니다.
  • 앱 사용자는 일반적으로 도메인에 대해 깊이 이해하고 있습니다. 만약 개발자도 사용자만큼 도메인의 주의 사항과 복잡성을 잘 이해한다면, 사용자가 앱을 사용하는 방식을 잘 예측할 수 있습니다. 발생할 수 있는 에러들을 예상하고 앱을 더 잘 테스트할 수 있습니다.
  • 비전문가(디자이너, 기획자 등)와 기술적인 문제에 대해 소통할 수 있는 훌륭한 방법입니다. 도메인은 프로젝트에 참여하는 모든 사람이 공유하는 언어입니다.
  • 때때로 기획과정에서 만들어진 요구 사항이 불완전하거나 의미가 없을 수도 있습니다. 개발자도 도메인을 잘 이해한다면 요구사항들을 객관적으로 볼 수 있게 되며, 의견을 낼 수 있습니다.

다만, 주의할 점은 처음에는 도메인에 익숙해지는 데 시간이 좀 걸리겠지만, 디테일한 사항들에 대해서는 신경을 쓰지 않아도 괜찮습니다. 왜냐하면 어차피 코드를 구현하는 동안에는 하기 싫어도 디테일한 사항들에 대해 질리도록 보게 될 것입니다.

2-1) 도메인 레이어는 꼭 필요할까요?

안드로이드 커뮤니티에서도 도메인 레이어가 과연 필요할까에 대한 의견이 분분합니다.

구글 앱 아키텍처 가이드에서도 도메인 레이어는 필수가 아닌 선택사항으로 명시해두고 있습니다.

많은 앱들을 추상화한다면, 다음과 같은 간단한 패턴을 따른다고 볼 수 있습니다.

  1. 데이터 소스에서 데이터를 갖고 온다.
  2. UI에서 데이터를 보여준다.
  3. 새로운 데이터로 데이터 소스를 업데이트한다.

레이어 아키텍처 관점에서 본다면, 위 패턴은 데이터 레이어와 프레젠테이션 레이어로만 충분해보입니다.

도메인 레이어를 따로 두는 것은 불필요해보이고, 귀찮은 작업으로 보이기만 합니다.

그런데 한 가지 중요한 사실을 빼먹었습니다.
바로, 개발자 자신, 나에 대한 생각을 빼먹었습니다.

도메인 레이어는 결국 개발자 자신을 위해서 생각할 때 그 필요성이 나타납니다.
도메인 레이어를 두는 것에 대한 장점을 적어보겠습니다.

  • 도메인 레이어에서 비즈니스 로직에만 집중함으로써 코드를 클린하게, 코드를 유지보수하기 쉽게 만들 수 있습니다.
  • UI나 안드로이드 프레임워크 코드와 같이 앱의 비즈니스 로직과는 관련 없는 코드들과의 일종의 경계를 정의합니다. (안드로이드 프레임워크가 얼마나 자주, 그리고 빨리 바뀌는가를 감안하면, 이러한 분리는 정말 중요해보입니다.)
  • 새로 들어올 팀원들에게 도메인 레이어를 공부하게 시키는 것만으로 앱의 전체적인 로직을 이해할 수 있게 만들어 주는 온보딩 역할을 제공할 수 있습니다.

3) 소프트웨어를 나의 애인이라고 생각하기

이건 좀 뜬구름 잡는 소리인 것 같은데, 소프트웨어에 대한 저의 개인적인 견해입니다.
여자친구가 없으면..?

연애를 하다보면 다양한 상황에 놓이게 됩니다.

잘 지내고 있던 애인이 갑자기 삐지거나, 이해할 수 없는 행동을 한다거나, 연락이 안되거나 등등...

소프트웨어도 마찬가지라고 생각합니다.

어제까지만 해도 잘 동작하던 코드가 오늘은 잘 동작하지 않다거나, 요구사항들이 수시로 변경된다거나 등등...

저희가 연애를 할 때에 위에서 언급한 저런 상황들에 대비해서 미리미리 애인에게 잘해줘야 하는 것처럼,
소프트웨어 개발에 있어서도, 확장 가능성, 변경성을 고려한 설계를 미리미리 잘 해줘야합니다.

그렇다고 애인에게 너무 과도하게 잘해주는 것은 흔히 말하는 호구로 낙인찍힐 수 있는 것처럼,
소프트웨어 개발에 있어서도 이런 불확실한 미래를 대비하여 오버 엔지니어링을 하는 것은 피해야 하며, 현재에 집중해야 합니다.

4) 돌고 돌아 High Cohesion, Low Coupling

만약 앱의 비즈니스 로직을 다루는 코드가 한 클래스, 특정 모듈이 아니라, 특별한 원칙 없이 프로젝트의 전반에 걸쳐서 나타난다면 어떤 일이 발생할까요?

필자도 처음 안드로이드를 개발할 때에는, UI의 기능을 담당해야할 액티비티나 프래그먼트에서 모든 비즈니스 로직을 처리하여 개발했었습니다.

안드로이드 개발 입문 서적이나, 관련 블로그를 찾아보았을 때 실제로 저렇게 갓 액티비티 혹은 갓 프래그먼트 (액티비티나 프래그먼트에서 모든 로직을 처리하는 극악의 코드) 코드가 많이 존재했었고, 네트워크 호출을 하는 등의 I/O 작업을 할 때 앱이 조금 버벅이는 것 빼고는 원하는 로직대로 잘 돌아가니 문제가 없을 것이라 생각했었습니다.

참고로, 제가 요새 읽고 있는 객체지향의 사실과 오해라는 책의 31~32페이지에서도 다음과 같은 글이 있었습니다.

외부의 도움을 무시한 채 모든 것을 스스로 처리하려고 하는 전지전능한 객체(god object)는 내부적인 복잡도에 의해 자멸하고 만다.

그런데 앱의 스케일이 커질수록, 그리고 요구하는 기능들이 많아질수록, 점점 제가 직접 쓴 코드임에도 불구하고, 코드를 읽기가 점점 어려워졌고, 보일러 플레이트 코드도 점점 많아졌습니다.

post-custom-banner

0개의 댓글