본문 바로가기

Android/Architecture

[Android] Clean Architecture - UseCase 란 ?

728x90

처음 학습하면서 작성한 글입니다. 필요시 추후 내용을 수정할 예정입니다.

틀린 부분이 있으면 언제든 지적해주면 감사하겠습니다 :)


Clean Architecture 를 공부하는 도중에, UseCase 라는 것을 domain layer 에서 사용하는 것을 보았다.

UseCase 가 무엇이길래 이것을 사용하는 것인지 알아보자.

UseCase 란 ?

서비스를 사용하고 있는 사용자(User)가 해당 서비스를 통해 하고자 하는 것을 의미한다.

 

즉, 블로그 라는 서비스가 있다고 가정해보자.

사용자는 블로그에 들어와서 보고 싶은 게시글을 '검색' 할수도 있고, '댓글'을 남기거나 '공유' 버튼을 누르는 등 다양한 행동을 수행할 수 있다. 이러한 사용자가 서비스에서 수행하고자 하는 것들이 UseCase 라고 할 수 있다.

 

그렇다면,

UseCase 를 사용하는 이유는 무엇일까 ?

첫째, 해당 ViewModel 이 어떤것을 하고자 하는지 직관적으로 파악할 수 있다.

이것을 "Screaming Architecture" 라고 부르기도 하는데, 말 그대로 어떠한 서비스를 제공하는지 딱 봐도 알 수 있게 해주는 것이다.

UseCase 의 이름은 직관적으로 어떤 것을 수행하는지 알 수 있도록 지어야 한다. 그리고 VM 에서는 해당 UseCase 를 파라미터로 전달받아 사용하게 되니 VM 에서 어떠한 일을 하는지 파라미터만 확인해도 알 수 있게 된다.

이러한 구조는 유지/보수 측면에서도 유용하지만, 여럿이서 작업하는 협업 구조에서 더욱 진가를 보인다고 생각한다.

 

두번째, 의존성을 줄일 수 있다.

첫번째에서 설명한 것 처럼, VM 에서는 UseCase 를 파라미터로 전달 받아서 사용하게 된다.

UseCase 를 사용하지 않게 되면 VM 에서는 Repository 를 전달 받아서 사용하게 되는데, 전달 받은 Repository 가 수정이 된다면 해당 Repository 를 사용하는 많은 부분에서 수정이 이루어져야 할 가능성이 높다.

하지만, UseCase 를 사용하게 되면 영향이 있는 UseCase 를 사용하는 부분에서만 수정을 하면 되기 때문에 의존성이 줄어든다. 라고 생각할 수 있다.

Clean Architecture 의 목적 중 하나인 요구사항 변경 시 변경의 최소화를 만족하기 위해서도 필요하다고 볼 수 있다.


사용하는 이유도 알아 보았으니,

어떻게 사용해야 하는지 한번 생각해볼 때다.

 

UseCase 는 Domain Layer 에서 선언하여 사용한다.

네이밍은 위에서 언급한 대로 어떤 것을 수행하는지 이름만 봐도 알 수 있도록 해두어야 한다.

 

UseCase 의 소스코드를 확인해보자.

 

UseCase 에서는 해당 기능을 수행하는데 필요한 Repository 를 사용하여 원하는 기능을 수행하도록 하면 된다.

 

그렇다면 UseCase 를 사용하지 않고 Repository 를 사용하면 되는거 아닌가? 왜 한 Depth 를 추가하는 것인가? 라고 생각할 수 있다.

Repository 를 사용하게 되면 위에 기술한 UseCase 를 사용하는 이유 두번째 와 마찬가지로 수정이 필요할 때, 많은 부분을 수정해야 할 수 있다. 필요한 부분만 꺼내어 사용하는 UseCase 를 사용함으로 변경을 최소화 할 수 있기 때문에 사용한다.

또한, 일관성의 문제도 있다.

해당 Repository 의 함수를 모두 사용한다고 Repository 를 그대로 사용하게 되면, 어느 부분에는 UseCase 를 사용하고 어느 부분에는 Repositroy 를 사용하게 되어 유지/보수 하는 것, 협업 시에 불필요한 시간이 소요될 가능성이 크다.

따라서, 일관성을 지켜서 구현을 하는 것이 이러한 방면에서 유용하기 때문에 UseCase 를 사용하는 것이 좋다.

 

해당 UseCase Class 에는 같은 동작을 수행하는 메서드 execute, invoke 를 작성해 두었다.

