[Spring Boot 멀티모듈] domain-common 빌드 실패 원인과 해결 과정 정리 - Lombok, JPA @Entity 인식 안됨, Gradle 의존성 삽질기

2025. 12. 13. 16:27·ServerDev/SpringBoot

 

 


 

Spring Boot + Gradle 기반의 멀티모듈 프로젝트를 구성하던 중,
공통 엔티티와 Enum, 도메인 객체를 모아둔 domain-common 모듈을 분리하여 관리하고 있었습니다. 프로젝트 구조는 다음과 같았습니다.

Wecam-project
├── domain-common
│   └── build.gradle
├── wecam-backend
│   └── build.gradle
├── wecamadminbackend
│   └── build.gradle
├── build.gradle (root)
└── settings.gradle

 

이 구조에서 domain-common은

  • @Entity
  • @Table
  • @Enumerated
  • Lombok 어노테이션 (@Getter, @Builder 등)

 

을 포함한 순수 도메인 모듈 역할을 하고 있었습니다.

 

 


 

2. 처음 마주한 에러

처음에는 단순히 domain-common 모듈이 잘 빌드되는지 확인하기 위해 아래 명령을 실행했습니다.

./gradlew :domain-common:build

그러자 바로 다음과 같은 에러가 발생했습니다.

Could not resolve all files for configuration ':domain-common:compileClasspath'.
> Could not find org.projectlombok:lombok:

처음에는 단순히 Lombok 의존성이 누락된 줄 알았습니다.

 

 


 

 

3. Lombok 버전 명시 → 그래도 실패

그래서 domain-common/build.gradle에 Lombok을 명시적으로 추가했습니다.

compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'

그리고 다시 빌드를 시도했지만,
이번에는 에러가 JPA 관련 어노테이션 전부를 인식하지 못하는 형태로 폭발했습니다.

 

 


 

 

4. @Entity, @Table, @Getter 전부 인식 안 됨

에러 메시지는 다음과 같은 형태였습니다.

error: cannot find symbol
@Entity
symbol: class Entity

error: cannot find symbol
@Getter
symbol: class Getter

이 시점에서 확인한 사실은 다음과 같았습니다.

  • Lombok 어노테이션 전부 인식 안 됨
  • JPA 어노테이션 전부 인식 안 됨
  • @Id, @Column, @ManyToOne 등도 전부 에러

즉, 컴파일러가 이 어노테이션들을 아예 모른다는 상태였습니다.

 


 

 

5. “다른 모듈에서는 잘 되는데?”라는 의문

여기서 가장 헷갈렸던 점은 이것이었습니다.

“같은 엔티티를 사용하는 다른 백엔드 모듈들은 문제없이 실행되는데
왜 domain-common만 빌드하면 전부 깨질까?”

그래서 이 문제를 기준으로 하나씩 정리해보기로 했습니다.

 

 


 

6. 원인 ① domain-common은 Spring Boot 모듈이 아니다

제가 찾아본 결과, 가장 중요한 핵심은 이것이었습니다.

domain-common 모듈은 애플리케이션 모듈이 아니다

즉,

  • @SpringBootApplication이 없음
  • 단독 실행 대상이 아님
  • JPA 컨텍스트가 없음

그런데 domain-common 안에는 @Entity가 들어있습니다.

이 말은 즉슨,

domain-common을 단독으로 빌드하거나 실행하면
JPA 관점에서는 “관리되지 않는 엔티티”가 된다

 

라는 의미였습니다.


 

7. 원인 ② JPA 어노테이션은 “라이브러리”가 필요함

 

또 하나 놓치고 있었던 부분은 이것이었습니다.

잘못된 생각

Spring Boot 프로젝트니까
JPA 어노테이션은 자동으로 다 되는 거 아니야?

실제로는

  • @Entity, @Table 등은 jakarta.persistence API
  • Spring Boot가 아니라 라이브러리가 제공함

그래서 domain-common에는 아래 의존성이 반드시 필요했습니다.

implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
implementation 'jakarta.validation:jakarta.validation-api:3.0.2'

 

이걸 추가하지 않으면,
컴파일 타임에 어노테이션 자체를 인식하지 못합니다.

 


 

8. 원인 ③ spring-boot-starter-data-jpa를 넣었는데도 안 되는 이유

 

저는 처음에 이렇게 생각했습니다.

“그럼 그냥 spring-boot-starter-data-jpa를 넣으면 되겠네?”

그래서 추가했습니다.

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

 

그런데 또 이런 에러가 발생했습니다.

Could not find org.springframework.boot:spring-boot-starter-data-jpa:

이유는 간단했습니다.

  • domain-common 모듈에는
    Spring Boot BOM (dependency management) 이 적용되지 않음
  • 그래서 버전이 자동으로 해석되지 않음

즉,

Spring Boot 플러그인을 적용하지 않은 모듈에서는
starter 의존성을 그냥 쓰면 안 된다

 

는 사실을 이때 명확히 알게 되었습니다.

 


 

9. 최종 정리: domain-common은 이렇게 구성하는 게 맞다

 

domain-common의 역할

  • 엔티티 정의
  • Enum
  • 공통 VO, ID 클래스
  • 실행 X
  • Repository X
  • Service X

domain-common에 필요한 의존성

