Posts [만들면서 배우는 클린 아키텍처] 만들면서 배우는 클린 아키텍처
Post
Cancel

[만들면서 배우는 클린 아키텍처] 만들면서 배우는 클린 아키텍처

image

‘만들면서 배우는 클린 아키텍처’ 기술 서적에 대해 학습했던 내용을 정리하기 위한 목적의 TIL 포스팅입니다.🙆‍♂️

시작하기전 추천사 (객체지향의 사실과 오해 저자 조영호)

  • 클린아키텍처의 핵심은 의존성 방향으로 비즈니스 로직이 외부 요소에 존재하지 않고 프레젠테이션 계층과 데이터 소스 계층이 도메인 계층에 의존하도록 만들어야 한다는 것이다.
  • 애플리케이션은 비즈니스 관심사를 다루는 내부(inside)와 기술적인 관심사를 다루는 외부(outside)로 분해된다. 여기서 외부에 포함된 기술적인 컴포넌트를 어댑터(adapter)라 부르고, 어댑터가 내부와 상호작용하는 접점을 포트(port)라 부른다.
  • 에릭 에반스는 «도메인 주도 설계»에서 “도메인 주도 설계의 전제 조건은 도메인 구현을 격리시키는 것이다.” 라는 말로 내부와 외부의 분리를 강조했다.도메인을 기반으로 애플리케이션을 구축하기 위해선 육각형 아키텍처처럼 경계와 의존성을 강제할 수 있는 아키텍처를 채택하는 것이 중요하다는 사실을 깨달았다.
  • 즉, 육각형 아키텍처는 도메인 중심의 개발을 위해 필요한 아키텍처라고도 볼 수 있을것이다.

1장 - 계층형 아키텍처의 문제는 무엇일까?

  • 저자의 경험에 의하면 계층형 아키텍처의 문제점은 코드에 나쁜 습관들이 스며들기 쉽게하고 시간이 지날수록 소프트웨어를 점점 더 변경하기 어렵게 만드는 수많은 허점들을 노출한다는 것이다.

계층형 아키텍처는 데이터베이스 주도 설계를 유도한다.

  • 웹 -> 도메인 -> 영속성 으로 흘러가는 의존성 방향은 자연스럽게 데이터베이스에 의존하게 만든다. 즉 모든 것이 영속성 계층을 토대로 만들어진다.
  • ORM 프레임워크(JPA)의 사용은 비즈니스 규칙을 영속성 관점과 섞고 싶은 유혹을 쉽게 받는다.

image 출처: https://dgle.dev/clean-arch-1/

  • 위 이미지에서처럼 도메인 계층에선 영속성 계층의 엔티티에 접근하여 사용하기 마련이게 된다. 그렇게 되면 두 계층 간의 강한 결합이 생기게되고 서비스는 영속성 모델을 비즈니스 모델로처럼 사용하게 되고 이로 인해 도메인 로직뿐만이 아닌 즉시로딩, DB트랜잭션 등 영속성 계층과 관련된 작업들을 해야만 한다.

  • 우리는 상태(state)가 아닌 행동(behavior)을 중심으로 모델링한다. 어떤 애플리케이션이든 상태가 중요한 요소긴하지만 행동이 상태를 바꾸는 주체이기 떄문에 행동이 비즈니스를 이끌어간다.
  • 비즈니스 관점에선 영속성계층보단 도메인 로직을 먼저 만들어야 한다. 그래야만 우리가 로직을 제대로 이해했는지 확인할 수 있고 이를 기반으로 영속성 계층과 웹 계층을 만들어야 한다.
    • 나의 생각🧐: 현재 실무에서 보통 API 스펙을 먼저 정의후에 비즈니스 로직을 구현하게 되는것 같다. 그 스펙에 맞춰 클라이언트(FE, ME) 개발자들이 화면 구현을 진행하게 되는데 위의 방법으로 적용해봐도 좋을것 같다.

지름길을 택하기 쉬워진다.

image 출처: https://dgle.dev/clean-arch-1/

  • 레이어드 아키텍처에서 만약 상위 계층에 위치한 컴포넌트에 접근해야 한다면 간단하게 해당 컴포넌트를 계층 아래로 내려버리면 된다.
  • 그럼 위 이미지처럼 영속성 계층이 비대해지게 될 것이다.
  • 아키텍처 관점에서 강제하지 않으면 (코드리뷰 수준이 아닌 빌드가 안되도록 하는 수준으로) 여러가지 핑계로(마감이 얼마 안남았다는 등) 아키텍처는 유지보수하기 어렵게되버릴것이다.
  • 모두 그렇다. 한 번은 괜찮을것이다. 근데 한 번하게 되면 누군가 쉽게 또 하게될것이다..

