본문 바로가기

카테고리 없음

MSA 도입 전 고민해야 할 것 ① 공통 모듈 설계편

공통 모듈 설계 배경

프로젝트를 진행하면서 다음과 같은 공통 규칙이 정의되었다.

 

[ 프로젝트 공통 사항 ]

  1. 검색 기능은 10건, 30건, 50건 기준으로 페이지에 노출될 수 있으며, 이외의 건수는 기본 10건으로 제한한다.
  2. 모든 테이블에는 created_at, created_by, updated_at, updated_by, deleted_at, deleted_by 필드를 추가하여
    감사 로그(Audit Log) 를 기록한다.
  3. ApiResponse, BaseCode, GlobalExceptionHandler를 구성하여 공통된 응답 스펙을 유지한다.

해당 요소들은 특정 서비스에 한정되지 않고, 모든 서비스에서 동일하게 유지되어야 하는 규칙에 해당한다.


모놀리식 구조를 MSA 구조로 전환

기존 모놀리식 구조에서는 모든 서비스가 하나의 프로젝트에 존재했기 때문에,

여러 서비스에서 공통적으로 사용하는 기능을 하나의 global 패키지에 모아 관리할 수 있었다.

 

공통 응답 포맷이나 감사 필드, 글로벌 설정(Config)과 같은 코드가 수정되더라도
하나의 코드베이스만 변경하면 전체 기능에 동일하게 반영할 수 있었으며,

별도의 동기화 작업 없이 전체 시스템에 일관되게 적용할 수 있었다.

 

하지만 MSA 구조에서는 각 서비스가 독립적인 프로젝트로 분리되기 때문에

기존과 동일한 방식으로 global 패키지를 각각의 서비스에 두고 관리하게 되면
다음과 같은 문제가 발생할 수 있다.

 

① 변경사항을 각 서비스 담당자가 수동으로 반영

예를 들어 감사 엔티티에 새로운 감사 필드가 공통으로 추가되어야 가정한다.

이때, 각 서비스 담당자가 변경 사항을 직접 반영해야 하고
동일한 코드를 여러 서비스에 반복적으로 복사하여 사용하는 구조가 만들어진다.

또한 일부 서비스에서 변경 사항이 누락될 경우

응답 형식이나 검증 로직, 필드명이 서비스마다 달라져 일관성이 무너지는 문제가 발생할 수 있다.

 

 

② 구현 기준 판단의 어려움

프로젝트에 새로운 팀원이 합류하게 되었을 때,

각 서비스 내부에 흩어져 있는 global 패키지 중 어떤 기능이 프로젝트의 기준이 되는지 판단하기 어려운 상황이 발생할 수 있다.

이는 공통 규칙이 문서가 아닌 코드에 흩어져 존재하게 되고
팀 규모가 커질수록, 서비스 간의 공통 규칙을 일관되게 유지하는 것이 점점 어려워지게 된다.

 

 

결과적으로 이러한 문제점은 코드 일관성 저하, 유지보수 복잡도 증가, 협업 비용 증가의 원인이 된다.

이러한 문제를 방지하기 위해 서비스 간에 공통으로 사용되는 기능을 하나의 공통 모듈로 분리하여 관리할 필요성을 느끼게 되었다.


1️⃣ 공통 모듈이란 ?

  • 여러 서비스에서 공통적으로 사용하는 기능을 하나의 모듈로 만들어 공유하는 방식
  • 각 서비스가 공통 모듈을 의존성으로 추가하여 사용하는 구조

 

공통 모듈의 장점 ]

공통 모듈을 사용하게 되면 다음과 같은 장점을 얻을 수 있다.

  1. 설계 일관성 확보
    공통 모듈을 통해 팀 내에서 정의한 설계 규칙을 일관되게 유지할 수 있다.
  2. 재사용성 증가
    여러 서비스에서 동일한 기능을 재사용할 수 있어 개발 효율이 높아진다.
  3. 유지보수 용이
    공통 기능을 한 곳에서 수정하면,

    해당 모듈을 사용하는 서비스에 동일한 수정 사항을 반영할 수 있어 유지보수가 수월해진다.

 