dependencies {
    // JPA 어노테이션
    implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'

    // Validation
    implementation 'jakarta.validation:jakarta.validation-api:3.0.2'

    // Lombok
    compileOnly 'org.projectlombok:lombok:1.18.30'
    annotationProcessor 'org.projectlombok:lombok:1.18.30'
}

Spring Boot Starter는 넣지 않는다

 


 

10. “그럼 실행할 때는 왜 문제 없었나?”

이 부분도 많이 헷갈릴 수 있는데, 이유는 명확합니다.

  • 실제 실행은 wecam-backend, wecamadminbackend에서 이루어짐
  • 해당 모듈들은:
    • @SpringBootApplication 존재
    • spring-boot-starter-data-jpa 포함
    • @EntityScan 또는 패키지 스캔으로
      domain-common의 엔티티를 정상 인식

즉,

domain-common은 실행 시점에는
“라이브러리처럼 로딩”되기 때문에 문제가 없었던 것
입니다.


11. 정리하며 배운 점

이번 이슈를 통해 명확히 정리된 포인트는 다음과 같습니다.

  1. 멀티모듈에서 공통 domain 모듈은 단독 실행 대상이 아니다
  2. @Entity는 Spring이 아니라 jakarta.persistence가 제공
  3. Lombok은 반드시 annotationProcessor까지 설정해야 한다
  4. Spring Boot BOM은 모든 모듈에 자동 적용되지 않는다
  5. domain-common:build는 성공하지 않아도 프로젝트 설계상 문제는 아닐 수 있다

12. 마무리

이번 경험은 단순한 에러 해결을 넘어서,
멀티모듈에서 “역할 분리”를 어떻게 해야 하는지를 명확히 이해하게 해주었습니다.

특히,

  • 공통 도메인 모듈 분리하려는 분
  • JPA 엔티티를 별도 모듈로 관리하려는 분
  • Lombok, JPA 인식 오류로 삽질 중인 분들께

분명 도움이 될 경험이라고 생각합니다.

 

 

[참고]
이 글은 실제 공개 프로젝트인 wecam 에서 발생한 에러입니다!
전체 코드가 궁금하다면 깃허브를 참고해주세요!! 

 

'ServerDev > SpringBoot' 카테고리의 다른 글

[SpringBoot - gRPC] 실시간 STT 스트리밍과 세션별 gRPC 스트림 분리 (Project: SpeakNote)  (0) 2025.12.13
[SpringBoot - WebSocket] 실시간 음성 스트리밍 서버 구조 (Project: SpeakNote)  (0) 2025.12.13
[Spring Boot] 사용자/관리자 API 분리를 위한 멀티모듈 설계 실전 가이드 (Common, User, Admin)  (0) 2025.12.13
[SpringBoot & FormData] JSON + 파일 업로드: HttpMediaTypeNotSupported 에러 해결  (0) 2025.12.09
[JPA] 동시성 제어 : LockModeType.PESSIMISTIC_WRITE  (0) 2025.12.07
'ServerDev/SpringBoot' 카테고리의 다른 글
  • [SpringBoot - gRPC] 실시간 STT 스트리밍과 세션별 gRPC 스트림 분리 (Project: SpeakNote)
  • [SpringBoot - WebSocket] 실시간 음성 스트리밍 서버 구조 (Project: SpeakNote)
  • [Spring Boot] 사용자/관리자 API 분리를 위한 멀티모듈 설계 실전 가이드 (Common, User, Admin)
  • [SpringBoot & FormData] JSON + 파일 업로드: HttpMediaTypeNotSupported 에러 해결
yeseul-kim01
yeseul-kim01
  • yeseul-kim01
    슬 개발일지
    yeseul-kim01
  • 전체
    오늘
    어제
    • 분류 전체보기 (79)
      • 자격증 (1)
        • 정보보안기사 (0)
      • DevOps (17)
        • Docker (6)
        • Kubernetes (1)
        • GitHub Actions (0)
        • AWS (4)
        • Monitoring (1)
        • Nginx (1)
        • GCP (3)
      • ServerDev (34)
        • SpringBoot (13)
        • DJango (5)
        • FastAPI (14)
        • Next (0)
        • Flask (0)
        • Database (2)
      • Algorithm (2)
        • BFS (0)
        • DFS (1)
        • 다익스트라 (0)
      • CS (8)
      • Data Engineering (1)
      • AI&MLOps (2)
      • Architecture (6)
      • Software Engineering (0)
        • Library Packaging (0)
      • Project (5)
        • docx-generator (0)
        • speak-note (2)
        • ms-serving (1)
        • keyshield (2)
      • ProgrammingLanguages (3)
        • Python (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Django
    FastAPI
    하이브리드아키텍처
    프로젝트기록-KeyShield
    백엔드
    트러블슈팅
    multipartfile
    프로젝트기록-speaknote
    실무일기-백엔드편
    SpeakNote
    rag
    멀티모듈
    di
    MLops
    STT
    SpringBoot
    실시간시스템
    동시성제어
    NLP부트캠프
    docker
    비동기처리
    Kubernetes
    실무일기-인프라편
    KeyShield
    grpc
    아키텍처설계
    FastAPI - CORS 마스터
    아키텍처
    KServe
    depends
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
yeseul-kim01
[Spring Boot 멀티모듈] domain-common 빌드 실패 원인과 해결 과정 정리 - Lombok, JPA @Entity 인식 안됨, Gradle 의존성 삽질기
상단으로

티스토리툴바