[OOP] 헥사고날 아키텍처 맛보기

2023. 7. 24. 17:24Computer Sciences/OOP

들어가며

개발을 공부하기 시작한 후로 OOP와 SOLID 등 객체지향에 대한 여러 개념에 대해 배웠다. 그러나 실제로 프로젝트를 개발할 때는 이러한 것들을 어떻게 활용해야 하는지 모른 채 찜찜한 채로 개발을 해왔었다. 그리고 TDD까지는 아니지만 테스트를 도입하여 프로젝트를 진행하고 있었다. 그런데 기능이 많아지고 테스트가 많아지면서 테스트 시간이 길어졌을 뿐만 아니라 테스트 코드를 작성하는데 점점 Mocking과 Stub에 대한 의존도가 높아졌다. 이렇게 테스트하는 게 맞나 고민하던 중 인프런에서 Mocking 및 외부 의존성 없이 순수 코드로만 테스트를 작성하는 강의를 보게 되었다. 이 강의에서는 의존성 주입 & 의존성 역전을 활용하여 레이어드 아키텍처에서 헥사고날 아키텍처로 전환하였다. 이를 통해 테스트 시 생각했던 고민들이 해결되었다. 또한 아키텍처를 전환하는 과정에서 객체지향의 개념이 많이 적용되는 것을 보았다. 이에 대한 이야기를 해보려고 한다.

레이어드 아키텍처

레이어드 아키텍처는 스프링을 공부하기 시작한 사람들은 학습 초기에 많이 배우는 아키텍처이다. 레이어드 아키텍처는 유사한 기능들을 같은 계층으로 묶어 관리하는 방식이다. 주로 Presentation - Buisness - Persistence 의 3개의 계층으로 구성한다. 그리고 스프링에서는 각각을 Controller - Service - Repository 로 많이 사용한다. 이 방식은 이해하기 쉽고 직관적이기 때문에 가시적으로 기능을 개발하기 편리하다. 필자 또한 초기에 배운 이 방식으로 줄곧 개발을 해왔었다. 그러나 앞에서 말했던 것처럼 기능 별로 계층만 분리해 놓았을 뿐 객체지향이 적용되기 어려운 방식이다. 이 아키텍처의 단점을 살펴보자.

레이어드 아키텍처

레이어드 아키텍처의 단점

1. DB 위주의 설계를 하게 된다. 

필자는 프로젝트를 구상하고 요구사항을 분석한 뒤 가장 먼저 한 것이 DB 스키마 설계였다. 어찌보면 합리적이라고 생각된다. 하지만 그보다 먼저 생각해야 할 것은 실제 시스템에 필요한 유스 케이스이다. 즉, 만들고자 하는 서비스가 실제로 어떻게 사용될지를 먼저 생각해야 한다.

 

2. 동시 작업에 어려움이 생긴다.

이는 첫 번째 단점과 이어지는데 DB 스키마부터 설계하지 않으면 기능 개발이 되지 않는다. 즉 Persistence -> Buisness -> Presentation 계층 순으로 개발하게 된다. 이렇게 되면 하나의 기능은 그 책임을 맡은 개발자만이 개발할 수 있다.

 

3. 도메인이 죽는다.

레이어드 아키텍처로 개발하게 되면 업무 도메인을 알기 어렵다. 또한 객체가 수동적이고 함수 위주로 동작하게 된다. 그래서 사실상 서비스가 모든 작업을 맡는 상황이 발생한다.

 

이러한 단점들은 코드를 객체지향이 아닌 절차지향적인 코드를 작성하도록 유도한다. 이는 테스트를 어렵게 하고 SOLID 원칙을 위배할 가능성이 높다. 필자가 느꼈던 찜찜함이 바로 아키텍처에서 발생했던 것이다.

개선하기

그렇다면 이러한 문제들을 개선해보자.

1. 죽은 도메인

죽어버린 도메인을 살리기 위해 서비스 계층과 레포지토리 계층 사이에 도메인 계층을 추가하자. 그리고 서비스 계층을 도메인을 레포지토리 계층에서 가져와 책임을 위임하는 곳으로 변경하자. 도메인 계층은 OOP스러운 도메인들이 협력하는 계층이다. 또한 외부에 의존하지 않는 POJO들로 구성된다.

도메인 레이어 추가

2. 낮은 Testability & 동시 작업 불가

도메인 계층은 외부와의 의존성이 없기 때문에 인스턴스화하기 쉽다. 서비스에서 의존하는 레포지토리에 대해서는 의존성 역전을 활용해 테스트 시 Fake 객체를 주입한다. 컨트롤러에서 의존하는 서비스, 레포지토리에 대해서도 마찬가지로 의존성 역전을 활용해 테스트 시 Fake 객체를 주입한다. 이로써 컨트롤러, 서비스 계층이 외부 인프라와 관계없이 개발이 가능하다. 또한 외부와 관계없이 각 계층이 인터페이스를 따라 개발 가능하므로 동시 작업이 가능해진다.

의존성 역전 및 주입을 통해 개선된 아키텍처

개선된 아키텍처 살펴보기

개선된 아키텍처의 계층 배치를 다듬어 보면 다음과 같이 바꿀 수 있다.

그리고 잘 생각해보면 컨트롤러만 서비스를 실행하지 않을 수 있다. 즉 다른 곳에서도 이를 사용할 수 있다. 도메인 계층이 외부에 의존하지 않으며 인터페이스에 따라 구현된 서비스만 있으면 되므로 가능하다.

이 아키텍처의 모양을 그려보면

이렇게 육각형 모양이 만들어진다. 이와 같이 육각형 구조로 만들어졌기 때문에 이러한 아키텍처를 헥사고날 아키텍처라고 부른다.

마치며

지금까지 기존 레이어드 아키텍처에서 헥사고날 아키텍처까지의 전환 과정을 간단하게 살펴보았다. 헥사고날 아키텍처는 코드를 유연하고 확장성 있게 개발하도록 유도한다. 핵심은 도메인 비즈니스 로직에 집중하고 외부 요소에 의존하지 않도록 하는 것이다.

 

배운 내용을 기반으로 헥사고날 아키텍처를 기존 서비스를 분석해보려고 했다. 이때 또 다른 문제들을 마주하는데 어떻게 도메인들을 정의하고 도메인 객체 간 관계 구성을 해야하는지가 헷갈렸다. 문득 예전에 읽었었던 「객체지향의 사실과 오해」가 떠올랐다. 분명 읽었었지만 실질적으로 어떻게 적용할지 모른 채 개발하고 있었고 점점 잊혀져왔다. 다시 이 책을 읽으면서 객체지향에 대해 생각해보고 프로젝트에 적용해보도록 할 것이다.