Home 1장. 계층형 아키텍처의 문제는 무엇일까?
Post
Cancel

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

소개

image

만들면서 배우는 클린 아키텍처 책을 읽고 정리하며 소감을 적는 포스트입니다.

계층형 아키텍처의 문제점

image

웹 계층, 도메인 계층, 영속성 계층으로 구성된 전통적인 웹 애플리케이션 구조

계층형 아키텍처는 맨 위의 계층에서 요청을 받아 도메인 계층에 있는 서비스로 요청을 보낸다.

서비스에서는 필요한 비즈니스 로직을 수행하고, 도메인 엔티티의 현재 상태를 조회하거나 변경하기 위해 영속성 계층의 컴포넌트를 호출한다.

계층을 잘 이해하고 구성한다면 다른 계층에 영향을 주지 않고 독립적으로 관리가 가능하다.

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

데이터베이스 주도 설계를 유도한다.

전통적인 계층형 아키텍처의 토대는 데이터베이스이다.

하지만 우리는 상태(State)가 아니라 행동(behavior)을 중심으로 모델링을 한다. 어떤 어플리케이션이든 상태가 중요한 요소이긴 하지만 행동이 상태를 바꾸는 주체이기 때문에 행동이 비즈니스를 이끌어 나간다.

그동안 만들어 본 유스케이스를 떠올려보면 도메인 로직보다는 데이터베이스의 구조를 먼저 생각하고, 이를 토대로 도메인 로직을 구현했을 것이다.

전통적인 계층형 아키텍처에서는 합리적인 방법이지만 비즈니스 관점에서는 전혀 맞지 않는 방법이다.

그래서 다른 무엇보다 도메인 로직을 먼저 만들어야 한다. 그래야 로직을 제대로 이해했는지 확인할 수 있다.

데이터베이스 중심적인 아키텍처를 만드는 가장 큰 원인은 ORM(object-relational mapping)이다.

image

도메인 계층에서 데이터베이스 엔티티를 사용하는 것은 영속성 계층과의 강한 결합을 유발한다.

위 그림과 같이 ORM에 의해 관리되는 엔티티들은 일반적으로 영속성 계층에 둔다.

계층은 아래 방향으로만 접근 가능하기 때문에 도메인 계층에서는 엔티티에 접근 할 수 있다. 그렇게 되면 영속성 계층과 도메인 계층 사이에 강한 결합이 생긴다.

이는 도메인 로직을 구현하면서 즉시로딩(eager loading)/지연로딩(lazy loading), 데이터베이스 트랜잭션, 캐시 플러시(flush) 등등 영속성 계층과 관련된 작업을 계속해야만 한다.

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

계층형 아키텍처는 같은 계층에 있는 컴포넌트나 아래에 있는 계층에만 접근이 가능하다. 이 규칙 외의 다른 규칙은 강제하지 않는다. 그래서 상위 계층에 위치한 컴포넌트에 접근해야 한다면 간단하게 컴포넌트를 아래로 내려버리는 경우가 생긴다.

image

영속성 계층에서는 모든 것에 접근 가능하기 때문에 시간이 지나면서 점점 비대해진다.

영속성 계층은 수년에 걸친 개발과 유지보수로 위 그림과 같이 될 가능성이 많다.

테스트하기 어려워 진다.

계층형 아키텍처에서 나타나는 일반적인 현상은 계층을 건너뛰는 것이다.

엔티티의 필드를 단 하나만 조작하면 되는 경우에 웹 계층에서 바로 영속성 계층에 접근하면 도메인 계층을 건드릴 필요가 없지 않을까?

image

도메인 계층을 건너뛰는 것은 도메인 로직을 코드 여기저기에 흩어지게 만든다.

위와 같이 계층을 무시하게 되면 두가지 문제가 생긴다.

첫 번째는 단 하나의 필드를 조작하는 것에 불과하더라도 도메인 로직을 웹 계층에 구현하게 된다는 것이다.

유스케이스가 확장 된다면 더 많은 도메인 로직을 웹 계층에 추가해서 핵심 도메인 로직들이 퍼저나갈 확률이 높다.

두번째 문제는 웹 계층 테스트에서 도메인 계층뿐만 아니라 영속성 계층도 모킹(mocking) 해야 한다는 것ㅇ디ㅏ.

이렇게 되면 단위 테스트의 복잡도가 올라가게 된다.

유스케이스를 숨긴다.

개발자는 새로운 유스케이스를 구현하는 새로운 코드를 짜는 것을 선호한다. 그러나 새로운 코드를 짜는 시간보다 기존 코드를 바꾸는데 더 많은 시간을 쓰게 된다.

계층형 아키텍처에서 도메인 로직이 여러 계층에 흩어지게 되면 새로운 기능을 추가할 적당한 위치를 찾는 일이 어려워 진다.

image

넓은 서비스는 코드 상에서 특정 유스케이스를 찾는 것을 어렵게 만든다.

넓은 서비스는 영속성 계층에 많은 의존성을 갖게 되고, 다시 웹 계층의 많은 컴포넌트가 이 서비스에 의존하게 된다.

동시 작업이 어려워 진다.

“지연되는 소프트웨어 프로직트에 인력을 더하는 것은 개발을 늦출 뿐이다.”
«맨머스 미신: 소프트웨어 공학에 관한 에세이», 프레더릭 P.브룩스

모든 상황에서 50명 정도 되는 큰 규모의 개발팀이 10명 정도 되는 작은 규모의 개발팀보다 5배 빠를 거라고 기대할 수는 없다. 하지만 적절한 규모에서는 인원을 더 투입하면 더 빨리진다고 기대 할 수 있다.

이러한 기대를 충족하기 위해서는 아키텍처가 동시 작업을 지원해야 하지만 계층형 아키텍처는 이런 측면에선 도움이 되지 않는다.

계층형 아키텍처는 모든 것이 영속성 계층 위에 만들어지기 때문에 영속성 계층을 먼저 개발해야 한다. 그렇기 때문에 특정 기능을 동시에 한명의 개발자만 작업이 가능하다.

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

.NET Serilog 사용법

2장. 의존성 역전하기