본문으로 건너뛰기

결정-0030: 컨텍스트의 공개 경계를 contract 패키지로 표시한다

상태

승인됨. 저장소의 결정-0007 2항(모듈 루트 직계 클래스를 공개 API로 삼는다)을 부분 대체합니다.

맥락

당시 전제는 Spring Boot 4.1과 Java 21, jOOQ, PostgreSQL 이며 구현된 컨텍스트는 auth 와 mail 둘입니다. ArchUnit 여덟 규칙이 빌드에서 구조를 강제합니다.

결정-0007은 Spring Modulith 규약을 차용해 모듈 루트에 직접 놓인 클래스를 공개 API 로 삼았고, 같은 자리에서 contract 패키지 방식을 명시적으로 기각했습니다. 기각 사유는 contract 패키지와 OHS/PL 격식이 컨텍스트가 여럿인 대형 도메인에는 맞지만 모듈 4개 규모에는 무겁다는 것이었습니다.

결정-0026이 옮겨온 문서 62건은 반대쪽 전제 위에 있습니다. 패키지 배치와 참조 규칙과 컨텍스트 협력이 contract 를 유일한 창구로 규정하고, 레이어 참조를 14행 표로 나누며, 타 컨텍스트 접근에 ACL 어댑터를 둡니다.

두 전제가 걸린 실제 비용을 셌습니다.

측정 항목 값
지금 모듈 루트에 놓인 클래스 2개입니다. mail/MailMessage 와 mail/MailSender 이며 auth 는 0개입니다
contract/ 로 옮길 파일 위 2개입니다
고칠 ArchUnit 규칙 isInternal() 판정 하나입니다
반대로 문서를 되돌릴 경우 컨텍스트 협력 문서 91줄 전체와 패키지 배치 문서의 레이어 참조 표 14행입니다

기각 사유였던 무겁다는 판단이 실측에서 확인되지 않습니다. 공개 표면이 두 클래스이므로 격식의 무게가 실체를 갖지 못합니다.

한 가지 더 있습니다. 코드가 이미 옮겨온 문서 쪽을 한 군데 따르고 있습니다. 명령 서비스가 조회 포트를 의존하지 않는다는 ArchUnit 규칙은 옮겨온 문서의 레이어 참조 표에 명시되어 있고, 결정-0007이 가리키던 기존 참조 문서의 의존 방향 표에는 없습니다.

결정-0027이 할일 도메인을 추가하기로 했으므로 컨텍스트 수가 늘어납니다. 결정-0007이 contract 가 맞는다고 인정한 조건인 컨텍스트가 여럿인 쪽으로 이동합니다.

검토한 대안

모듈 루트 방식을 유지하고 옮겨온 문서를 되돌립니다

구분 내용
장점 코드 변경이 0입니다
단점 문서 쪽 비용이 코드 쪽의 여러 배입니다
기각 사유 되돌리면서 레이어 참조 14행과 ACL 규정을 잃습니다. 그것들은 옮겨온 문서가 기존 문서보다 더 정밀한 지점입니다

양쪽을 병기합니다

공개 경계가 두 가지로 표현되면 ArchUnit 이 무엇을 강제할지 정할 수 없으므로 기각합니다.

contract 패키지를 채택합니다 (채택)

결정

컨텍스트의 공개 경계는 <컨텍스트>/contract/ 이며 그 밖의 모든 하위 패키지는 internal 입니다.

  1. mail/MailMessage 와 mail/MailSender 를 mail/contract/ 로 옮깁니다.
  2. ArchUnit 의 isInternal() 판정을 모듈 루트가 아님에서 contract 패키지가 아님으로 바꿉니다. 규칙의 이름과 나머지 일곱 규칙은 그대로입니다.
  3. 어휘를 컨텍스트로 통일합니다. 결정-0007이 쓰던 모듈을 컨텍스트로 부르며 가리키는 대상은 같습니다.
  4. 결정-0007의 나머지 항은 그대로 유효합니다. 특히 중간 겹을 두지 않는다는 판단은 유지합니다. 본 결정이 뒤집는 것은 공개 표시 방법이지 계층 구조나 분할 기준이 아닙니다.

규칙의 서술은 패키지 배치와 참조 규칙이 소유하며 본 결정기록은 근거를 보존합니다.

결과

  • 발행되는 문서와 실제 코드가 같은 경계를 말합니다. 옮겨온 62건을 고치지 않고 씁니다.
  • 공개 선언이 계속 물리적 행위로 남습니다. 결정-0007이 파일을 루트로 올리는 행위 자체가 공개 선언이라 한 성질을 contract 로 옮기는 행위가 똑같이 갖습니다.
  • ACL 어댑터와 레이어 참조 14행 규칙이 함께 들어옵니다. 강제 현황 표가 미강제 항목까지 밝힙니다.
  • 감수하는 것
    • 결정-0007이 검토 끝에 기각한 것을 채택합니다. 그때의 판단이 틀렸다기보다 전제가 바뀌었습니다. 당시에는 발행되는 문서가 없었고 컨텍스트가 넷 규모였습니다.
    • 패키지가 한 겹 깊어집니다. 공개 타입이 mail.MailSender 에서 mail.contract.MailSender 가 됩니다. 임포트 문이 길어지는 대신 경계가 이름으로 보입니다.
    • 문서와 코드가 이미 어긋난 것을 함께 고쳐야 합니다. 문서의 컨텍스트 지도는 넷을 적고 있으나 코드에는 auth 와 mail 뿐입니다. 결정-0058에 따라 지도에서 예정을 걷어냅니다.
© 2026 dev.goraebap