아키텍처/클린 아키텍처

[클린 아키텍처] 아키텍처 청소부 스터디 후기

Kyle H 2023. 8. 21. 02:00

0. 클린 아키텍처 스터디를 시작하게 된 이유

좋은 기회로 내놓으라 하는 국내 서비스 대표기업에서 주최하는 스터디에 참여할 기회를 얻게 되었습니다. 

  • 여러 가지 주제가 있었고, 그중에 선택해서 지원하는 방식이었는데 클린 아키텍처 스터디와, 대규모 시스템 설계 스터디 둘 중에 고민을 하게 되었습니다. 
  • 지원 당시에 한참 객체지향에 대해 공부하고 있었습니다. JPA를 공부하고 프로젝트를 시작해보려고 하는데, 어느 메소드를 어느 클래스에 만들어야 하는지가 스스로 명확히 할 수 없었기 때문이었습니다. 
  • 어느 정도 객체지향을 공부하고 보니 "그래, 이 객체에 이 역할을 부여해야지"라는 생각이 들기 시작했는데, 이제 문제는 "얘를 어디에 배치하지? "였습니다. 
  • 우리가 흔히 접하는 계층형 아키텍처(레이어드 아키텍처)에서도 객체를 어떻게 분류하고 조직화(패키지) 할지는 너무나 각양각색이었고, DTO를 만들어야 할 때마다 "얘를 어느 계층까지 끌고 가야 되는 거지?"라는 생각이 들게 되었습니다.

그렇게 이것저것 검색을 해보면서 클린 아키텍처에 대해 관심을 갖게 되었고, 지원을 하게 되었습니다.

 

1. 기존 개발의 문제점 인지

계층형 아키텍처는 우리에게 너무나도 익숙합니다. 대부분의 튜토리얼, 개발 서적 등에서 가장 접하기 쉬운 것이 전통적인 계층형 아키텍처입니다. 서비스를 개발할 때 이런 계층형 아키텍처를 적용하는 것이 당연시되지만, 이로 인해 발생하는 여러 문제점들이 있었습니다.

  • 객체의 분류 및 조직화: 저의 경우에는 위에서 얘기한 것처럼, 계층을 나누긴 나눴는데 세부 클래스들을 다시 어떤 패키지로 묶을지가 애매하다고 느꼈습니다. Java에서 "default" 접근 제어자를 같은 패키지 (하위 패키지도 안됨)까지 한정한 이유에 대해 생각하면 더 머리가 아파집니다.
  • 데이터베이스 주도 설계 유도: 계층형 아키텍처를 사용하다 보면 자연스레 데이터베이스 주도 설계를 하게 됩니다. 웹 -> 도메인 -> 영속성 레이어로 이어지는 흐름 속에서, 일반적으로 애플리케이션의 행동보다는 상태를 주체로 설계하고 개발하게 됩니다. 테이블 레이아웃을 설계하고, 영속성 레이어를 구현한 뒤 도메인, 웹 레이어 구현으로 이어지게 됩니다. 이렇게 하면 정작 비즈니스를 이끌어가는 행동이 뒷전이 되어버립니다.
  • 계층 건너뛰기: 웹 계층에서 도메인 계층을 건너뛰고, 바로 영속성 계층을 접근할 수 있게 됩니다. 이러한 쉬운 길을 택하다 보면 어느새 계층 간 경계가 모호해지고, 도메인 로직이 여기저기 퍼지게 됩니다. 실제로 회사에서 레거시 코드를 보거나 SI 외주업체에서 만들고 도망간 코드를 보면 온갖 비즈니스 로직이 컨트롤러에 작성한 상황을 마주하게 됩니다.
  • 테스트 난이도 상승: 웹 계층에 도메인 로직이 섞여 들어가게 되면 단위 테스트가 복잡해지고, 테스트 시 영속성 계층도 모킹해야 하는 일이 생겨납니다. 
  • 모호한 유스케이스: 하나의 도메인 계층 서비스에서 다양한 유스케이스를 처리하는 경우, 코드를 수정하거나 추가할 때 위치 찾기가 어려워집니다. 이러한 이유로 여러 사람이 동시에 작업하는 것도 어려워집니다.

 

2. 클린 아키텍처에서의 해결 방안

