5.2 KiB
5.2 KiB
common module 허용 기준
목적
common 모듈은 공유 편의 때문에 만드는 기본 모듈이 아니다.
기본값은 만들지 않음 이다.
이 문서의 목적은:
- “일단 common으로 보내자”를 막고
- 모듈 경계를 흐리는 공유를 줄이고
- 정말 필요한 공용 코드만 예외적으로 허용하는 것이다
공식/원전 기준 요약
- 모듈은 외부에 노출하는 API와 내부 구현을 구분해야 한다.
- 다른 모듈은 공개된 API에만 의존해야 하며, 내부 구현 의존은 막아야 한다.
- 헥사고날 아키텍처의 핵심도 경계와 역할 분리다.
- 겉보기 중복만 보고 조기 추상화를 만들면 이후 변경 비용이 커질 수 있다.
기본 규칙
1. common은 기본 금지
새 코드를 추가할 때 기본 선택지는 아래 순서다.
- owning layer/module 내부에 둔다
- 경계가 필요하면 해당 module의 API로 노출한다
- 그래도 어느 곳에도 자연스럽게 속하지 않을 때만
common을 검토한다
즉 “어디 둘지 애매하면 common”을 금지한다.
2. common은 아래 조건을 모두 만족할 때만 허용
다음이 모두 참일 때만 common 도입을 검토한다.
- 3개 이상 모듈에서 실제로 재사용된다
- 변화 이유가 같다
- 특정 모듈이 소유한다고 보기 어렵다
common으로 옮겨도 의존 방향이 더 나빠지지 않는다- 모듈 API를 좁게 노출하는 방식으로 해결하기 어렵다
하나라도 애매하면 기존 owning module에 둔다.
3. “중복 존재”만으로는 common 근거가 아니다
코드가 비슷해 보여도 다음이면 common으로 보내지 않는다.
- 서로 다른 비즈니스 문맥에서 독립적으로 변할 가능성이 큼
- 지금은 비슷하지만 미래 요구가 갈라질 가능성이 큼
- common으로 모으면 이름과 책임이 모호해짐
즉 진짜 공통 원인(common cause)일 때만 허용한다.
4. 레이어 경계를 깨는 공유 금지
common이 아래를 섞는 것을 금지한다.
- presentation + domain
- domain + infrastructure
- application + web transport
- persistence 모델 + API 모델
- 외부 API payload + 내부 domain meaning
공유보다 경계 보존이 우선이다.
5. common에는 business policy를 두지 않는다
다음은 common에 두지 않는다.
- 도메인 규칙
- 상태 전이 규칙
- 권한 판정
- 에러 코드 정책
- 외부 연동별 특화 규칙
이런 것은 반드시 owning module 또는 boundary contract가 소유한다.
6. common에 둘 수 있는 것
예외적으로 허용 가능한 후보:
- 경량 value type
- 순수하고 작은 utility
- 여러 모듈이 같은 이유로 쓰는 매우 안정적인 helper
- 모듈 경계를 깨지 않는 공통 annotation / marker / tiny abstraction
- 명확한 소유자가 없는 순수한 language-level helper
단, 이것도 실제 재사용과 변화 이유가 검증되어야 한다.
7. common의 utility는 특히 좁게 제한
utility는 아래 조건을 만족할 때만 허용한다.
- side effect 없음
- framework/business/persistence 의존 없음
- 이름만 보고 역할이 분명함
- 단순 문자열/시간/컬렉션 helper라도 owning type 안에 둘 수 없는 이유가 있음
StringUtils, DateUtils, CommonUtils, AppUtils 같은 잡동사니 묶음은 금지한다.
8. 모듈 API 노출이 common보다 우선
Spring Modulith의 방향처럼, 공용화가 필요해 보일 때 먼저 검토할 것은:
- 해당 모듈의 공개 API로 노출할 수 있는가
- named interface처럼 노출 범위를 좁게 지정할 수 있는가
- explicit dependency로 필요한 부분만 허용할 수 있는가
즉 “common으로 이동”보다 “모듈 API 설계 개선”을 먼저 본다.
9. 공용 타입은 더 보수적으로 관리
common으로 이동한 타입은 사실상 여러 모듈이 기대는 기반이 된다.
기본:
- 변경에 더 보수적이어야 한다
- naming을 더 명확히 해야 한다
- Javadoc/문서가 더 중요하다
- examples/tests가 함께 있어야 한다
10. common은 dump zone이 아니다
다음 징후가 보이면 잘못된 common이다.
- 이름이
Common*,Util*,Base*,Helper*위주 - business/domain/web/persistence 코드가 섞여 있음
- 모듈 간 순환 의존을 가리기 위해 common을 사용
- “일단 여기 두자”가 반복됨
이 경우 common을 늘리는 대신 다시 소유 모듈로 분해한다.
11. common 도입은 문서화한다
새로운 common 타입/패키지를 추가할 때는 최소한 아래를 설명한다.
- 왜 owning module에 둘 수 없는가
- 어떤 모듈들이 실제로 재사용하는가
- 같은 이유로 어떻게 함께 바뀌는가
- 어떤 경계를 깨지 않는가
설명할 수 없으면 common으로 보내지 않는다.
프로젝트 기준 요약
common기본 금지- 재사용만으로는 부족하고 “같은 이유로 함께 변함”이 필요
- 모듈 API 설계 개선이 common보다 우선
- 경계/레이어를 섞는 공용화 금지
- business policy는 common 금지
- utility/common dump zone 금지
- 예외적 허용 시에도 좁고 순수하고 안정적인 타입만