Spring multi module

Seung jun Cha·2023년 5월 31일
0
  1. 의존성이 전혀 없는 프로젝트 생성 후 src 삭제
  2. 루트 디렉토리에서 api module 생성
  3. 똑같이 common module 생성
  4. root project의 setting.gradle에 module 참조 설정
include 'module-api'
include 'module-common'
  1. api가 common을 참조해야하기때문에 root project의 setting.gradle에 선언한 값과 동일해야 한다. 아래 코드를 api의 build.gradle에 추가
implementation project(':module-common') 
// root project -> settings.gradle에 선언한 값과 같아야함.

 tasks.register("prepareKotlinBuildScriptModel") {}

common-module의 요소를 api에서 사용하려면 빈으로 등록되어 있어야 한다. 하지만 컴포넌트 스캔은 등록된 패키지 하위부터 읽는다. 즉 package dev.be.moduleapi 패키지부터 읽는데 common 모듈은 여기에 들어가지 않으므로 api모듈에서 common 모듈은 빈으로 등록되지 않는다

  public String save(){
        System.out.println(CodeEnum.SUCCESS.getCode());   
        // 자바코드로 common 모듈을 참조하고 있는지 확인
       
       System.out.println(commonDemoService.CommonDemoService());
       // common 모듈에 있는 commonDemoService를 사용할 수 없다.
        return "save";
    }

그래서 직접 빈으로 등록할 패키지를 스캔해야 한다. 깨알팁은 ""안에서는 자동완성이 안되므로 먼저 코드로 쓰고 ""를 붙이면 편하다. api 모듈에서 필요한 모듈만 빈으로 등록하기 때문에 좀 더 효율적이다.
이때 module-api에 있는 settings.gradle는 삭제해주어야한다.
(이유는 정확히 모르겠지만 module-common과 모듈이 나누어져 있어서 스캔 대상으로 module-common이 인식이 안되지만, api에 있는 settings.gradle을 삭제하면서 api 모듈의 틀? 에서 벗어나면서 module-common이 인식이 되는듯?)

@SpringBootApplication(
        scanBasePackages = {"dev.be.moduleapi", "dev.be.modulecommon"}
)
public class ModuleApiApplication {
    public static void main(String[] args) {
        SpringApplication.run(ModuleApiApplication.class, args);
    }
}

예외처리
1. enum 클래스에서 예외 정의
2. 해당 예외에 대한 exception 클래스 생성 (RuntimeException 상속)
3. exception 클래스를 처리하는 exceptionHandler 생성
4. 공통적인 Response로 반환 : @JsonInclude(Include.NON_NULL)
null인 값은 응답객체에 필드를 보여주지 않기위해 위의 어노테이션을 사용

DB 연동
common 모듈의 build.gralde에 아래의 의존성을 추가한다. 이때 api가 아니라 implement로 선언하면 api모듈에서 Spring-data-jpa를 사용하지 못한다. 따라서 api를 사용하려는 build.gradle의 plugins에 id 'java-library' 추가하거나 상위 모듈(=root)에서 'java-library' 추가한다.

    ex) subprojects {
            apply plugin: 'java-library'
        }

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.12'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
	id 'java-library'
}

dependencies {
api 'org.springframework.boot:spring-boot-starter-data-jpa'
	}

그리고 엔티티와 repository의 패키지를 명확하게 인식하기 위해 @EntityScan@EnableJpaRepositories 어노테이션을 사용한다

@SpringBootApplication(
        scanBasePackages = {"dev.be.moduleapi", "dev.be.modulecommon"}
)
@EntityScan("dev.be.modulecommon.domain")
@EnableJpaRepositories("dev.be.modulecommon.repository")
public class ModuleApiApplication {
    public static void main(String[] args) {
        SpringApplication.run(ModuleApiApplication.class, args);
    }
}

멀티 모듈 환경에서 gradle을 사용해 빌드 및 배포
common 모듈의 build.gradle 파일에서

tasks.bootJar { enabled = false } // 기본값은 true

bootJar 옵션을 true로 설정하면 'xxx.jar' 파일이 생성된다.
ex) module-common-0.0.1-SNAPSHOT.jar
이렇게 생성된 'jar' 파일은 그 파일 안에 Application을 실행시키는 데 필요한
[dependencies / classes / resources]을 포함하고 있어 java -jar 옵션으로 jar 파일을 실행시킬 수 있다.

그런데 Common Module은 다른 Module에서 참조하는 목적의 Module이므로
실행 가능한 jar 파일을 생성할 필요가 없다.
그래서 ModuleCommonApplication.class는 존재할 필요가 없고, Common Module에서는 bootJar 옵션값을 false로 설정한다.

tasks.jar { enabled = true }  // 기본값도 ture지면 명시적으로 표시

jar 옵션을 true로 설정하면 'xxx-plain.jar' 파일이 생성된다.
ex) module-common-0.0.1-SNAPSHOT-plain.jar
이렇게 생성된 '-plain.jar' 파일은 'jar' 파일과는 다르게 dependencies를 제외한 [classes / resources]만을 포함하고 있어
java -jar 옵션으로 jar 파일을 실행시킬 수 없다.

Common Module에서는 Api Module에서 사용할 [classes / resources]만 존재하면 되므로 jar 옵션값을 true로 설정한다.

  • .jar 파일을 사용해서 빌드하고 실행하는 방법
    • root project에서 Gradle 빌드 명령어를 실행한다.
      ex) pwd 입력 시 "$HOME/xxx/yyy/Spring-Boot-2.7.1-Multi-Module-Template"
    • Api module을 실행시킬 jar 파일이 생성된 경로로 이동한다.
      ex) cd module-api/build/libs/
    • 해당 Path로 이동 후 java -jar 명령어를 실행한다.
      ex) java -jar module-api-0.0.1-SNAPSHOT.jar
    • ./gradlew clean 명령어는 기존에 만들어진 build 폴더를 모두 삭제한다

[Multi Module에서 Gradle 빌드 명령어 + jar 파일 실행 CLI]

  • Gradle 빌드 명령어 :: root project 위치에서
    -> ./gradlew clean :module-api:buildNeeded --stacktrace --info --refresh-dependencies -x test // 테스트 코드는 체크하지 않는다
    build 폴더에 '.jar', '-plain.jar'이 생성된다
  • profile 지정 X
    -> java -jar module-api-0.0.1-SNAPSHOT.jar
  • profile을 지정해서 빌드하려면
    -> java -jar -Dspring.profiles.active=local module-api-0.0.1-SNAPSHOT.jar

0개의 댓글