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

계층형 아키텍처란?

계층(layer)으로 구성된 (웹) 애플리케이션은 전통적인 웹 애플리케이션 구조를 말한다.

크게보면 웹 → 도메인 → 영속성 으로 구성된 3계층으로 많이 표현되는데

  • 웹 : 요청을 받아서 서비스로 요청을 보냄
  • 도메인(비즈니스) : 필요한 비즈니스 로직을 수행하고 엔티티의 현재 상태를 조회하거나 변경하기 위해 영속성 계층의 컴포넌트 호출
  • 영속성 : 엔티티, 리포지터리 등 데이터베이스 관련 컴포넌트

오랫동안 사용한만큼 견고한 아키텍처 패턴이 맞고 잘 이해하고 사용하면 각 계층에 독립적으로 로직을 작성하고 기존 기능에 영향없는 기능 추가도 가능하다.

다만, 계층형은 코드에 나쁜 습관들이 스며들기 쉽고 시간이 지날수록 유지보수가 힘들어지는 단점들이 있다.

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

계층형의 토대는 데이터베이스라서 웹은 도메인을, 도메인은 영속성을 의존하다보니 모두 데이터베이스에 의존하게 된다.

보통 애플리케이션을 만들때 비즈니스를 관장하는 규칙이나 정책을 반영한 모델을 만드는데 이때 우리는 상태(state)가 아니라 행동(behavior)을 중심으로 모델링한다.

하지만 계층형의 설계는 보통 데이터베이스를 토대로 도메인 로직을 구현하는 방식이라서 아키텍처의 구현으로는 맞더라도 비즈니스 관점에선 다르다.

가장 중요한 도메인 로직을 먼저 만들어야 로직을 제대로 이해하는지 확인하고 이를 토대로 웹과 영속성 계층을 설계할 수 있기 때문이다.

ORM(object-relational-mapping, 객체 관계매핑) 프레임워크(JPA, 하이버네이트 등)를 사용하면 비즈니스 규칙을 영속성 관점에 섞고 싶은 생각이 들게 된다.

ORM에 의해 관리되는 엔티티들은 일반적으로 영속성 계층에 두고 도메인계층에선 엔티티에 접근가능한데 이러한 구조는 영속성 계층과 도메인 계층 사이에 강한 결합을 만들게 된다.

서비스에서 영속성 모델을 마치 비즈니스 모델처럼 사용하다보면 도메인 로직뿐만 아니라 영속성 계층과 관련된 작업들도 해줘야 한다.

영속성 코드가 사실상 도메인 코드에 녹아들면서 둘 중 하나만 바꾸는게 어려워져서 계층형의 목표와 대치되는 코드가 된다.

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

계층형 아키텍처는 특정한 계층에서는 같은 계층에 있는 컴포넌트나 아래에 있는 계층에만 접근 가능하다는 규칙이 있다.

만약 상위 계층에 위치한 컴포넌트에 접근해야 한다면? 컴포넌트를 계층 아래로 내려버리면 된다. 한번은 괜찮을 수 있다. 근데 2번, 3번이 넘고 나 뿐만 아니라 다른 동료들도 그렇게 하게 되면?

유틸리티나 헬퍼 컴포넌트 등이 아래 계층으로 내려오게 되면 영속성 계층은 모든 것에 접근 가능하기 때문에 시간이 지날 수록 점점 비대해 질 것이다.

테스트하기 어려워진다.

계층형 아키텍처에서 계층을 건너뛰도록 하는 경우도 있다. 엔티티의 필드를 딱 하나만 조작하면 될 경우에 웹 계층에서 바로 영속성 계층에 접근하면 도메인 계층을 건너 뛰게 된다. 이런 경우 크게 두가지 문제가 발생하는데

  1. 도메인 로직을 웹 계층에 구현하게 된다.
    만약 유스케이스가 확장된다면 더 많은 도메인 로직이 웹 계층에 추가되면서 애플리케이션 전반으로 책임이 섞이고 핵심 도메인 로직들이 퍼져나갈 수 있다.
  2. 웹 계층 테스트에서 도메인 계층뿐만 아니라 영속성 계층도 모킹(mocking)해야 한다.
    이 경우 단위 테스트의 복잡도가 올라가고 이렇게 복잡한 설정을 할 시간이 없어서 테스트를 안하게 되는 시작이 된다.

유스케이스를 숨긴다.

기능을 추가하거나 변경할 적절한 위치를 찾는 일이 빈번하기 때문에 ㅐ아키텍처는 코드를 빠르게 탐색하는데 도움이 돼야 한다.

계층형 아키텍처에서는 도메인 로직이 여러 계층에 걸쳐 흩어지기 쉬운 환경이라 유스케이스가 “간단”해서 도메인 계층을 생략하면 웹 계층에 존재할 수도 있고, 도메인과 영속성 모두에 접근할 수 있도록 컴포넌트의 계층을 내리면 영속성 계층에 존재할 수도 있다.

이런 경우 새로운 기능을 추가할 적당한 위치를 찾기 어려워지고 여러 개의 유스케이스를 담당하는 아주 넓은 서비스가 만들어질 수도 있다.

넓은 서비스는 영속성 계층에 많은 의존성을 갖게되고, 웹 레이어의 많은 컴포넌트가 이 서비스에 의존하게 된다. 서비스는 점점 더 복잡해지고 테스트하기도 어려워진다.

동시 작업이 어려워진다.

새로운 기능을 추가하기 위해 3명의 개발자가 있을때 각 계층에 각각의 기능을 동시에 개발할 수 있을까?

계층형에선 영속성 계층 위에 모든 것이 만들어지기 때문에 영속성 계층을 먼저 개발ㄹ해야 하고, 그 다음에 도메인 계층, 웹 계층을 만들어야 한다.

동시에 한꺼번에가 아니라 한번에 한명의 개발자만 일할 수 있는 것이다.

또한 넓은 서비스가 있다면 서로 다른 기능을 동시에 작업하기 어려운데 병합 충돌(merge conflict)이나 롤백이 필요한 문제가 발생할 수 있다.

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

올바르게 구축하고 몇 가지 추가적인 규칙들을 잘 적용한다면 계층형 아키텍처는 유지보수하기 매우 쉬워지며 코드를 쉽게 변경하거나 추가할 수 있다.

하지만 잘못된 방향으로 흘러가기 쉽다보니 계층형 아키텍처로 만들든 다른 아키텍처 스타일로 만들든, 지름길을 택하지 않고 유지보수하기에 더 쉬운 솔루션을 만드는 데 도움이될 것이다.

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

https://yoo0926.github.io/2023/02/25/book/clean-architecture/clean-1/

Author

Jaeyong Yoo

Posted on

2023-02-25

Updated on

2023-06-10

Licensed under

댓글