회고

20220920-21 TIL #비즈니스 로직은 분리 #레이어를 나누자 #Repository pattern

paran21 2022. 9. 21. 20:55

이번주 초까지 급하게 끝내야 하는 일정이 있어서 코드리뷰를 못하다가, 약간 시간이 생긴 오늘 코드리뷰를 했다.

평소에도 궁금한건 물어보면서 진행했지만, 오늘 리뷰하면서 전체적으로 우리 앱의 아키텍처에 대해서도 다시 설명을 해주셨다.

 

마침 오늘 아침에 서버 연동 부분을 보면서 어떤 레이어 구조로 나눠져 있는지, 각각 어떤 역할을 하는지 다시 살펴보았고,

계속 업무를 하면서 처음보다는 이해가 된 부분도 있고 궁금해진 점도 있어서, 2시간 가까이 얘기하면서 많은 부분이 정리되었다.

 

최근에 가장 큰 고민은 비즈니스 로직을 어디에 구현해야하는지, 였다.

우리 패키지 구조에서 이미 ui와 feature는 구분을 하고 있고, 위젯을 만들면서도 계속 위젯에는 로직이 들어가지 않게 분리하려고 했다.

ui와 비즈니스 로직은 분리해야지, 생각을 했으면서도 정작 구현할 때는 위젯에다가 로직을 구현해놨다가 나중에 몇번씩 수정하기도 했다.

(특히 onPressed 같은 애들!!)

 

dialog을 구현하면서 이 dialog창을 종료하기 위해 사용한 Navigator pop은 당연히 여기에 있어야지, 라고 생각을 했는데 단순히 dialog를 닫는 버튼도 아니고, TextButton에 따라서 각각 다른 onPressed가 붙어야 되는 상황이었다.

그래서 이 dialog위젯을 사용하는 페이지에서 맞는 onPressed를 변수로 넣어주도록 코드를 수정하였다.

또, dialog 버튼 중에 pop이 두 번 되어야 하는 상황이 있었다.

firstScreen-secondScreen-dialog 상황에서, dialog로 그만두기, 를 하면 secondScreen에서 나가는 거라서 firstScreen으로 돌아가야 했다.

우선 pop을 두 번 사용해서 firstScreen으로 돌아가는 것은 구현을 하였다.

그런데 dialog onPressed에 pop을 두 번 사용하면, dialog가 부모 위젯인 secondScreen가 해야할 로직까지 처리를 하게 된다!

그래서 dialog onPressed에서는 dialog에서 해야할 로직, 즉 pop을 한번만 해주고, secondScreen에서 콜백을 받아서 해당되는 경우에 pop을 하여 firstScreen으로 이동하게 하였다.

이 기능을 구현하면서 구현자체보다 이 함수가 여기서 쓰는게 맞는지 고민이 많았는데 사수와 얘기하면서 많은 공부가 되었다.

위젯을 분리한다는게 어떤 개념인지 조금 더 알게 된 것 같고, 특히 부모 위젯/자식 위젯의 관계에 대해서도 생각해 볼 수 있었다.

 


 

간단한 차트를 그리면서, 서버에서 가져온 데이터들을 다시 변환하는 메서드가 필요했다.

처음에 생각한 건, 데이터 모델인 class에 구현하는 것이었다.

그런데 우리 아키텍처에서는 데이터 모델 클래스는 정말 데이터 모델만 정의 + json을 변환해주는 역할만 하고 있고, 실제 이 데이터는 여러 레이어를 거쳐서 state notifier에서 상태를 관리한다.

dataSource에서는 apiClient를 호출해서 서버에서 데이터를 가져오고,

repository에서 이 data를 가져오면서 Either<Failure, Data>로 에러 상황과 정상 상황을 구분한다.

그리고 각 notifier에서는 repository를 통해 데이터를 가져오고, fold로 left(error상황)과 right(정상적으로 data가 들어온 경우)를 각각 처리를 해준다.

ui page에서는 provider를 통해 이 notifier를 observe하고 있기 때문에, notifier가 가지고 있는 상태가 변경되면 ui를 새로 그린다!

우리 아키텍처가 완전히 일치하는 건 아니지만 Repository pattern을 기본으로 한다고 해서, 더 찾아보면 좋을 것 같다.

 

코드리뷰를 하면서, 현재 우리 앱 구조에서 비즈니스 로직은 각 페이지에서 provider로 구현을 하는게 낫다고 얘기해주셨다.

ui page와 분리를 해야할 것 같아서 notifier에 여러 계산 로직들(최대값 구하기, 증가율 구하기 등등)을 구현해놓았는데

notifier는 상태를 가지고 있기 때문에 여기에 구현되는 로직들은 "상태"를 변경하는 경우들만 있는게 이 레이어의 목적과 맞다고 보았고,

단순히 상태가 변경되는 경우가 아니라 데이터들을 가지고 변경되는 로직들은 해당 페이지에 private provider로 구현하여 ui에서는 이 provider를 watch하도록 하자는 거였다.

이렇게 하면 일단 각 레이어들이 각각 맡은 역할만 하면서 분리가 되기 때문에 기능을 수정해야 할 때(앞으로 변경사항이 굉장히 많을 거라고 하셨다...재밌겠다..!) 어디서 어떤 부분을 수정해야 할 지 빨리 파악할 수 있을 것 같다.

page에 provider가 굉장히 많아 질 수 있지만(오늘 수정하면서 엄청 늘었다!), 그럼에도 얻는 이점이 더 큰 것 같다.

 

또, provider 중에 완전히 동일한데 두 페이지에서 사용해서 전역으로 선언한 애가 있었다.

그런데 provider는 기본적으로 싱글턴이고, 유저 정보와 같이 전역으로 쓰지 않는 이상 private으로 선언하는게 좋다고 해서 수정을 해주었다. (싱글턴이고 같이 데이터를 변경해야되는 경우가 아니라 이 경우는 private이 맞다!!)

 

요새 퇴근하고 집에와서 뻗어있느라 공부를 많이 못했는데 회사에서라도 공부를 많이 해서 다행이다...

오늘 리뷰를 바탕으로 내일 오전까지 코드를 잘 수정해서 pr올려야겠다!

 

그리고 우리 노션에 업무표를 만들어놨는데 하나라도 더 받아서 해보고 싶다!!