레이어드 아키텍처에서도, 계층에 대해 이해하고 빌드 도구나 테스트 도구 등을 통해 제약을 강화하면 위의 문제들을 해결할 수 있습니다. 여기서는 스터디를 진행하면서 학습하게 된 클린 아키텍처에서의 해결 방안들에 대해 작성해 보겠습니다.

  • 객체의 위치 결정: 레이어드 아키텍처에서는 주로 Presentation Layer, Business Logic Layer, Data Access Layer로 나뉩니다. 그러나 이렇게 3 계층으로 나뉘어진 아키텍처에서 객체를 어디에 위치시켜야 하는지를 결정하는 것은 쉽지 않습니다. 클린 아키텍처에서는 이 문제를 엔티티, 유스케이스, 인터페이스 어댑터, 프레임워크와 드라이버라는 4가지 계층으로 나누어 해결하였습니다. 각 계층은 명확한 역할과 책임을 가지고 있으며, 이를 이해하면 객체의 위치 결정에 대한 문제를 해결할 수 있습니다.
  • 객체의 분류 및 조직화: 클린 아키텍처에서는 어느 정도 명확한 객체의 위치를 제공합니다. 외부에 의해 호출되는(인고잉) 어댑터와 포트, 그리고 외부로 나가는 호출(아웃고잉) 어댑터와 포트, 그리고 애플리케이션 코어에 해당하는 유스케이스, 엔티티 계층으로 그 역할이 분명하게 나뉘어 있습니다. 이러한 계층 구조로 패키지를 구성하면 개발 직무 이외의 사람과의 소통에서도 어느 지점에 새로운 기능을 추가하고 변경할지 명확히 할 수 있습니다.

  • DTO의 범위: 클린 아키텍처에서는 의존성에 대한 규칙이 명확합니다. "의존성은 내부로만 향한다." 이 원칙을 준수하면서 개발을 하려고 보면, DTO 객체뿐만 아니라 다른 객체에 대해서도 의존성을 명확히 할 수 있습니다.
  • 도메인 주도 설계 : 클린 아키텍처에서는 애플리케이션 코어라고 부르는, 엔티티와 유스케이스가 말 그대로 애플리케인션의 핵심으로 다루어집니다. 오직 해결하려는 도메인의 문제에만 집중하여 애플리케이션 코어단을 유지하기 때문에, DB와 웹 이런 것들은 세부사항으로 분류합니다.
  • 계층 간의 명확한 경계 나누기 : 클린 아키텍처에서는 각 계층 간의 경계를 명확하게 나누고 그에 따라 참조할 수 있는 의존성을 관리합니다. Java의 접근 제어자와 패키지 구조, 추가로 멀티 모듈 기능을 통해 코드베이스를 나눈다면 컨트롤러에서 영속성 계층을 직접 참조하는 일을 막을 수 있습니다.
  • 테스트 용이성 : 클린 아키텍처에서는 각 계층은 독립적이며, 따라서 단위 테스트를 쉽게 작성할 수 있습니다. 모킹이 필요한 경우에도, 계층의 경계에서만 이루어져 복잡성을 줄일 수 있습니다.
  • 명확한 유스케이스 : 클린 아키텍처는 유스케이스를 명확히 정의하고, 각 유스케이스를 독립적으로 관리합니다. 이로 인해 코드 위치를 찾기 어렵거나 여러 사람이 동시에 작업하기 어려운 문제를 해결합니다.

 

3. 스터디를 통해 배운 것

  이 스터디를 하면서 무엇을 배웠냐?라고 물어보면 의존성 관리라고 말하고 싶습니다. 책을 읽다 보면 자주 반복되는 키워드와 주제들이 있었습니다. 이러한 키워드와 주제를 관통하는 핵심은 "의존성을 관리하라."가 아닌가 싶습니다. 결국 클린 아키텍처에서 자랑하는 장점들은 모두 뚜렷한 경계를 나누고, 의존성을 관리하였을 때 누릴 수 있는 것들이기 때문이었습니다.

  하지만 그게 꼭 클린 아키텍처여야 하는가? 에 대해선 좀 의문이 들었습니다. 이미 많은 빅테크 기업들에서도 클린 아키텍처 없이 시스템을 운영하고 있다 보니 "꼭 필요한가?"라는 생각과, 저자가 자신의 경험을 토대로 말하는 것처럼, 그 목적을 이루려고 하다 보면 결국은 시스템의 아키텍처가 클린아키텍처에 수렴하게 되는 건지 궁금증이 생겨났습니다. 이 궁금증은 이제 직접 소스도 보고 구현도 해보면서 더 생각해보려고 합니다.

 

  스터디에서 정말 학습 외적으로도 많은 도움을 받았다고 생각합니다. 많은 지원자들 중에서 좋은 기회를 얻은 것에 정말 감사함도 느끼고, 제가 다른 스터디원들에게 도움이 되었을까라는 조금 미안한 마음도 듭니다. 회사에서는 경험해보지 못한 서로 의견을 얘기하며 학습하는 것에 재미도 알게 되고, 각자 테스트 하는 방식, 코드를 작성하는 방식들에 대해서도 얘기하는 것이 참 재미있는 경험이었습니다. 앞으로도 기회가 된다면 다양한 스터디에 참여해보고 싶단 생각이 들었습니다. 이 글을 스터디원분들 중 보실 분이 있을지는 모르겠지만, 정말 모두 감사하다는 말을 전하고 싶습니다!