4 분 소요

만들면서 배우는 클린 아키텍쳐 1장 정리

저자 서문

우선 전통적인 계층형 아키텍처와 육각형 아키텍처에 대한 이야기가 먼저 나옵니다.

요약하자면 전통적인 계층형 아키텍처는 문제가 많고, 이를 해결하기 의헤 육각형 아키텍처를 사용해야 한다는 것 같습니다.

추천사

육각형 아키텍처에 대해 간단하게 요약해서 설명을 해줍니다.

‘포트와 어댑터(Ports and Adapters)’ 패턴과 육각형 아키텍처는 같은 의미를 지니고 있는 것 같습니다.

그리고 전통적인 계층형 아키텍처와 육각형 아키텍처에 대해 간략하게 설명을 해주는데 아직 완전히는 이해할 수 없지만 이 책을 다 읽고 나서 다시 보면 이해할 수 있을 것 같습니다.

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

계층형 아키텍처는 전통적인 웹 애플리케이션 구조로써 웹 계층, 도메인 계층, 영속성 계층으로 나뉘어집니다.

맨 윗단의 웹 계층에서는 사용자의 요청을 받아 도메인 또는 비지니스 계층이 있는 서비스로 요청을 보냅니다.

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

사실 계층형 아키텍처는 잘만 사용한다면 견고한 아키텍처 패턴입니다.

다만 이를 이용하는 사용자들이 제대로 사용하지 못하면 문제가 발생하는데 계층형 아키텍처는 이러한 문제점에 수많은 허점들을 노출하여 아키텍처에 문제가 발생하기 쉽습니다.

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

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

웹 계층은 도메인 계층에, 도메인 계층은 영속성 계층에 의존하기 때문에 자연스레 아키텍처 전체가 영속성 계층, 즉, 데이터베이스에 의존하게 됩니다.

이것에 문제점은 우리가 애플리케이션을 만들 때, 도메인을 위주로 설계하는 것이 자연스럽기 때문입니다.

우리가 무엇인가를 만들려고 할 때, 상태(영속성, 데이터베이스)를 먼저 생각해서 모델링을 하는 것이 아니라 행동(비지니스 로직, 도메인)을 중심으로 모델링을 합니다.

그런데 전통적인 계층형에서는 이와 반대로 되기 쉽기 때문에 문제가 발생합니다.

우리는 결국에 회사에서 일을 하기 때문에 비지니스에 초점을 맞춰야 하고, 그러기 위해서는 도메인 로직을 먼저 만들고 이를 토대로 영속성 계층과 웹 계층을 만들어야 합니다.

즉, 도메인이 중심이 되야한다는 것입니다.

데이터베이스 중심적인 아키텍처가 만들어지는 가장 큰 원인으로 ORM 프레임워크를 들 수 있습니다.

ORM 프레임워크 자체는 문제가 없지만 이를 사용하는 개발자는 ORM 프레임워크를 이용해 데이터베이스 중심적인 아키텍처를 구성하기 쉽습니다.

데이터베이스 중심적인 아키텍처를 구성하게 되면 엔티티가 레포지토리와 강한 결합을 유발하여 별개가 되기 힘듭니다.

즉, 이 상황에서 리포지토리를 메모리에서 데이터베이스로 교체한다면 엔티티의 로직도 수정해야하는 일이 발생할 수 있습니다.

도메인 로직과 영속성 코드는 별개로 가야 데이터베이스를 교체하더라도 도메인 로직에는 손을 되지 않기 때문에 쉽게 바꿀 수 있습니다.

책을 읽으면서 느낀 점

여기서 생각해보니 제가 예전에 C++로 데스크톱 애플리케이션(주소록, 단어장, 가계부, 명함철, 메모장 등)을 만들 때도 항상 도메인을 먼저 설계한 다음(유즈케이스 시나리오 등)에 그 로직을 짜고, 메인테스트 시나리오 짜고 콘솔창을 통해 비지니스 로직이 제대로 돌아가는지 확인을 먼저하였습니다.

이 후 여기에 메모리에 저장하는 로직을 추가하고, MFC를 이용해 웹 계층에 해당하는 View를 만들었습니다.

그리고 여기에 기존에 메모리에 저장하는 방식(파일)에서 MySQL을 이용하여 데이터베이스에 저장하는 방식으로 바꿨습니다.

책에서 이 구절을 읽으면서 이때까지 진행했던 프로젝트도 항상 도메인 모델 구축이 최우선이었다는 것을 새삼스럽게 깨닫게 되었습니다.

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

전통적인 계층형 아키텍처를 이용하다 보면 쉬운 길로 가려고 하는 유혹에 빠지게 됩니다.

이렇게 코드를 계속해서 짜게 되고 시간이 흘러 이러한 상황이 축적되면 이제 웹이나 도메인이나 영속성 계층의 경계가 허물어지게 되고, 구분 자체가 무의미해지는 경우가 발생하게 됩니다.

그래서 로직에는 문제가 없더라도 이러한 구분이 무너지는 로직을 세우지 않도록 강제하는 방법이 있습니다.

책을 읽으면서 느낀 점

예전에 메모장 프로젝트를 구현할 때 view에서 처리할 로직과 model에서 처리할 로직을 제대로 구분하지 않고, 왠만한 건 다 view에서 처리하도록 설계한 경험이 있습니다.

이러한 코드가 누적되다 보니 다음 설계도 이와 비슷하게 되었고, 결국에 도메인과 view의 차이가 모호해졌습니다.

이렇게 되다 보니 나중에 다른 기능을 추가했을 때, 기존 코드가 문제가 되어 코드를 수정해야하는데 어디서부터 손을 봐야할 지 힘들었던 경험이 있습니다.

즉, 당장에는 쉽게 갈 수 있지만 결국에 나중에 문제가 발생하거나 유지 보수 관리 및 변경을 할 때 굉장히 어려워질 수 있기 때문에 애초에 이러한 일이 일어나지 않도록 막는 것이 좋은 것 같습니다.

테스트하기 어려워진다.

웹 계층에서 도메인을 거치치 않고, 영속성 계층에 바로 접근하는 경우, 즉, 로직이 단순해서 계층을 뛰어 넘어서 접근하는 경우 두 가지 문제가 발생할 수 있습니다.

첫째, 웹 계충에서 도메인 로직을 구현하게 된다는 것이고, 이게 처음에는 하나일지 모르나 시간이 흐르면서 여러 도메인 로직이 웹계층에서 구현될 수 있습니다.

둘째, 이렇게 되면 테스트하기가 너무 어려워져서 결과적으로 테스트를 안하게 됩니다.

책을 읽으면서 느낀 점

완전히 같은 내용은 아니지만 View와 Controller와 Model의 구분이 명확해야 하는데 이것이 모호할 경우 아까처럼 View에서 Model로직을 처리하기 때문에 코드가 복잡해지고 나중에 유지보수하기 힘들고, 문제가 발생해도 문제를 발견하기 힘들어집니다.

메모장에서 캐럿의 이동을 구현할 때 MVC를 제대로 구분하지 못해서 힘들었던 경험이 생각났습니다.

유스케이스를 숨긴다.

개발자들은 새로운 코드를 짜는 것보다 기존 코드를 개선하는데 더 많은 시간을 소모합니다.

즉, 유지보수를 하는데 시간을 더 많이 쓰기 때문에 아키텍처를 바탕으로 코드를 빠르게 탐색할 수 있어야 합니다.

그러나 계층형 아키텍처에서는 도메인 로직이 여러 계층에 걸쳐서 흩어져있기 때문에 새로운 기능을 추가할 적당한 위치나 변경점을 찾기 매우 어려워집니다.

이렇게 구분이 명확하기 않으면 한 계층이 너무 비대해지게 되고, 그렇게 되면 우리가 정의한 유스케이스를 담당하는 서비스를 찾기 어려워집니다.

그래서 유스케이스 하나에 특화된 도메인 서비스를 정의할 필요가 있습니다.

책을 읽으면서 느낀 점

비대하고 모호한 만능 서비스보다는 유스케이스 당 필요한 서비스를 각자 구현하는 것이 나중에 찾기가 편한 것 같습니다.

프로젝트가 커지다 보면 구현할 떄 계속해서 여러 기능이 추가될 수 있는데 이 때마다 특화된 서비스를 따로 구현해주는 것이 만능 서비스를 구현해 하나에서 다 처리하는 것보다 나은 것 같습니다.

동시 작업이 어려워진다.

‘맨머스 미신’에서 ‘지연되는 소프트웨어 프로젝트에 인력을 더하는 것은 개발을 늦출 뿐이다.’라는 말이 있습니다.

왜냐하면 계층형 아키텍처에서는 각 계층의 로직들이 구분되지 않고 흩어져 있기 때문에 개발자들이 각자 명확하게 역할을 구분하여 작업을 할 수 없기 때문입니다.

이렇게 되면 서로 구현했던 로직이 충돌하여 더 큰 문제가 발생할 수 있기 때문에 개발자들은 다른 개발자가 로직을 구현하는동안 기다려야 하는 상황이 발생할 수도 있습니다.

애초에 계층이 명확히 구분된 아키텍처를 구성했다면 이러한 문제를 방지할 수 있습니다.

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

계층형 아키텍처에서는 강제성이 없기 때문에 까딱 잘못하면 잘못된 방향으로 가기 쉽습니다.

하지만 이러한 문제점을 항상 염두해 두면 유지보수하기 편한 아키텍처를 구성할 수 있습니다.

댓글남기기