View

300x250

Data Layer 쪽의 리펙토링을 진행하면서, 내가 데이터 계층의 Repository Impl 클래스를 파이어베이스에 의존적이게 코드를 작성하고 있다는 걸 깨달았다. 클린 아키텍처의 의의를 ‘쉽게 갈아끼울 수 있는 백엔드와 프론트엔드’ 라고 생각하고 적용하려고 노력하고 있기 때문에, 범용 클래스를 무조건 “특정 서비스에 의존적이지 않은 형태”로 작성해야 한다고 생각한다. 이에 요걸 분리하기 위해서 여러가지 고민을 했고, 이걸 글로 남겨두려고 한다!

현재 계층 구조와 설계한 사용 모델들을 간략하게 써보면 아래와 같다.

  • Presentation Layer에서는 뷰 계층의 model을 사용한다.
  • Domain Layer에서는 Entity를 사용한다.
  • Data Layer에서는 데이터 계층의 model을 사용한다. (뷰 model 과 다름!)

Untitled.png

여기에서 Domain 계층을 독립적으로 만들기 위해서 Presentation, Data 계층은 entity를 알고 있지만 그 반대는 적용되지 않도록 설계하고자 했다. 그래서 entity→model, model→entity의 형변환 책임을 viewmodelrepositoryImpl 클래스에 주고자 하였다. 여기까지는 매우 자연스럽다고 생각하고 요렇게 코드를 작성하고 있었다.

Untitled.png

여기에서 나는 파이어베이스를 사용하고 있기 때문에, Data 계층에서 사용할 model을 Firebase000Model 이라고 이름을 짓고 Firebase에서 사용할 수 있는 여러 메서드들을 넣어 작성해주고 있었고, entity ↔ model 형변환 함수도 함께 작성해 구현을 하고 있었다. 그런데 조금 생각해보니, 여기 부분이 문제였다.

만약 내가 Firebase가 아니라 다른 서비스를 사용하거나 로컬DB를 사용한다면 어디까지가 Entity의 영역이고, 어디까지가 서비스에 묶인 model을 사용하는 영역이여야 하지? 누가 형변환의 책임을 져야하지? 라는 고민에 빠졌다. 아무래도 범용 인터페이스용 클래스와 로직을 담당하는 클래스는 특정한 서비스에 종속된 모델을 사용하지 않아야 하므로 datasourceImpl 클래스로 책임을 줘야할 것 같은데… 라고 생각하면서 경우를 나눠봤다.

Untitled.png

아래 이미지처럼 3가지 정도의 케이스가 나왔다.

Untitled.png

  1. data 계층의 범용 model 과 datasourceImpl 클래스에서 사용하는 서비스 종속 model 을 따로 사용하기
  2. data 계층의 범용 model 없이 datasourceImpl 클래스에서만 서비스 종속 model을 사용하기
  3. data 계층 전체에서 entity 만 사용하기

3가지 케이스 중에서 고민을 해봤을 때, 2번째 방법을 사용하기로 마음먹었다.

일단 첫 번째 케이스를 사용한다고 했을 때, 너무 모델이 파편화되는 느낌이였다. 굳이 같은 의미의 모델을 계층에 따라 3개로 분리하는 것도 어떻게보면 번거로운데, 이걸 한 번 더 쪼개어 캐스팅을 하자니 너무 번거롭고 작업량이 많아질 것이라고 판단하였다.

두 번째 케이스에서는 굳이 datasourceImpl 클래스에서만 사용할 모델을 만들 필요가 있을까? 라는 생각이 들었다. 하나의 계층도 아니고, 하나의 클래스에서만 사용하는 데이터모델과 entity를 분리하면 첫 번째처럼 번거로운 일이 아닌가? 라는 생각을 했다. 아무래도 데이터를 파이어베이스 모델로 받아오자마자 entity로 형변환하여 내보내게 될텐데, 그냥 바로 entity로 받아버리는게 낫지 않나? 라는 생각이 들었다. 이것도 귀찮은 일이구나 라고 생각하다가 세 번째 케이스를 생각해보니 이게 제일 낫다고 생각이 들었다.

세 번째 케이스에서는 모든 클래스에서 domain 계층의 entity를 사용하는 것이다. 작업량은 제일 줄어들겠지만, 약간의 문제가 발생한다. data 게층의 코드를 작성하면서, entity가 특정 서비스에 의존성을 갖는 문제가 발생할 수 있다. 아래 이미지의 왼쪽은 내가 작성한 entity, 오른쪽은 파이어베이스 model 코드이다.

Untitled.png

작아서 잘 보이지는 않겠지만, 오른쪽에는 파이어베이스 프레임워크에서 사용하는 시간 데이터타입인 TimeStamp 관련 코드, FireStoreDocument에서 모델 데이터를 가져와 인스턴스를 만드는 함수 등이 포함된다. 만약 파이어베이스 모델을 entity로 형변환을 해주게 되면 이런 잡다한 파이어베이스 관련 코드가 왼쪽 model에는 제거될 수 있다. 이것만으로 entity와 모델을 분리해야하는 이유는 충분하다고 판단했다.

요런 이유로 각 클래스가 사용할 모델을 아래처럼 다시 설계하였다. 이 설계를 바탕으로 사용하는 모델과 형변환의 책임을 다시 적용해 현재 리펙토링 중인 구조를 조금 더 깔끔하게 변경해보려고 한다. 후… 며칠 더 걸리겠구만 🥲🥲

Untitled.png

요런 형태를 통해서 궁극적으로 내가 지향하는 모델 구조는 아마 이게 아닐까 싶다 ㅎㅎ

Untitled.png

320x100
Share Link
reply
반응형
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31