[Team 박카스] 1st 코드 리뷰(1)

Doccimann·2022년 1월 27일
0
post-thumbnail

첫번째 코드 리뷰에서는 어떤 이야기가 오갔을까요?

  1. 동네마켓, 동네마켓의 품목을 나타내는 view를 recyclerView로 나타내는데 있어서 과연 clean-architecture의 원칙에 위배 되지않게 잘 구현을 했는가? (사실 이게 제일 중요하죠)
  2. 발표자는 과연 본인의 코드를 잘 이해하고 있었는가?
  3. 발표자는 동네마켓(TownMarket), 동네마켓의 물품(HomeItem)에 관한 Model을 효율적으로 구성을 하였는가?
  4. 과연 발표자의 코드가 최선이었으며, 최선이 아니었다면 개선해야할 부분은 어디가 있는가?

글을 본격적으로 작성하기에 앞서

1월 24일에는 Team 박카스의 첫번째 코드 리뷰가 있었던 날입니다. (발표자는 현재 글을 쓰고있는 본인이었습니다...😅) 팀의 첫번째 코드 리뷰가 있었던 날인만큼 첫 스타트를 잘 끊어야한다는 부담감을 안고 시작하였는데요! 일단 제가 발표한 저의 코드 설명(?)을 대략적으로 끄적여보겠습니다 😁😁


내가 발표한 내용의 대략적 요약

우선 저희는 안드로이드 개발을 하는데 있어서 Clean Architecture를 기반으로 코드를 작성하고 있기 때문에 recyclerView를 만들어내기 위해서는 다음과 같은 순서를 따르게 되어있어요!

  • 우선 저희가 view에 나타내야하는 item들의 Model을 정의해줘야해요. (item에 대한 정보는 필요하니까요!)
  • Model을 정의하셨다면, Model에 대한 ViewHolder를 정의해줘야해요. RecyclerView는 view에 대한 자원을 효율적으로 관리하기 때문에 viewHolder가 필요하답니다! (물론, 어댑터를 구현할 때 강제적으로 넣을수밖에 없는 환경이지만요! ㅋㅋㅋ)
  • viewHolder를 구현을 하셨다면, 그 다음에는 recyclerView에 넣을 어댑터를 구성해줍니다!
  • 어댑터의 구성이 끝났다면? 그냥 recyclerView에 꽂으면 끝나쥬?

Model 구현

우선 저는 TownMarketModel, HomeItemModel을 구현하기에 앞서서, HomeListModel이라는, HomeListFragment에 사용될 모델들을 추상화한 추상 클래스를 하나 정의를 해주었는데요, 저걸 만들 당시에 생각은 아래와 같아요!

  • 저희는 기존에 CellType에는 BottomNavigationBar에 담길 아이템 정보를 저장하였는데요, 문제는 HomeListFragment의 recyclerView에 들어갈 아이템들은 모두 같은 HOME_CELL이라는 속성을 가진다는 것이에요! 그러면 홈에 있는 아이템들을 비교가 불가능하니, HomeCategory라는 enum class로 HomeItem의 속성을 따로 관리하여, HomeCategory를 기준으로 비교 수행을 할거야!

그런데 문제가 하나 발생했어요! 기존에는 ModelRecyclerAdapter라는 추상 클래스에서는 ListAdapter를 상속을 받고 있었는데, ListAdapter에 들어갈 Diff_Callback이 달라져야했어요. (비교 기준이 추가가 되었기도 하지만, 결정적으로 TownMarketModel, HomeItemModel이 HomeListModel을 상속받기 때문에 기존의 ModelRecyclerAdapter에 적용이 안된다는 문제랍니다)

그래서 저는 선택을 해야했는데요! 저에게 주어진 선택지는 두 가지가 있었어요.

  1. HomeListModel을 포기하자. 그러면 ModelRecyclerAdapter 말고 다른 어댑터를 추가적으로 구현할 필요가 사라지더라! (물론 이걸 실현하려면, HomeListCategory를 서로 비교할 대체 방안을 마련해야겠지?)
  2. HomeListModel을 포기하지말자. 대신에 adapter의 추상 클래스가 늘어나는건 어쩔수없는 출혈로 생각을 하자.

저는 결국엔 후자를 선택을 하였는데요! 별 다른 이유가 없습니다... 계속 고민해도 HomeListCategory를 Diff_callback에서 비교 수행을 하도록 만들 방법을 찾지 못했기 때문이죠!! (자랑이다 참... 😥) 그래서 HomeListModel을 상속받는 TownMarketModel, HomeItemModel을 다음과 같이 구현을 해줬어요. (물론, 확정된건 아닙니다. 앞으로 구현할 내용에 따라서 Model이 포함해야할 내용은 얼마든지 변동이 가능하니까요.)




ViewHolder의 구현

