include 'module-api'
include 'module-common'
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로 설정한다.
[Multi Module에서 Gradle 빌드 명령어 + jar 파일 실행 CLI]