multi-module 가이드를 참조하여 Spring Boot로 멀티 모듈 프로젝트를 생성하는 스터디를 해보겠습니다.
멀티 모듈 프로젝트?
멀티 모듈 프로젝트는 기존의 단일 프로젝트를 프로젝트 안의 모듈로서 가질 수 있는 구조를 제공합니다.
장점
- 재사용, 공유 할 수 있다
- 빌드를 쉽게 할 수 있다
- 변경으로 인한 영향 최소화가 가능하다
- 의존성을 최소화한다.
목표
재사용 가능한 라이브러리를 생성하여 해당 라이브러리를 사용하여 "Hello, World" 메시지를 리턴하는 api 애플리케이션 빌드
환경
- Spring Boot 2.4.2
- Maven
- IntelliJ
- openjdk 11
프로젝트 생성
우선 스프링 부트 프로젝트 생성해봅니다.
모듈 생성
그다음 모듈을 생성하겠습니다.
위와 같은 방법으로 "api", "service", "core"라는 모듈 세 개를 생성합니다.
프로젝트 생성이 완료되면, 최상위 pom.xml (multimodule) modules 하위에 추가한 모듈을 확인할 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<groupId>com.moonsiri</groupId>
<artifactId>multimodule</artifactId>
<version>0.0.1</version>
<name>multi module</name>
<description>multi module project</description>
<modules>
<module>api</module>
<module>core</module>
<module>service</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<repositories>
<repository>
<id>MOONSIRI-REPOSITORY</id>
<url>...</url>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<!-- deploy repo setting -->
<distributionManagement>
<repository>
<id>MOONSIRI-REPOSITORY</id>
<name>MOONSIRI-REPOSITORY</name>
<url>...</url>
</repository>
</distributionManagement>
<properties>
<encoding>UTF-8</encoding>
<java.version>11</java.version>
</properties>
<dependencies>
<!-- 공통으로 사용하는 dependency 추가 -->
</dependencies>
</project>
core 모듈
core 모듈은 "jar"로 패키징 되어 다른 곳에서 사용되어야 하기 때문에 pom.xml(core)에 packaging 설정을 해줍니다.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <!-- jar로 packaging -->
<!-- 상위 pom.xml 사용 -->
<parent>
<groupId>com.moonsiri</groupId>
<artifactId>multimodule</artifactId>
<version>0.0.1</version>
</parent>
<groupId>com.moonsiri.multimodule</groupId>
<artifactId>core</artifactId>
<version>0.0.1</version>
<distributionManagement>
<repository>
<id>저장소ID</id>
<name>저장소명</name>
<url>저장소URL</url>
</repository>
</distributionManagement>
</project>
api 모듈에서 조회할 메시지를 설정 후 properties configuration을 생성합니다.
service.message=Hello, World
package com.moonsiri.multimodule.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("service")
public class ServiceProperties {
private String message; // service.message
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
maven deploy로 라이브러리를 레파지토리에 deploy합니다.
service 모듈
service 모듈은 core 모듈을 사용하기 위해 dependency에 추가를 해줍니다.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <!-- jar로 packaging -->
<!-- 상위 pom.xml 사용 -->
<parent>
<groupId>com.moonsiri</groupId>
<artifactId>multimodule</artifactId>
<version>0.0.1</version>
</parent>
<groupId>com.moonsiri.multimodule</groupId>
<artifactId>service</artifactId>
<version>0.0.1</version>
<dependencies>
<!-- core 모듈 사용 -->
<dependency>
<groupId>com.moonsiri.multimodule</groupId>
<artifactId>core</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
<!-- source 공개 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
core 모듈의 ServiceProperties로 메시지를 조회하는 Service를 생성합니다.
package com.moonsiri.multimodule.service;
import com.moonsiri.multimodule.config.ServiceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
@Service
@EnableConfigurationProperties(ServiceProperties.class)
public class MessageService {
private final ServiceProperties serviceProperties;
public MessageService(ServiceProperties serviceProperties) {
this.serviceProperties = serviceProperties;
}
public String message() {
return this.serviceProperties.getMessage();
}
}
메시지가 잘 조회되는지 Test Code를 작성하여 확인해보겠습니다.
package com.moonsiri.multimodule.service;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest("service.message=Hello, world")
class MessageServiceTest {
@Resource
MessageService messageService;
@Test
void getMessage() {
String message = messageService.message();
Assertions.assertNotNull(message);
System.out.println(message);
}
@SpringBootApplication
static class TestConfiguration {
}
}
maven deploy로 라이브러리를 레파지토리에 deploy합니다.
api 모듈
api 모듈은 service 모듈을 사용하기 위해 dependency 추가를 하고 빌드를 위한 설정을 추가합니다.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <!-- jar로 packaging -->
<!-- 상위 pom.xml 사용 -->
<parent>
<groupId>com.moonsiri</groupId>
<artifactId>multimodule</artifactId>
<version>0.0.1</version>
</parent>
<groupId>com.moonsiri.multimodule</groupId>
<artifactId>api</artifactId>
<dependencies>
<dependency>
<groupId>com.moonsiri.multimodule</groupId>
<artifactId>service</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
<build>
<finalName>module-api</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
message를 조회하는 api를 구현하겠습니다.
package com.moonsiri.multimodule.controller;
import com.moonsiri.multimodule.service.MessageService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ApiController {
private final MessageService messageService;
public ApiController(MessageService messageService) {
this.messageService = messageService;
}
@GetMapping("/message")
public String message() {
return messageService.message();
}
}
ApiApplication을 실행합니다.
package com.moonsiri.multimodule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
성공!
+)
멀티 모듈 환경에서 jsp 경로를 찾지 못한다면 IntelliJ Working directory에 $MODULE_WORKING_DIR$ 를 셋팅하면 됩니다.
https://stackoverflow.com/questions/44794588/intellij-run-configuration-spring-boot-vs-maven-issues
+)
젠킨스 설정
[Reference]
spring.io/guides/gs/multi-module/
'spring' 카테고리의 다른 글
[Spring] cannot deserialize from Object value (no delegate- or property-based Creator) (0) | 2021.08.18 |
---|---|
[SpringBoot] Test환경에 H2 적용하기 (0) | 2021.08.04 |
[SpringBoot] JWT 설명 및 생성, 검증 (0) | 2021.01.18 |
[Spring] JSONArray를 사용하지 않고 Ajax로 배열 list 넘기기 (2) | 2021.01.06 |
[Spring] java/jsp에서 properties value 불러오기 (0) | 2021.01.05 |
댓글