필자가 구현할 때 예제로 사용했던 소스코드에서는 execute 를 사용했는데, 이처럼 별도의 네이밍을 한 메서드를 사용하여 작업을 수행하도록 해도 상관 없다.

하지만, UseCase 에서는 별 다른 작업을 수행하지 않고 Repository에 있는 함수를 호출하는 작업 하나밖에 없기 때문에 invoke 를 사용하는 것도 좋은 방법이라고 생각하여 이를 추가하였다.

* invoke 를 사용하는 경우, class 이름만 사용하여 함수를 호출할 수 있다. 자세한 사용법은 하단에 기술되어 있다.


잠깐, 여기서 사용되는 Repository 는 어디서 구현되고 있을까?

위의 Domain Layer 에 선언된 부분을 보면 UseCase 와 Repository 는 보이는데, Repository의 구현부. Impl 부분이 보이지 않는다.

여기서 한번 생각을 해보자.

UseCase 에서 사용 할 데이터는 어디에 있을까?

데이터 모델은 Domain Layer 에 존재하는데, 데이터 자체는 Data Layer 에 존재하게 된다. 그렇기 때문에 RepositoryImpl 는 Data Layer 부분에 있다.

 

 

이처럼 선언되어 있으며, 각 DataSource 는 실제 데이터를 가져오는 CRUD 이다.

이 RepositoryImpl 안에서 Repository 의 구현을 작성해두고, UseCase 에서 Impl 에서의 함수를 호출해서 사용하게 되는 것이다.

 


UseCase 를 호출하는 부분은 어떻게 되어있을까?

UseCase 를 사용하는 부분은 ViewModel 이다. 따라서 이곳에서 전달 받아서 사용하면 된다.

필자의 경우 간단한 토이 프로젝트이기 때문에 이런식으로 사용하는 UseCase 를 다 넣었지만, UseCase 가 많아지고 공통적으로 사용하는 부분이 많아 질 경우, UseCase 를 하나로 합치는 UseCase 를 만들어서 사용할 수 있다.

예로들어 위에 언급했던 블로그 라는 서비스의 게시글 '검색', '댓글', '공유' 의 3가지 UseCase 가 있을 때, '댓글' 과 '공유' 는 게시글을 보고 있을 때 수행할 수 있는 서비스 이다. 따라서 PostUseCase 라는 이름으로 UseCase 를 선언하고 그 안에 '댓글' 과 '공유' 의 UseCase 를 전달 받아 사용하면 된다.

 

UseCase 의 사용은 이처럼 하면 된다.

주석으로 처리된 부분과 시작 부분을 보면 앞서 UseCase 코드를 설명할 때 invoke와 execute 의 차이를 알 수 있다.

사용 시, 함수 명을 쓰고 안쓰고의 차이지만 조금 더 자연스럽게 읽히고, UseCase 를 사용할 때 조금 더 편하게 사용할 수 있다는 장점이 있다. (필자는 조금이라도 코드 량을 줄이고자 사용하기도 한다)

 

이처럼 해당 UseCase 가 필요한 부분에서 사용하여 원하는 데이터를 가져오도록(서비스를 제공하도록) 사용하면 된다.


UseCase 의 사용 법을 정리하자면,

Domain Layer.

  • Repository : interface. 구현부는 Data Layer.
  • UseCase : Repository 를 사용.

Data Layer.

  • RepositoryImpl : Domain Layer 의 Repository 구현부. CRUD(DataSource) 를 사용하여 실제 데이터를 가져온다.

Presentation Layer.

  • ViewModel : UseCase 를 사용.

이 3개의 계층의 4가지 클래스가 사용된다.

ViewModel 에서 실제 UseCase 를 호출해서 사용하게 되고, UseCase 는 Repository 를 호출, Repository 는 Data Layer 의 Impl 에서 구현, Impl 는 CRUD(DataSource) 를 사용하여 실제 데이터를 가져온다.

1. ViewModel 에서 UseCase 호출
2. UseCase 에서 RepositoryImpl 호출 
3. RepositoryImpl 에서 데이터를 Return
4. UseCase 에서 return 받은 데이터를 ViewModel 로 던짐
5. ViewModel 에서 Return 받은 데이터를 사용.

 

라는 흐름으로 UseCase를 사용하게 된다.

 


본 게시글에 사용된 코드는 gitHub에 업로드 해두었습니다.

https://github.com/HeeGyeong/CleanArchitectureSample

 

GitHub - HeeGyeong/CleanArchitectureSample

Contribute to HeeGyeong/CleanArchitectureSample development by creating an account on GitHub.

github.com

 

728x90