viewHolder의 구현은 생각보다 간단합니다! 다만, 데이터 타입이 Model에서 HomeListModel로 변경이 되었기 때문에, HomeModelViewHolder라는 추상 클래스를 추가적으로 구현을 해서, 그걸 상속받는 형식으로 작성을 하였답니다! 코드를 한 번 볼까요?

  • reset() : ImageView에 할당이 되어있는 리소스(여기서는 ImageView에 있는 그림이 되겠죠?)를 해제시키는 역할을 하는 메소드입니다. Glide의 clear method를 ImageView의 extension으로 사용해서 구현할 예정이에요.
  • bindData(model : M) : view에 model에 있는 데이터를 모조리 꽂아주는(?) 기능을 하는 메소드에요. 일단 이미지를 모조리 메모리에서 해제를 시키고 시작합니다!
  • bindViews(model : M, adapterListener : AdapterListener) : bindData를 통해서 data를 view에 바인딩을 시키면, 그 다음엔 뷰에다가 리스너를 달아야겠죠? 아이템을 클릭해주면 다음 행동이 시작되어야 하니까요!

사실 여기까지 작성했다면, viewHolder의 이후 구현은 정말로 쉬운데요! 그냥 오버라이드 해서 내용만 채워주면 되니까요 😁 (사실 그 전에 viewHolder에 대한 view xml을 작성해야한다는....읍읍!)
TownMarketModel에 대한 viewHolder만 예시로 들어드릴게요!

사실 아직까지는 TownMarket에 대한 데이터를 받아올 곳이 없어서...일단 view는 봐야 속이 편하니까! 그래서 임시적으로 데이터를 하드코딩을 해놨답니다!


RecyclerAdapter의 구현

이제 RecyclerAdapter만 구현하면 다 왔습니다! 일단 코드부터 볼까요?

위에서 말한대로, ListAdapter를 상속받되, ListAdapter의 생성자 파라미터로 HomeListModel에서 companion object(우리 말로는 동반자 객체? 이려나?)로 구현을 해둔 Diff_Callback을 넘겨주었어요.

이 Diff_Callback이 recyclerView의 modelList에 변화가 감지될 때마다 변화된 부분만 쏘옥! 골라서 그 아이템만 갈아끼워 줄거에요.(나중에 android 개념을 끄적일 때가 된다면 Diff_Callback에 관해서도 자세하게 다뤄줄게요😁)

제 코드에서 조금 특이한 부분이 하나 있을텐데요, onCreateViewHolder에서는 viewHolder를 반환시켜서 recyclerView에 viewHolder를 전달해주는게 국롤이라면 국롤인데! 뜬금없이 뭔 이상한 메소드를 호출하고 있어요! 사실은, 다 사연이 있어요.

HomeListFragment에 띄워야할 Model의 종류가 하나면 그냥 onCreateViewHolder에서 viewHolder를 반환시키고 끝낼텐데, Model이 두 가지 종류 이상이라서 mapper를 구성하여 homeListCategory에 따라서 viewHolder를 반환하도록 구현을 해두었답니다!

구현은 아주 간단하니까, 여기서는 생략을 하도록할게요. (위에서 말한대로, homeListCategory를 받아서 viewHolder에 넣어야할 파라미터들을 mapper에 동시에 전달해주면 되는거랍니다!)


recyclerView에 이제 adapter를 끼워보자!

우선은, Adapter의 파라미터에 빈 리스트를 넣어줬는데요, 이유는 다음과 같아요.

  • recyclerView가 띄워주는 데이터는 변화가 자주 일어나기 때문에, 데이터들을 ViewModel에서 LiveData의 형태로 관리를 해줘야해요. 그리고 LiveData의 변화를 감지해서 adapter의 submitList를 호출해서 recyclerView의 데이터를 다시 초기화해주면 된답니다!

그리고 viewModel, resourcesProvider(이거는 androidx에 존재하는 resourcesProvider가 아니라, 제가 따로 구현을 해둔 resourcesProvider에요.)를 넣어주고, adapterListener를 넣어주면 됩니다. 저는 adapterListener를 따로 구현체를 두고 코딩을 하지 않고, adapter를 초기화할 때 익명객체의 형태로 구현을 하는 방안을 채택했습니다! (어차피 여기서 리스너가 할 일이, intent를 사용해서 activity를 새로 띄우는게 끝이라고 생각해서요...)


이상 제가 발표했던 내용들이었어요! 다음 글은, 제 코드가 어떻게 팀원들에게 공격당하고, 달달 볶였는지(?) 소개할 예정입니다!

긴 글 읽어주셔서 감사합니다. 질문은 언제나 환영이에요 ☺️

profile
Hi There 🤗! I'm college student majoring Mathematics, and double majoring CSE. I'm just enjoying studying about good architectures of back-end system(applications) and how to operate the servers efficiently! 🔥

0개의 댓글