brunch

매거진 kmong Tech

You can make anything
by writing

C.S.Lewis

by 박재영 Apr 27. 2020

RecyclerView In Kmong MVP

크몽에서는 MVP를 어떻게 적용했을까?

안녕하세요! 크몽 안드로이드 개발자 vigli(비글리)입니다 :)

모두 잘 계셨나요?

크몽 앱에 적용된 MVP 패턴에서 RecyclerView 부분을 소개하고자 합니다.


소개에 앞서 MVP 패턴을 간단히 설명해 드리자면,

MVP는 Model, View, Presenter로 구성된 아키텍처 패턴입니다.

위의 그림에 선이 많아 복잡해 보일 수 있습니다만 정말 간단한 구조입니다.

View : Activity, Fragment 등이며, 사용자의 인터렉션이 필요한 부분이 속합니다. View는 자신의 인터페이스인 IView를 가지고 있고, 이를 통해 Presenter에게 자신의 상태를 변경합니다.

Presenter : MVP 패턴에서 핵심 역할을 수행합니다. View의 상태를 관리하고 Model에게 필요한 데이터를 요청합니다. 그리고 비즈니스 로직이 포함됩니다. IPresenter를 구현하고 있어, View의 인터렉션을 전달받습니다.

Repository : Local, Server 데이터를 관리합니다. IRepository를 구현하고 있으므로, Presenter에게 필요한 데이터를 전달합니다.


중요한 원칙은 아래와 같습니다.

MVP는 각자의 역할을 충실히 수행하고 서로의 역할을 침범하지 않는다.

MVP 서로의 연결은 직접 하지 않는다.


이 원칙으로 MVP를 Activity에 적용한다면 간단히 적용할 수 있을 것 같아요.


다른 곳에도 적용해볼게요.

RecyclerView로 해볼까요?


RecyclerView는 View 재활용, 메모리와 성능 관리 등 핵심적인 역할을 직접 담당합니다. 개발자는 RecyclerView에 데이터를 잘 연결만 해주면, RecyclerView가 앞서 말한 핵심적인 역할을 알아서 해주죠. 즉, 개발자는 데이터만 잘 다루면 되죠. 

RecyclerView 앱을 구성하는 핵심 View 중 하나가 분명해요. 그래서 이번 글을 쓰게 됐죠!

크몽에도 이렇게 많은 화면에 RecyclerView가 있답니다.

Kmong Android App



그럼 RecyclerView는 어떻게 MVP를 적용할까요?

RecyclerView, Adapter, ViewHolder…

머릿속으로, 또는 노트에 그려봅시다.

RecyclerView에도 MVP의 모습이 잘 그려지시나요?

잘 그려지시는 분은 지금부터 보여드릴 구조와 비교를 해보시고, 잘 그려지지 않는 분은 이런 방법이 있구나! 하고 가볍게 보시면 좋을 것 같습니다.


우선, 가장 중요한 사실이 하나 있습니다!

이 구조는 정답이 아닙니다


모든 코드에 정답은 없습니다. 시대에 따라, 앱의 성격에 따라, 사람에 따라, 등등 다양한 환경에 따라 같은 기능을 하는 로직이라도 코드는 다르게 무수히 많이 나올 수 있습니다.

그러므로 지금 설명하는 내용에 비판적인 시각으로 바라봐주시길 바랍니다.



RecyclerView는 

Adapter, ViewHolder가 꼭 필요합니다! 하나씩 MVP 패턴을 어떻게 구성될 수 있는지 볼까요?


RecyclerView : View로 구성할 수 있습니다. 단지, 리스트를 보여줍니다. 

ViewHolder : View와 Presenter로 나눌 수 있습니다. View는 리스트에 속하는 아이템뷰를 보여줍니다. 그리고 Presneter는 아이템뷰에 보여줄 데이터를 비즈니스 로직에 따라 가공해서 뷰에 연결합니다.