테스트하기 쉬워진다

image 출처: https://dgle.dev/clean-arch-1/

  • 계층형 아키텍처에서 일반적으로 계층을 건너뛰는 변화가 나타난다.
    • 엔티티의 필드를 단 하나만 조작하면 되는 경우 웹 계층에서 바로 영속성 계층에 접근하는 것이다. (도메인 계층을 건너띄고)
  • 두 가지 문제점이 있다.
    • 1)도메인 로직을 웹 계층에 구현하게 되는것. 유스케이스가 확장되면 웹 계층에 더 많아질것이고 애플리케이션 전반에 걸쳐 책임이 섞이고 도메인 로직들이 퍼져나가 유지보수성이 떨어지게될것
    • 2)웹 계층 테스트에서 도메인 계층뿐만 아닌 영속성 계층도 모킹하게 되어 단위 테스트 복잡도가 올라가고 테스트를 작성하지 않게되는것. 웹 컴포넌트의 규모가 커지면 다양한 영속성 컴포넌트에 의존성이 많이 쌓이며 테스트 복잡도는 더 올라갈것이다..

유스케이스를 숨긴다

image 출처: https://dgle.dev/clean-arch-1/

  • 계층형 아키텍처는 도메인 서비스의 ‘너비’ 에 관한 규칙을 강제하지 않다보니 위 이미지처럼 여러 개의 유스케이스를 담당하는 아주 넓은 서비스가 만들어지기도 한다.
  • 넓은 서비스는 영속성 계층에 많은 의존성을 갖게 되고, 다시 웹 레이어의 많은 컴포넌트가 이 서비스에 의존하게 된다. 그럼 서비스를 테스트하기도 어려워지고 작업해야할 유스케이스를 책임지는 서비스를 찾기도 어려워진다.
  • 고돌 특화된 좁은 도메인 서비스가 유스케이스 하나씩만 담당하게 한다면 위와 같은 작업들은 수월해질것이다. ex. UserService 에서 사용자 등록 유스케이스를 찾는 대신 RegisterUserService 를 바로 열어서 작업을 시작하는 것처럼 말이다.

동시 작업이 어려워진다.

  • 개발 인원이 늘어난다했을때 생산성이 그만큼 늘어나려면 아키텍처가 동시 작업을 지원해야 한다. 하지만 이는 쉽지 않다..
  • 그리고 계층형 아키텍처는 그다지 위의 관점에서 도움되지 않는다. 모든 것이 영속성 계층 위에 만들어지기에 영속성 계층 -> 도메인 계층 -> 웹 계층 의 순으로 이뤄져야하고 새로운 유스케이스를 추가해야한다면 동시에 한 명의 개발자만 작업할 수 있게 된다.
  • DB 주도 설계는 영속성 로직이 도메인 로직과 너무 뒤섞여서 각 측면을 개별적으로 작업할수 없기 때문이다.
  • 또한 코드에 넓은 서비스가 있다면 같은 서비스를 동시 편집하는 상황이 발생하는 일이 잦게될것이고 병합 충돌(merge conflict)과 잠재적으로 이전 코드로 되돌려야 하는 문제를 야기하게 된다.

유지보수 가능한 소프트웨어를 만드는데 어떻게 도움이 될까?

  • 물론 계층형 아키텍처를 올바르게 구축후 몇가지 추가적인 규칙들을 적용하면 유지보수하기 매우 쉬워지며 코드를 쉽게 변경 or 추가할 수 있게 된다.
  • 그러나 앞에서 살펴봤듯이 계층형 아키텍처는 많은것들이 잘못된 방향으로 흘러가도록 용인한다. 아주 엄격한 자기훈련 없이는 시간이 지날수록 품질이 저하되고 유지보수하기 어려워지기 쉽다. 그리고 마감일이 새로 픽스될때마다 이러한 자기훈련은 느슨해질것이다.
  • 계층형 아키텍처로 만들든 다른 아키텍처 스타일로 만들든, 계층형 아키텍처의 함정을 염두에 두면 지름길을 택하지 않고 유지보수하기 더 쉬운 솔루션을 만드는데 도움이될 것이다.

2장 - 의존성 역전하기

Reference

This post is licensed under CC BY 4.0 by the author.

[AWS] AWS TGC 내용 정리

-