헥사고날 아키텍처 얕게 공부한 뒤 느낀점 - 기본이나 잘하라
어제 내 프로젝트 구조에 대해 글을 작성한 뒤로, 헥사고날 아키텍처에 대한 여러 글을 읽고 예제들을 살펴보며 느낀점은 '이게 도대체 레이어드 아키텍처랑 뭐가 다른거지?' 였다. (물론 내 기존 코드에는 문제가 많다. 기존 코드에 문제가 없다고 말하려는게 아니다. 고칠 점은 당연히 고쳐야한다.)
물론 다르다. 다른데, 그게 막 헥사고날 아키텍처는 위대하고 레이어드 아키텍처는 별로다라고 말할만큼 다른가?이다. 결국 요청 처리 흐름은 큰 틀을 벗어나지 않는다. API로 요청이 들어오면 도메인 로직을 수행하는데, 도메인 로직 수행을 위해선 데이터베이스에 뭔가 요청해야하고, 이렇게 저렇게 작업을 한 뒤에 필요하면 다시 뭔가 값을 반환한다.
그럼에도 불구하고 둘의 차이는 있는데, 내가 생각한 레이어드 아키텍처와 헥사고날 아키텍처의 가장 큰 차이 두 가지를 적어본다.
- 헥사고날 아키텍처는 레이어드 아키텍처보다 DIP에 더욱 신경쓴다. 영역 간 의존에는 절대 구체 클래스에 의존하지 않는다.
- 각 영역 간의 구분을 명확히 하는데, 특히 도메인 영역과 데이터베이스 영역에서 그러하다. 도메인 객체와 엔티티 객체는 다르다.
헥사고날 아키텍처라는 이름이 붙은 데에는 첫 번째 이유가 좀 큰 것 같은데, DIP에 신경쓰면서 생성한 인터페이스에 그럴듯한 이름을 붙여줘서 헥사고날 아키텍처가 된 게 아닌가 싶다. 단순히 Controller -> Service의 구체 클래스 의존이 아니라. Controller -> Service<I> <- ServiceImpl의 형태에 Service<I>에 Port라는 이름을, Controller에는 Adapter라는 이름을 붙여준다. 마찬가지로 Service -> Repository의 의존이 아니라. Service -> Repository<I> <- RepositoryImpl의 형태를 띤다. 이름도 같다.
Port와 Adapter라는 개념 자체는 마음에 든다. 실제 개념과 유사하다고 생각한다. Port는 연결되는 부분이다. Adapter는 Port에 꽂아넣는다. 컴퓨터로 생각하면, 메인 보드에 USB 포트 두 개를 이용해 키보드와 외장 하드를 연결한 상황이라고 생각해보자. 키보드는 Controller에, 메인 보드는 Service에, 외장 하드는 Repository에 해당한다. 키보드라는 adapter를 통해 메인 보드에 뭔가 요청을 보내면 메인 보드에서 연산을 처리한다. 이 때 필요한 데이터는 외장 하드라는 adapter를 통해 가져온다. 이렇게 생각하니 개념 자체가 쉽게 이해됐다.(맞게 이해했는지는 사실 아리송하다)
이 과정에서, 키보드를 내가 쓰던 A에서 B로 바꾼다고 메인 보드 입력 포트를 변경해야 하는 것은 아니다. 외장 하드도 마찬가지다. 이런 개념을 아키텍처에 적절히 적용한 네이밍이라고 생각되고, 그래서 이 부분은 마음에 들었다.
또한 도메인 영역과 데이터베이스 영역을 명확하게 구분한 부분도 좋았다. 사실 이렇게 둘만 나눈게 아니라 명확하게 외부 영역과 도메인 영역을 나눴다고 보는게 더 맞는 것 같다. 이 부분은 내 코드에 도입하고 싶은데, 코드로 어떻게 표현해야 하는지를 아직은 잘 모르겠다. 좀 더 예제들을 살펴보면서 도입해보고자 한다.
뭐 이런 차이들이 있었는데, 결국 그래서 뭐가 다르냐? 싶으면 잘 모르겠다. 레이어드 아키텍처나 헥사고날 아키텍처나 핵심은 같다. 도메인 영역을 다른 영역으로부터 분리한다. 도메인 영역을 지키고 싶어서 두 아키텍처가 대두된 것이다. 즉, Service레이어(헥사고날에선 UseCase)에서만 도메인 정보를 사용하며, 도메인 영역에서 사용되어야 하는 정보는 철저하게 외부에 의존해선 안된다. 쉽게 말하면 자바에서 제공하는 기본적인 자료구조(List, Set 등등)나 유틸리티 라이브러리(lombok과 같은, 그런데 사실 얘네도 떼는게 진짜 순수한 POJO객체긴 하다), 그리고 같은 도메인 영역의 정보를 제외하곤, 도메인 객체에는 어떤 구문도 import되어선 안된다.
그래서 헥사고날 아키텍처는 정말 그 자체만으로 적용해볼만 하면 좋은 아키텍처일까? 에 대한 답은 '헥사고날이건 아니건, 할 일이나 잘하라'이다. 헥사고날 아키텍처는 좋은 개념이다. DIP를 잘 지키며, SRP와 ISP 도 철저히 지킨다. 그런데, 결국은 이 원칙들은 객체지향의 기본인 SOLID원칙이다. 레이어드 아키텍처를 사용하던, 뭘 사용하던 기본만 잘하면 결국 좋은 아키텍처 형태를 만들 수 있다는 것이다.
결론을 내자면, 내가 공부하면서 느낀 헥사고날 아키텍처는 '객체지향 기본 원칙을 철저히 지키고자 노력하면서 야무진 이름을 붙인 아키텍처'다. 훌륭하다. 그러나, '헥사고날 아키텍처는 모든 문제의 해결책이 된다' 라고 생각한다면 절대로 틀린 생각이다. 헥사고날 아키텍처를 적용해서 문제가 해결됐다면, 그건 헥사고날 아키텍처를 적용해서가 아니라. 객체지향 기본 원칙을 철저히 지키고자 노력하면서 이에 걸맞는 야무진 이름을 붙여서이다.