그렇다면 공통 모듈은 실제 애플리케이션에 어떤 방식으로 주입되어 사용될까?

공통 모듈은 실행 중에 동적으로 주입되는 것이 아니라, 빌드 시점에 의존성으로 주입되는 방식으로 동작한다.

 

[ 공통 모듈 주입과정 ]

각 서비스는 다음과 같은 과정 통해 공통 모듈을 주입하게 된다.

❶ Gradle 또는 Maven 설정 파일에 dependency로 추가하고,

❷ 빌드 과정에서 해당 모듈의 코드가 함께 포함된 하나의 실행 파일(JAR)로 패키징된다.

이후 해당 ❸ JAR 파일을 기반으로 Docker 이미지를 생성하게 되며,

❹  Docker 또는 docker-compose는 이 이미지를 실행하여 컨테이너를 구동하는 역할을 담당한다.

2️⃣ 공통 모듈 도입 고민

하지만 공통 모듈은 하나로 관리되는 만큼 아래와 같은 단점이 존재한다.

  1. 의존성 증가
    여러 서비스가 공통 모듈에 의존하게 되어 결합도가 증가한다.
  2. 배포 복잡성
    공통 모듈이 변경되면 이를 사용하는 모든 서비스에 영향을 미칠 수 있어 배포가 어려워진다.
  3. 버전 관리 부담
    다양한 서비스에서 사용하는 경우, 버전 충돌이나 하위 호환성 문제 발생 가능한다.

 

그렇다면 어떤 기능을 공통 모듈로 관리하면 좋을까 ?

바로 도메인에 종속되지 않고, 정책 변경의 영향을 거의 받지 않는 공통 기능만을 한정적으로 분리하는 것이 좋다.

 

예를 들어 다음과 같은 항목은 공통 모듈로 분리하기에 적절하다.

- ApiResponse, 공통 응답 포맷
- ErrorCode, SuccessCode, BusinessException
- 공통 BaseEntity (created_at 등 감사 필드)
- 플랫폼 규칙(검색 관련 제약)
- 공통 인증 관련 유틸 또는 인증 객체 처리 로직

 

반면 아래와 같은 요소는 공통 모듈로 분리하지 않고 각 서비스에서 관리하는 것이 좋다.

- 비즈니스 로직 (주문, 결제, 회원 정책 등)
- 서비스별로 다르게 해석될 수 있는 validation
- 특정 도메인에 강하게 의존하는 DTO

 

이러한 요소들은 서비스마다 정책과 요구사항이 다르기 때문에
공통 모듈로 분리할 경우 오히려 결합도가 증가하고 유연성이 떨어질 수 있다.


결론

MSA 구조에서 무작정 모든 것을 공통으로 묶게 된다면, MSA의 장점인 서비스 독립성이 무너질 수 있다.

반대로 아무것도 공유하지 않는다면, 팀 전체의 생산성과 일관성이 크게 떨어지게 된다.

따라서 공통 모듈은

도메인과 완전히 분리되고,

변경 가능성이 낮으며,

모든 서비스에서 동일하게 사용되는 영역에 한해서만

제한적으로 구성한다면,

협업 과정에서도 불필요한 혼선을 줄이고 팀 전체의 개발 경험도 더 좋아질 수 있을 것 같다고 생각했다.

 

나아가 적절히 구성된 공통 모듈은 단순히 코드 재사용성을 넘어,

우리 팀이 어떤 기준으로 협업하고 있는지를 가장 잘 보여주는 설계 요소가 될 수 있다고 느꼈다.


[참고자료]

 

내배캠_숙련프로젝트 참고자료

https://agongstory.tistory.com/53