Architecture/DesignPatterns 14

왜 헥사고날인가? 구조적 고민과 실천의 기록

실무에서 주로 레이어드 아키텍처(Layered Architecture)를 자연스럽게 사용했습니다. Controller, Service, Repository처럼 층을 나누고 각 레이어에서 역할을 나누는 방식은 익숙하고 구조를 파악하기도 쉬웠습니다.하지만, 시간이 지날수록 위의 구조에 대해 불편함이 생겼습니다.도메인 로직이 Service나 Repository에 흩어져 도메인 규칙이 명확하지 않음비즈니스 로직이 상위 레이어에 의존적으로 퍼짐Kafka, 외부 API, 배치 등 새로운 인프라를 기존 구조에 끼워 넣기 애매함테스트 시 상위 계층의 많은 의존성 고려 필요이런 문제를 겪으면서, 헥사고날 아키텍처(Hexagonal Architecture) 또는 포트-어댑터 아키텍처(Ports and Adapters Ar..

[만들면서 배우는 클린 아키텍처] 10 아키텍처 경계 강제하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다. 지금까지 아키텍처에 대해서 많은 이야기를 나눴다. 코드를 어떻게 작성하고 어디에 위치시킬지 결정하는 데 있어 우리를 안내해 줄 목표 아키텍처를 가지게 돼서 기쁘다. 하지만 일정 규모 이상의 모든 프로젝트에서는 시간이 지나면서 아키텍처가 서서히 무너지게 된다. 계층 간의 경계가 약화되고, 코드는 점점 더 테스트하기 어려워지고, 새로운 기능을 구현하는데 점점 더 많은 시간이 든다. 이번 글에서는 아키텍처 내의 경계를 강제하는 방법과 함께 아키텍처 붕괴에 맞서 싸우기 위해 취할 수 있는 몇 가지 조치를 살펴보겠다. 경계와 의존성아키텍처 경계를 강제하는 여러 가지 방법에 대해 이야기하기에 앞서 아키텍처의 어디에 경계가 있고, '경계를 강제한다'는 것이 ..

[만들면서 배우는 클린 아키텍처] 09 애플리케이션 조립하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다.  유스케이스, 웹 어댑터, 영속성 어댑터를 구현해 봤으니, 이제 이것들을 동작하는 애플리케이션으로 조립할 차례다.3장에서 이야기했듯이 애플리케이션이 시작될 때 클래스를 인스턴스화하고 묶기 위해서 의존성 주입 메커니즘을 이용한다.이번 글에서는 평범한 자바로 이를 어떻게 하는지, 그리고 스프링, 스프링 부트 프레임워크에서는 이를 각각 어떻게 하는지 살펴보겠다. 왜 조립까지 신경 써야 할까?왜 유스케이스와 어댑터를 그냥 필요할 때 인스턴스화하면 안 되는 걸까? 그것은 코드 의존성이 올바른 방향을 가리키게 하기 위해서다. 모든 의존성은 안쪽으로, 애플리케이션의 도메인 코드 방향으로 향해야 도메인 코드가 바깥 계층의 변경으로부터 안전하다는 점을 기억하자...

[만들면서 배우는 클린 아키텍처] 08 경계 간 매핑하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다. 이 책의 전반부에서는 웹, 애플리케이션, 도메인, 영속성 계층이 무엇이고, 하나의 유스케이스를 구현하기 위해 각 계층이 어떤 역할을 하는지에 대해 다뤘다. 그런데 늘 겪는 문제인 각 계층의 모델을 매핑하는 것에 대해서는 거의 다루지 않았다. 여러분도 매퍼 구현을 피하기 위해 두 계층에서 같은 모델을 사용하는 것에 대해 논의해 본 적이 있을 것이다. 아마 논쟁은 이런 식으로 진행됐을 것이다.매핑에 찬성하는 개발자:두 계층 간에 매핑을 하지 않으면 양 계층에서 같은 모델을 사용해야 하는데 이렇게 하면 두 계층이 강하게 결합됩니다.매핑에 반대하는 개발자:하지만 두 계층 간에 매핑을 하게 되면 보일러플레이트 코드를 너무 많이 만들게 돼요. 많은 유스케이..

[만들면서 배우는 클린 아키텍처] 07 아키텍처 요소 테스트하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다.  내가 목격한 많은 프로젝트에서 자동화된 테스트는 미스터리였다. 모두가 위키에 적혀 있는 따분한 규칙에 따라 테스트를 작성했지만 팀의 테스트 전략을 물었을 때 제대로 답변하는 이는 아무도 없었다. 이번 글에서는 육각형 아키텍처에서의 테스트 전략에 대해 이야기한다. 아키텍처의 각 요소들을 테스트할 수 있는 테스트 유형에 대해 논의할 것이다. 테스트 피라미드아래의 그림의 테스트 피라미드에 따라 테스트에 관한 이야기를 시작해 보자(테스트 피라미드는 마이크 콘의 책 (인사이트, 2012)에서 확인할 수 있다). 아래의 그림은 몇 개의 테스트와 어떤 종류의 테스트를 목표로 해야 하는지 결정하는 데 도움을 준다.기본 전제는 만드는 비용이 적고, 유지보수하기..

[만들면서 배우는 클린 아키텍처] 06 영속성 어댑터 구현하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다.  첫 번째 글(계층형 아키텍처의 문제는 무엇일까?)에서 계층형 아키텍처에 대해 부정적으로 이야기하면서 이 아키텍처에서는 결국 모든 것이 영속성 계층에 의존하게 되어 '데이터베이스 주도 설계'가 된다고 이야기했다. 이번 글에서는 이러한 의존성을 역전시키기 위해 영속성 계층을 애플리케이션 계층의 플러그인으로 만드는 방법을 살펴보겠다. 의존성 역전영속성 계층 대신 애플리케이션 서비스에 영속성 기능을 제공하는 영속성 어댑터에 대해 이야기하겠다. 아래의 그림은 영속성 어댑터가 애플리케이션 서비스에 영속성 기능을 제공하기 위해 어떻게 의존성 역전 원칙을 적용할 수 있을지 보여준다.애플리케이션 서비스에서는 영속성 기능을 사용하기 위해 포트 인터페이스를 호출한..

[만들면서 배우는 클린 아키텍처] 05 웹 어댑터 구현하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다.  오늘날의 애플리케이션은 대부분 웹 인터페이스 같은 것을 제공한다. 웹 브라우저를 통해 상호작용할 수 있는 UI나 다른 시스템에서 우리 애플리케이션으로 호출하는 방식으로 상호작용하는 HTTP API가 여기에 해당한다.우리가 목표로 하는 아키텍처에서 외부 세계와의 모든 커뮤니케이션은 어댑터를 통해 이뤄진다. 따라서 이번에는 웹 인터페이스를 제공하는 어댑터의 구현 방법을 살펴보자. 의존성 역전웹 어댑터와 관련된 아키텍처 요소(어댑터 자체와 애플리케이션 코어와 상호작용하는 포트)에 조금 더 초점을 맞춘 그림이다.웹 어댑터는 '주도하는 ' 혹은 '인커밍' 어댑터다. 외부로부터 요청을 받아 애플리케이션 코어를 호출하고 무슨 일을 해야 할지 알려준다. 이때..

[만들면서 배우는 클린 아키텍처] 04 유스케이스 구현하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다.  애플리케이션, 웹, 영속성 계층이 현재 아키텍처에서 아주 느슨하게 결합돼 있기 때문에 필요한 대로 도메인 코드를 자유롭게 모델링할 수 있다. DDD를 할 수도 있고, 풍부하거나(rich) 빈약한(anemic) 도메인 모델을 구현할 수도 있고, 우리만의 방식을 만들어 낼 수도 있다. 이번 그래서는 앞에서 소개한 육각형 아키텍처 스타일에서 유스케이스를 구현하기 위해 이 책에서 제시하는 방법을 설명한다. 육각형 아키텍처는 도메인 중심의 아키텍처에 적합하기 때문에 도메인 엔티티를 만드는 것으로 시작한 후 해당 도메인 엔티티를 중심으로 유스케이스를 구현하겠다. 도메인 모델 구현하기한 계좌에서  다른 계좌로 송금하는 유스케이스를 구현해 보자. 이를 객체지..

[만들면서 배우는 클린 아키텍처] 03 코드 구성하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다.  코드를 보는 것만으로도 어떤 아키텍처인지 파악할 수 있다면 좋지 않을까? 이번 글에서는 코드를 구성하는 몇 가지 방법을 살펴보고, 육각형 아키텍처를 직접적으로 반영하는 표현력 있는 패키지 구조를 소개하겠다. 새 프로젝트에서 가장 먼저 제대로 만들려고 하는 것은 패키지 구조다. 프로젝트에서 계속 사용할 괜찮아 보이는 구조를 잡는다. 그러고 나서 프로젝트가 진행될수록 점점 바빠지고 패키지 구조는 짜임새 없는 엉망진창 코드를 그럴싸하게 보이게 만드는 껍데기일 뿐이라는 점을 깨닫게 된다. 한 패키지에 있는 클래스들이 불러오지(import) 말아야 할 다른 패키지에 있는 클래스들을 불러오게 된다. 지금부터 예제 코드를 구조화하기 위한 여러 가지 방법들을..

[만들면서 배우는 클린 아키텍처] 02 의존성 역전하기

'만들면서 배우는 클린 아키텍처' 책을 정리한 내용입니다. 이번 글에서는 계층형 아키텍처의 대한 불만의 대안에 대해 이야기를 하려고 한다.먼저 단일 책임 원칙(Single Responsibility Principle, SRP)과 의존성 역전 원칙(Dependency Inversion Principle, DIP)에 대해 이야기하는 것으로 시작하자. 단일 책임 원칙소프트웨어 개발을 하는 사람이라면 아마 단일 책임 원칙에 대해서 알고 있거나, 최소한 안다고 가정해도 될 것이다.이 원칙의 일반적인 해석은 다음과 같다.하나의 컴포넌트는 오로지 한 가지 일만 해야 하고, 그것을 올바르게 수행해야 한다.이는 좋은 조언이지만 단일 책임 원칙의 실제 의도는 아니다.'오로지 한 가지 일만 하는 것'은 단일 책임이라는 말을..