Adapter : View와 Model, Presenter로 나눌 수 있습니다. Adapter는 RecyclerView의 위치에 어떤 아이템이 보여줘야 하는지(View), 어떤 데이터를 추가, 삭제 업데이트하는지(Model) 전체적인 관리(Presenter)를 합니다.

그래서 크몽의 RecyclerView에는 이렇게 MVP가 적용되어 있습니다.


???

이상하죠?

지금까지 설명으로는, Adapter는 모든 역할을 다 수행하므로 View, Model, Presenter로 나눠줘야 합니다.

그런데 크몽에서 Adapter 역할을 분리하지 않습니다.


왜? 가장 큰 이유는, 개발자 피로도 줄이기!라고 말하겠어요.

이제부터 이유를 설명해 드릴게요.


1. 개발 공수 낮춤

Adapter의 역할에 따라 MVP로 나눠야 하는 일을 하지 않으므로 코드량이 줄어듭니다. 결과적으로 개발 공수가 줄어듭니다.

2. 테스트를 줄이자

리스트에 각 아이템 별 데이터가 제대로 나오는지? 제대로 기능을 수행하는지? 이 부분은 ViewHolder에서 테스트하므로 Adatper에서 어떤 ViewHolder를 만드는지, 어떤 ViewHolder에 데이터를 주는지에 대한 테스트는 과한 테스트가 됩니다. 물론 테스트는 모든 상황에 대처할 수 있어야 합니다. 그리고 Adapter는 올바른 ViewHolder를 만들고 그에 맞는 데이터를 줘야 합니다. 하지만 그 두 행위가 잘못됐다면, ViewHolder의 아이템 뷰가 제대로 역할을 못 하므로 테스트 상황에 걸리게 되며, 그에 따른 에러 처리가 동작합니다.

3. 구글 코드

구글 코드라서 테스트를 하지 않아요?? 

Adapter가 수행할 역할은 Base Adatper를 만든 개발자가 테스트를 할 것이기 때문이죠.(일을 떠넘기죠 -ㅅ-) 물론 구글 개발자도 사람입니다. 어떤 오류가 날지 모릅니다. 그래서 예외 상황에 대해 오류 처리하는 것으로 테스트를 합니다. (저희는 구글 코드도 항상 의심합니다. 하지만 Adapter는 예외로 적용합니다.)

Adapter는 믿되, ViewHolder를 믿지 않습니다.


그래서 크몽에서는 Adapter는 분리하지 않습니다.



그럼 마지막으로 ViewHolder는 어떻게 나누었는지 살펴볼게요.

RecyclerView In Kmong MVP2


ViewHolder의 아이템뷰는 View, Presenter로 나눕니다.

여기서 View와 Presenter는 서두에 말한 Activity에서 MVP 구조와 역할이 같습니다.

다만, IRootView라는 인터페이스가 추가되었습니다.


아이템뷰는 다양한 화면에 사용됩니다.

동일한 아이템뷰를 쓰는 화면

위와 같이 메인화면, 카테고리 상세 화면, 찜목록에는 동일한 아이템뷰가 사용되죠.

즉, 아래와 같은 관계가 형성됩니다.

중요한 것은, 아이템뷰가 어떤 화면에 붙을지 모른다는 이에요.

어디에 붙든 자신의 역할만 수행하면 되죠!

그리고 의존성을 없애기 위해, IRootView 인터페이스를 이용하여 View에게 데이터를 요청하거나 이벤트를 처리합니다.

이렇게 함으로써 아이템뷰는 같은 UI/동작에 대해 화면별 다른 역할을 수행하게 만들 수 있습니다.



어떠셨나요?


정답은 없습니다. 항상 더 좋은 방향을 위해 시도하는 거죠!

여러분은 어떻게 규칙을 정했는지 정말 궁금하네요!!


긴 글 읽어주셔서 감사합니다.

크몽 Vigli이었습니다.




Android 개발자




매거진의 이전글 크몽 FE 팀 코드리뷰문화 개선기(1+1=3)
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari