본문 바로가기

백엔드 개발일지

쉽게 알아보는 클린 아키텍처 (Clean Architecture)

반응형

지금까지의 프로젝트에서는 전통적인 MVC 패턴을 사용했다. 구조가 간단해 러닝 커브도 없고 신경 써야 할 부분이 상대적으로 적다는 장점 때문에 MVC 패턴을 선호해왔지만, 삐삐 서비스를 1년간 운영하면서 MVC 패턴의 단점을 점차 느끼고 있다.
 
그 중 가장 큰 문제는 기능이 추가되면서 Controller가 비대해진다는 점이다. 한 도메인에 대한 API 요청/응답 처리컨트롤러에 몰려 있어 코드를 파악하기 어렵고 유지보수성과 확장성이 떨어진다는 단점이 있다. 이것이 바로 MVC 패턴의 한계이다.
 
우리는 이러한 MVC 패턴의 한계를 인식하고, 현재 천천히 Clean Architecture로 리팩토링을 진행하고 있다. 이 글에서는 클린 아키텍처의 목적과 장점을 설명하고자 한다.
 
 

1. 아키텍처란

아키텍처란 앱 또는 소프트웨어 개발에서 코드를 구성하고 조직화하는 방법이다. 
아키텍처를 통해 하나의 서비스가 어떻게 구성되며 어떻게 동작되는지를 표현할 수 있다.
 

 
위의 그래프를 통해 알 수 있듯이 좋지 않은 디자인을 가진 소프트웨어는 시간이 지날수록 기능을 추가하는 것이 어렵고 이후에도 지속적으로 어려워진다. 처음에는 구축할 때는 시간이 오래걸리겠지만 소프트웨어 잘 컴포넌트화 할 수록 추후에는 새로운 기능을 더 빠르게 많이 추가할 수 있게 된다. 이것이 바로 소프트웨어 아키텍처가 중요한 이유이다.
 
 
그렇기에 우리는 코드를 구조화하여

  • 유지보수성을 높이고
  • 테스트가 가능하고
  • 재사용성이 높으며
  • 확장성 등의 측면에서

유리함을 가져가기 위한,
즉, 개발 프로세스를 향상시키기 위해 아키텍처를 잘 설계해야 한다.
 
 

2. 기존 아키텍처들의 한계

아키텍처는 여러가지가 존재하는데 일단 흔히 접해봤을 MVC 패턴부터 간단히 훑어보자.
 

1) MVC

MVC 패턴은 위의 그림처럼 사용자의 요청을 Controller가 처리하고, 비즈니스 로직에 따라 Model을 업데이트한 뒤, View에 전달해 화면에 표시하는 구조이다.
 
이 패턴은 구조적으로는 각 책임이 명확해 보이지만 복잡한 애플리케이션에서는 단점이 명확히 보인다. 컨트롤러가 입력 처리, 요청에 대한 응답 관리 등을 담당하게 되는데 시간이 지날수록 기능들은 늘어나고 결국 Controller가 맡는 일이 많아져 Controller가 뚱뚱해지는 문제가 생긴다. 이는 코드 복잡도를 높이고 테스트와 유지보수를 어렵게 만든다.

 
 

2) MVVM

이러한 MVC 패턴의 단점을 극복하고자 나타난게 MVVM이다.

ViewModel이 View와 Model 사이에서 데이터와 상태를 관리하며, 데이터 바인딩을 통해 View와 ViewModel 간의 변경사항을 자동으로 동기화하는 구조이다.
 
아까 보았던 MVC는 Controller가 입력 처리와 View-Model 간의 연결을 모두 담당했기에 역할이 중첩되어 컨트롤러가 뚱뚱해지기 쉬웠다. 하지만 지금 MVVM은 ViewModel이 상태와 로직을 관리하고, View는 이를 바인딩하여 단순히 UI를 표현하므로 UI와 로직 간의 결합이 더 느슨해진다. 한 마디로 MVC보다는 책임 분리와 결합도 측면에서 모두 개선될 수 있다.
 
 
그러면 이제 해결이 되었을까??
그럼에도! 시간이 지나면 결국 ViewModel이 뚱뚱해진다... 결국 다시 원점으로 돌아온다.

 
 

3. 클린 아키텍처

MVC 패턴은 시간이 지날수록 단점이 부각된다. 사람마다 MVC 패턴의 단점을 정의하는 것은 다르겠지만 내가 느끼기엔 MVC 패턴의 제일 큰 단점은 구조가 단순하기 때문에 컨트롤러가 쉽게 비대해지는 문제가 생길 수 있다는 점이다.
 
이제는 코드를 더 극단적으로 분리시켜줄 아키텍처가 필요하며, 이를 효과적으로 구현할 수 있는 것이 바로 클린 아키텍처이다.

 

1) 목표

소프트웨어를 계층으로 나누어 관심사를 분리하자.

 
 
서비스는 일반적으로 아래와 같은 구조를 보인다.

도메인 영역비즈니스 룰이 담긴 영역으로 쉽게 변하지 않는 영역이다. 서버 DB에 저장하거나 로컬 DB에 저장하거나 도메인은 알 필요가 없다. 마찬가지로 UI의 세부 요소가 어떻게 구성되든 도메인은 알 필요가 없다.
 
요구사항에 따라 UI는 쉽게 변할 수 있고 확장성 등의 문제로 기존 DBMS를 다른 DBMS로 교체할 수는 있지만, 이들이 변경된다고 비즈니스 룰이 담긴 도메인까지 함께 변경될 필요는 없다.
 
 
이처럼 클린 아키텍처에서는 쉽게 변하는 영역과 쉽게 변하지 않는 영역을 레이어로 나누어 관리하며, 이를 통해 서비스 정책 변경에 유연하게 대처할 수 있는 구조를 제안한다.
 

 

위의 그림은 클린 아키텍처를 찾아보면 쉽게 볼 수 있는 그림이다.

  • 내부의 원은 쉽게 변하지 않는 영역이 위치하며, 외부로 갈수록 변화 가능성이 높은 영역이 위치한다.
  • 내부 영역은 외부 변화의 영향을 받지 않도록, 의존성은 항상 외부에서 내부로 향하도록 관리된다.

 
 
이렇게 계층을 나누고 관심사를 분리함으로써,

  • 소스코드 전반을 쉽게 파악할 수 있고
  • 수정 사항에 대한 대응이 쉬워지고
  • 다른 계층에 영향을 주지 않아
  • 테스트가 쉬워진다

한 마디로 높은 응집도와 낮은 결합도를 가지며, 더 높은 생산성을 얻게 된다.

 

2) 원칙

클린 아키텍처를 설계하기 위해 준수해야 할 네 가지 원칙이 있다.
 

내부 영역으로 갈 수록 변경될 가능성이 낮아야 한다

클린 아키텍처 원의 안쪽으로 갈 수록 변경되지 않는 데이터이며 반대로 바깥쪽으로 갈 수록 변경될 확률이 높은 요소들이 위치한다.
 
원의 가장 안쪽에는 변경될 가능성이 적은 엔티티가 위치하고, 변경될 가능성이 높은 UI/DB 등을 원의 가장 바깥쪽에 위치시킨다.
→ 이렇게 분리하면, 변경사항이 생겼을 때 바깥쪽을 중심으로 살펴보면 되니 작업이 수월하다
 

외부 영역은 내부 영역에 의존할 수 있지만, 내부 영역은 외부 영역에 의존할 수 없다

이렇게 설계하면, 각 계층 간 의존성이 낮아지고 역할 구분이 명확해짐에 따라, 에러 발생의 가능성을 줄이고 코드 유지보수를 더욱 수월하게 처리할 수 있다.
 
클린 아키텍처가 갖는 기본의 목적 역시 관심사를 분리하는 것.
각각의 관심사에 따라 계층을 나누고, 세부 구현이 아닌 도메인 중심으로 설계하며, 내부 영역이 프레임워크나 데이터베이스/UI 등의 외부 요소에 의존하지 않도록 한다.
 

좋은 아키텍처는 프레임워크에 의존하지 않는다

프레임워크는 어디까지나 개발 생산성을 높이는 도구이지, 프레임워크 때문에 내부 로직이 좌우되는 상황은 발생해서는 안된다.
 

유스케이스는 아키텍처에서 최우선

클린 아키텍처에서 핵심이 되는 요소는 UseCase이다. 유스케이스는 비즈니스 로직을 담당하므로, 어플리케이션의 주요 로직을 담은 부분이다.
 
좋은 아키텍처는 유스케이스를 그 중심에 두기에, 프레임워크나 환경에 전혀 구애받지 않고 유스케이스를 지원하는 구조를 아무런 문제 없이 기술할 수 있다.
 
 
 
결론적으로, 우리는 클린아키텍처를 통해 소프트웨어의 독립성을 최대화할 수 있다.
이는 프레임워크, UI, 데이터베이스, 외부 애플리케이션 등의 변경이 핵심 비즈니스 로직에 미치는 영향을 최소화할 수 있다. 또한, 계층을 명확히 분리함으로써, 앞에서 걱정했던 유지보수성확장성을 크게 향상시킬 수 있다.
 
 
 
참고: https://www.youtube.com/watch?v=V0PZmJ7eDvo&t=35s

반응형