전부터 작성하려고 했는데 이제서야 작성하는 아키텍처 글....
이번 글에서는 우선 전체적인 틀에 대해서 작성하려고 한다
1. 클린 아키텍처란? 필요성?

위의 그림을 굉장히 많이 보았을 텐데,
먼저 아키텍처에 대해서 이야기를 해보자면
코드를 작성할때, 구조에 대해서 크게 신경쓰지 않아도 동작하는 프로그램을 만들 수 있지만 그렇게 한다면 점차 코드 개발이 힘들어지거나
또는 유지보수하기 힘들어진다.
그렇게 되는 가장 큰 이유중 하나가 코드 서로가 서로에게 큰 영향을 주기 때문인데,
예를 들어서 A코드를 동작하는데 B코드가 사용되고 필요하다면 B코드를 수정하면 자연스럽게 A코드의 수정이 필요한 경우가 많다.
이는 어쩔 수 없는 현상이지만 A코드를 동작할때, B,C,D..... 코드가 모두 사용된다고 하면, 굉장히 복잡하고 난감한 상황에 빠질때가 많아진다.
그래서 우리는 코드의 관심사 분리 혹은 독립성에 대해서 신경을 써야하고, 이를 위해서 아키텍처에 대해서 고민하게 되는데,
그 중 이러한 부분을 신경써서 구성한 아키텍처를 클린 아키텍처라고 하게 된다.
2. 클린 아키텍처의 구성
클린 아키텍처를 작성할 때, 위의 그림을 보면 층층이 나뉘어진걸 볼 수 있다.
한가지 기능을 만들더라도, 코드를 레이어별로 쪼개서 만드는 것인데 이는 레이어로 코드를 나눠서 레이어별로 관심사를 분리하는 것에 의미가 있다.
위의 그림에서는 엔티티(엔터프라이스 비즈니스 룰), 유즈케이스(어플리케이션 비즈니스 룰), 인터페이스 어댑터(컨트롤러, 프레젠터 등) 그리고 프레임워크&디바이스(외부 인터페이스 등) 이렇게 나뉘어진 것을 볼 수 있다.
각각 레이어에 대한 설명은 추후 글을 더 올리며 설명할 예정인데, 간단히 지도 프로그램을 예로든다면
1. 지도 거리계산, 최적 루트 탐색 등 비즈니스 로직을 Entitie 또는 Enterprise buisiness Rule로 만들고,
2. 길찾기 기능을 유즈케이스,
3. 길찾기 기능 결과값을 외부 시스템에 적합한 형태로 변환 하는 것을 인터페이스 어댑터로 나누고
4. 이를 UI에서 표현한다
크게 위에서와 같이 각각의 기능을 수행하는 것을 4가지 구조로 나눈다.

위의 그림에서 화살표를 볼 수 있는데, 화살표의 방향은 인지하고 있는 방향이라고 생각하면 된다.
(데이터의 흐름이나 요청방향이라고만 생각하면 이해가 어려울 수 있다. 즉 의존방향이다.)
1. 외부 인터페이스는 인터페이스 어댑터만을 인지하고 있고 인터페이스 어댑터를 이용해서 목적을 달성한다.
2. 인터페이스 어댑터는 유즈케이스만을 인지하고 있고, 자신의 목적을 유즈케이스를 이용해서 목적을 달성한다.
3. 유즈케이스는 엔티티만을 인지하고 있고, 엔티티를 이용해서 목적을 달성한다.
4. 엔티티는 자신에게 맡겨진 임무를 수행한다.
위와 같은 과정이고 외부의 레이어는 내부의 레이어에 요청을하고 이를 통해 자신의 목적을 달성한다.
세부적인 내용은 다른 글을 통해 다루도록 하겠다.
3. 앱 아키텍처
우선 나는 안드로이드를 주력으로 개발하고 있기 때문에... 서버를 공부하는 분이나 다른 분들보다는 안드로이드를 조금씩 공부하는 분들이 이 글을 많이 볼것 같은데(스프링부트나 IOS 관련한것도 앞으로 종종 올릴게요...) 그렇기 때문에 앱 아키텍처와 혼동하는 사람들이 많을 것 같다.
이를 이해하는 건 앞으로 규모가 커지면 커질수록 중요하고 또 특히나 클린 아키텍처는 앱 이외의 서버 개발이나 다른 개발을 할때도 중요한 개념이다.

앱 아키텍처의 경우 간단하게 설명하고 지나가자면,
UI에 대한 포커스가 매우 중요하다. UI와 실제 데이터의 상태에 대한 고려가 중요하기 때문에 프레젠테이션 레이어가 존재하고 이를 뷰모델을 중심으로 구현하여 MVVM 패턴을 구성한다.
안드로이드의 경우 뷰 기반이든 Compose기반이든 VIewModel을 통해 뷰와 도메인 혹은 데이터레이어를 분리하는데 초점이 맞춰져 있다. IOS도 크게 다르지는 않은데 SwiftUI가 나오고 나서 state등을 이용해서 자동적으로 뷰가 update 되긴 하지만 큰 프로젝트를 관리하는데 있어서 MVVM을 여전히 사용하는게 좋다는(논쟁이 있긴하다...) 의견이 있다.
이를 앱 아키텍처에서는 뷰부터 뷰모델까지 프레젠테이션 레이어로 구분하고 그 다음 해당 UI를 위한 유즈케이스 정도를 도메인 레이어,
비즈니스 로직을 데이터 레이어로 분류한다.
그럼 Domain Layer와 Data Layer는 그 내부의 비즈니스 로직이나 데이터 형태를 결정하는데 역할을 하는데(도메인 레이어의 경우 필수적이진 않다)
자세한 내용은 역시 다른 글을 통해서 다루도록 하겠다.
해당 화살표 표시 또한 클래스간의 종속성을 의미한다.
4. 클린 아키텍처와 앱 아키텍처
결론적으로 말하자면 어느정도 목적성이 일치하는 부분은 있을지라도 서로 다른 아키텍처이다.

위의 그림은 클린아키텍처와 앱 아키텍처를 혼합한 모습이다. 이렇게 보니 동심원상으로 프레젠터와 레포지토리, sdk와 디비&서버가 같은 선상에 있어서 약간 이해가 어렵기 때문에

위와 같이 또 바꿀 수 있다.
저렇게 되는 이유는 디비와 레포지토리의 경우 엔티티나 유즈케이스에 의존적이지 않기 쉽지 않기 때문이다.
안드로이드의 경우만 봐도 룸DB나 서버와의 통신을 사용할 때, data class를 이용하게 되는 경우가 많다. 통신이나 데이터 교환형식을 data class로 모델을 만들고 이를 통해 사용하기 때문이고, 이러한 모델을 사용해 비즈니스 로직등을 작성한다.
그러면 우리가 익히 알고있는 구글의 앱 아키텍처와 구성이 달라지게 된다. 위의 그림에서 화살표 방향을 보면 데이터 레이어가 도메인 레이어에 의존적이다. 이는 앱 아키텍처에서 데이터 레이어에 들어가야할 엔티티가 도메인 레이어로 들어가버리기 때문인데 이 부분에서 구글의 앱 아키텍처와 클린 아키텍처의 가장 큰 차이점이 발생하게 된다.
클린 아키텍처는 여기서 핵심적인 레이어가 도메인이되고, 어떤 레이어에도 의존하지 않지만
구글의 앱 아키텍처에서는 핵심적인 레이어가 데이터 레이어로 심지어 도메인 레이어는 선택사항이다.
의문이 하나 들 수 있다. 그렇다면 레포지토리와 DB server에 관련된 부분을 Entity와 같은 선상에 두면 되지 않는가???
유즈케이스만을 도메인 레이어에 두고, 엔티티를 데이터 레이어에 옮기게 해서
유즈케이스 -> 엔티티 or 레포지터리 -> 외부 DB,서버
개인적인 고찰로 이런식으로 두면.... 문제가 생길 수 밖에 있는게 바로 삼각 관계이다....
유즈케이스에서 엔티티로 갈수도 있고 레포지터리로 갈수도 있지만
하나의 케이스가 더 추가된다. 바로 엔티티와 레포지터리가 서로 필요한 상황이 생길 수 있다.
게다가 이 둘이 같은 데이터 모델을 공유하게 된다면 코드 수정시 연쇄적인 코드 수정이 필요할 수 있다.
5. 결론
생각보다 아키텍처는 정해져있지만은 않다. 이미 작성된 개념들을 토대로 해당 개념을 이용해서 잘 하면 된다
아키텍처는 정답을 암기하는 문제가 아니라, 우리 팀이 당면한 ‘변경 비용’을 줄이기 위한 선택의 조합이다.
그래서 구글 앱 아키텍처만으로도 충분한 시기가 있고, 처음부터 도메인 중심(Clean Architecture)으로 가야 하는 시기가 있으며, 이미 작성된 구조 위에 점진적으로 Clean 개념을 흡수하는 전략도 가능하다.
이번 글에서 다루지 못한 부분은 다음 시간에....
'개발 > 아키텍처' 카테고리의 다른 글
| [Architecture] DataResource (0) | 2025.09.11 |
|---|---|
| [Architecture] 데이터 모델과 아키텍처 (0) | 2025.08.12 |