단일 모듈에서 멀티 모듈 전환기 - (8) 회고 및 마무리
들어가기 앞서
단일 모듈에서 멀티 모듈 전환기에서 다루는 거의 모든 내용은 주관적인 관점을 가지고 있습니다.
다른 글의 내용을 인용할 경우 레퍼런스를 참조하거나 참고 문서에 존재합니다.
피드백은 언제나 환영합니다. 글의 내용에 대한 의견이나 질문이 있으시면 댓글로 남겨주세요.
‘단일 모듈에서 멀티 모듈 전환기 - (7) 멀티 모듈 전환 with Gradle’에서 이어집니다.
전환 후 구현 계층의 장단점
장점
가독성과 재사용성이 증가한다
구현 계층의 협력 도구 클래스를 이용하면 재사용성이 증가하고 서비스 계층의 비즈니스 로직의 가독성이 향상된다. 비즈니스 로직에서 상대적으로 어떤 규칙이 더 중요하고 어떤 규칙이 덜 중요한지 한눈에 파악할 수 있다.
관심사의 분리가 명확해진다
서비스 계층은 비즈니스 흐름에, 구현 계층은 상세 로직에 집중함으로써 코드의 응집도가 높아진다. 이는 코드 변경 시 영향 범위를 최소화하고, 특정 기능을 수정할 때 해당 구현 클래스만 찾으면 되므로 유지보수성이 향상된다.
테스트 용이성이 개선된다
구현 계층의 협력 도구 클래스는 단일 책임을 갖기 때문에 단위 테스트 작성이 용이해진다. 전환 전의 서비스 클래스에 존재하던 테스트 코드가 협력 도구 클래스로 위임될 수 있다.
단점
단기적으로 생산성이 하락한다
구현 계층이라는 계층이 하나 더 추가됨에 따라 단기적으로 생산성이 떨어진다. 빠르게 구현해야하는 시점에 계층이 추가된 것은 작성해야할 코드가 더 많아졌다는 것을 의미한다.
의미 없는 계층이 될 수 있다
단순한 CRUD만 존재하는 프로젝트에서 구현 계층은 의미 없는 계층이 될 수 있다. 재사용성을 극대화하기 위한 계층인데 재사용성이 거의 없는 프로젝트라면 무의미한 계층이다. 또한 단순히 거쳐가는 계층이 될 수 있다.
클래스 수의 증가로 인한 복잡성 증가
구현 계층을 도입하면 협력 도구 클래스가 많아지면서 전체 프로젝트의 클래스 수가 늘어난다. 이로 인해 초기 진입 장벽이 높아질 수 있으며, 클래스 간 관계를 파악하는 데 더 많은 시간이 소요될 수 있다.
전환 후 도메인 모델의 장단점
장점
DB 테이블에 의존하지 않는 유연한 모델이 나온다
ORM 기술인 JPA는 JPA 엔티티를 이용해 테이블을 객체로 매핑해주는 장점을 가진다. 객체로 쉽게 매핑은 가능하지만 DB 테이블에 의존적이다. 테이블의 연관관계에 맞춰 엔티티를 설계해야한다. 하지만 도메인 모델을 도입한다면 DB 테이블에 의존하지 않는 도메인 모델을 설계할 수 있다. 상황에 따라 유연한 설계가 가능하다.
실제 사용하는 용어를 적용할 수 있다
DB 테이블의 설계할 때의 용어와 실제 도메인과 관련된 내용을 다룰 때 용어가 달라질 수 있다. 하지만 도메인 모델을 사용하게 되면 실제 사용하는 용어를 도메인 모델에 적용할 수 있다. 개발은 개발자들끼리만 하는 것이 아닌 다양한 분야의 사람들과 같이 소통하며 개발된다. 다양한 분야의 사람이 존재한다라는 것은 각자의 이해관계가 조금씩 다르다는 것이다. 이해관계가 다르면 사용하는 용어도 다를 수 있다. 이는 소통의 부재로 다가올 수 있다. 도메인 모델을 사용함으로써 개발자, 기획자, 디자이너 등 다양한 사람들과 용어를 통일할 수 있다.
기술 변화에 유연하게 대응할 수 있다
도메인 모델은 특정 기술에 의존하지 않는 POJO로 구성되어 있어, ORM 기술이나 데이터베이스가 변경되더라도 비즈니스 로직은 그대로 유지될 수 있다. 이는 장기적인 프로젝트에서 기술 스택 변경 시 큰 이점으로 작용한다.
단점
생산성이 하락한다
도메인 모델을 만든다는 것은 하나의 프로젝트에 (JPA를 쓴다는 가정하에) JPA 엔티티와 도메인 모델 두가지가 존재한다는 것을 의미한다. JPA 엔티티로 빠르게 생산성을 챙길 수 있는데 이 장점을 포기하는 것이다. 생각보다 도메인 모델을 설계하는 데 시간이 많이 든다. 도메인에 대한 지식이 부족했던 초반 설계와 도메인에 대한 지식이 풍부해진 이후 설계는 달라진다. 도메인 모델 설계는 이러한 설계를 유연하게 가져갈 수 있는 것이 장점이지만 결국엔 설계를 바꿔야한다는 점은 같다. 물론 나중을 생각하면 훨씬 적은 비용을 치르는 것이긴 하다.
매핑 작업의 추가 부담
JPA 엔티티와 도메인 모델 사이의 매핑 로직이 필요하며, 이는 추가적인 코드 작성과 유지보수 비용을 발생시킨다. 특히 복잡한 도메인에서는 이 매핑 로직이 상당히 복잡해질 수 있으며, 성능 이슈로 이어질 가능성도 있다.
학습 비용 증가
도메인 모델과 관련된 개념(DDD, Bounded Context 등)의 이해와 적용에는 추가적인 학습 비용이 발생한다. 새로운 팀원이 합류할 때마다 이러한 개념들에 대한 교육이 필요하며, 팀 전체가 동일한 이해 수준을 유지하는 것이 중요하다.
전환 후 멀티 모듈의 장단점
장점
강제로 격리할 수 있다
BC를 설계하고 멀티 모듈을 설계하면 의존성 관리를 통해 강제로 격리할 수 있다. 새로운 개발자가 들어와도 사용 가능한 모듈과 사용 불가능한 모듈을 구분함으로써 휴먼에러를 방지할 수 있다. 또한 모듈 간 기술 의존성을 관리할 수 있다.
병렬 개발 및 유지보수 효율성 향상
각 모듈이 명확히 분리되어 있어 여러 팀이 동시에 다른 모듈을 개발하거나 유지보수할 수 있다. 특정 기능이나 도메인에 변경이 필요할 때 해당 모듈만 집중적으로 수정할 수 있어 효율성이 증가한다. 이는 MSA의 장점이기도 하다.
기술 스택 다양화 가능
모듈별로 다른 기술 스택을 적용할 수 있어 각 도메인이나 기능에 최적화된 기술을 선택할 수 있다. 예를 들어, 데이터 처리가 중요한 모듈에는 특화된 데이터 처리 라이브러리를, 실시간 처리가 필요한 모듈에는 비동기를 적용할 수 있다.
단점
생산성이 하락한다
강제로 격리할 수 있다는 장점은 생산성이 하락한다라는 것과 동일하다. 좀 더 쉬운 방법이 존재하는데 격리를 통해 통제하는 것은 쉬운 방법을 포기한다라는 것과 같다
설정 및 빌드 복잡성 증가
여러 모듈로 분리되면서 프로젝트 설정 파일과 빌드 스크립트가 복잡해진다. Gradle 설정이 모듈별로 필요하며, 의존성 관리가 더 복잡해질 수 있다.
모듈 간 경계 설정의 어려움
어떤 기능이나 클래스가 어느 모듈에 속해야 하는지 결정하기 어려운 경우가 발생한다. 특히 여러 도메인에 걸쳐 있는 기능을 어느 모듈에 배치할지, 또는 별도 모듈로 분리할지 결정하는 과정에서 많은 논의와 의사결정이 필요하다.
테스트 환경 구성의 복잡성
모듈 간 의존성이 있는 통합 테스트를 구성할 때 복잡성이 증가한다. 특히 DB 모듈과 Domain 모듈 간의 테스트 의존성 관리가 어려우며, Test Fixtures 관리에도 추가적인 노력이 필요하다.
내가 아키텍처를 정할 수 있는 팀의 리더라면?
만약 제가 아키텍처를 정할 수 있는 팀의 리더라면 어떤 아키텍처를 설계할 지 고민해봤습니다.
현재 시점에는 다음과 같은 결론이 나왔습니다.
- DB 모듈은 분리하지 않는다.
- Domain 모듈과 DB 모듈을 합친 Core 모듈로 구성한다.
- JPA 엔티티와 도메인 모델 둘 다 가져가되 애플리케이션에서는 도메인 모델만 사용하고 JPA 엔티티는 도메인 모델 간의 매핑의 역할로 사용한다.
- DB 계층을 인터페이스로 격리하되 모듈로 분리하지는 않는다.
- 생산성이 필요할 경우 Core 모듈은 어느 정도 기술에 의존하는 코드를 작성한다.
- Core 모듈은 코드리뷰를 통해 기술 의존 코드를 관리한다.
DB 모듈을 분리하는 것은 기술에 의존하지 않게하는 것인데 생산성이 필요하다면 기술 의존은 어느 정도 필요하다고 생각합니다. 만약 회사의 핵심 프로젝트면서 차세대 프로젝트로 진행한다면 DB 모듈을 분리하는 것은 고려해볼 것 같습니다.
물론 당장 빠르게 성과를 내야한다면 단일 모듈로 JPA 기술만 사용해서 프로젝트를 구성하는 것이 나은 방법이겠지요?
마무리
이 프로젝트는 코드가 변화해가는 과정을 경험하며 매 상황마다 장단점을 느끼는 것이 목표였습니다. 제한된 시간 안에 성과를 만들어 내지 않아도 되는 프로젝트였는데요. 백엔드 팀원 한명과 같이 주 1회 10시간씩 3달에 걸쳐 진행된 프로젝트였습니다. 30분씩 번갈아가며 진행한 페어 프로그래밍을 통해 매 순간 의논하였습니다. 충분한 고민을 통해 코드가 변화해나가는 경험을 했습니다. 하지만 실무에서는 절대 그럴 수 없다는 것을 잘 알고 있습니다. 이 경험을 통해 코드 설계에 대해 실무에서 빠른 의사 결정을 할 수 있는 힘을 길렀다고 생각합니다.
프로젝트를 마무리하며 느낀점은 “은탄환은 없다” 라는 것입니다. 모든 것은 트레이드 오프가 존재합니다. 요즘 유행하는 DDD, 클린 아키텍처가 유행한다고 해서 “이 이론들이 가장 최고야. 책에서는 이렇게 하니까 이렇게 해야지” 라는 것은 지양해야한다고 생각합니다. 무조건적인 지지는 독이 될 것이라고 생각합니다.
개발자는 문제를 해결해나가는 사람이지 예술을 하는 사람이 아니기 때문입니다. 결국엔 이 또한 시대의 흐름일 뿐 아키텍처는 계속 변화할 것이니까요.
다음으로
단일 모듈에서 멀티 모듈 전환기는 끝이 났습니다. 다음 아키텍처와 관련된 주제는 MSA가 될 것 같아요. 지금까지 만든 멀티 모듈을 가지고 MSA로 전환하는 과정을 경험해보려 합니다. 하지만 당장은 우선순위가 밀려있어 언제 할지는 모르겠습니다. 당장은 저에게 부족한 부분인 기술적인 부분을 공부해보려고 합니다.
지금까지 긴 글을 읽어주셔서 감사합니다.
Github Repository 전체 코드
https://github.com/dh0304/multi-module