신입사원이 된지 어느덧 만4개월이 넘었다..
회사에선 자사 서비스를 운영하는데 프로젝트가 참 이상하게 구성돼있다.
한 프로젝트 안에 두개의 서비스가 운영되고있고 랜딩페이지나 이상한 잡다한것들이 많다.
그래서 나보고 한번 멀티모듈을 공부 해보라해서 공부하고 정리했다.
일단 멀티 모듈이란 말 그대로 모듈을 사용하는 것이다
모듈이라 함은 내가 이해하기론 여러곳에서 쓸 수 있는 함수
static같은 느낌 같았다.
먼저 우아한녀석들블로그에서 멀티 모듈을 정리한 글이 있어서 그 글을 참고했다. 링크는 맨 하단에 기입해두겠다.
하나의 단일 프로젝트를 여러 개의 모듈로 분리해서 구성하는 기법.
모듈간 의존성을 최소화하여 유연하고 확장성 있는 애플리케이션을 개발하기 위해 사용됨.
서로 독립적인 프로젝트 단위를 가지고 있다. 이런 구조일 경우 큰 문제점은 시스템의 중심 Domain이 가져야 할 구조와 규칙 등을 동일하게 보장해주는 메커니즘이 없다.
이럴 경우 한 프로젝트에서 수정을 하면 다른 프로젝트에 복&붙하며 개발을 해야한다.
그래서 Domain을 모듈화 하여 공통 코드를 모아두고 같이 쓸 수 있게 해주는 것이다.
공통으로 사용하는 코드들을 Common(공통)이라는 모듈에 담는다.
‘이제 수정 사항은 Common 모듈에서 하면 된다…’
A 애플리케이션에서 기능을 추가한다. 개발자는 코드를 어디에 작성할지 고민 하게 되고, 공통 모듈에 점점 추가될 것이다. B 애플리케이션도 마찬가지 일 것이다.
이제 C 애플리케이션에서 기능을 추가한다. 공통 모듈에 유용해 보이는 코드들이 있다. 사용한다.
사실 이 기능은 A 애플리케이션을 위해 작성된 코드이다. 이 과정이 반복이 되면 공통 모듈은 점점 커지고 애플리케이션에서 하는 일들이 줄어들고 공통 모듈에서 더 많은 일을 하게 될 것이다.
A를 B로, B를 C로 가공한 코드에서 다시 C에서 A로 가공한 코드가 나온다. 예를 들어 아래와 같이
java
class AService {
private final ARepository aRepository;
public A act(Long id) {
...
return aRepository.findById(id);
}
}
class BService {
private final AService aService;
public B act(Long id) {
A a = aService.act(id);
...
return mapToB(a);
}
}
class CService {
private final BService bService;
public C act(Long id) {
B b = bService.act(id);
...
return mapToC(b);
}
}
class DService {
private final CService cService;
//띠용!!
public A act(Long id) {
C c = cService.act(id);
...
return mapToA(c);
}
}
예를 들어 DB를 사용하지 않는 애플리케이션에서 공통 모듈을 사용하기 위해 데이터베이스와 커넥션을 맺게 된다. 그 외에 다른 의존성도 마찬가지다.
Thread Pool, Connection Pool, Timeout 등의 설정도 몰리게 된다.
대표적인 예로 DB 커넥션이 있다. 모든 DB에는 가질 수 있는 최대 커넥션 개수가 정해져 있다.
Spring Boot 3.1.3
JDK 17
Oracle - dev, Maria - local
JPA
Gradle 9.0 - Groovy
Intellij IDE
먼저 구조는 이렇게 나눴다.
api api2 core util
api - insert user
api2 - get user
core - entity, repository, config
util - dto
모듈을 새로 만든다.
언어, 시스템빌드, JDK, Gradle 언어를 선택하고 모듈 이름을 작성한 후 생성
모듈을 생성하면 include ‘모듈명’ 이라고 생성 될 것이다. 생성이 안되면 직접 입력하면 된다.
root 프로젝트 build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.3'
id 'io.spring.dependency-management' version '1.1.3'
}
bootJar.enabled = false
sourceCompatibility = 17
targetCompatibility = 17
tasks.named('test') {
useJUnitPlatform()
}
subprojects {
group = 'com.exam'
version = '0.0.1-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
maven { url 'https://maven.atlassian.com/3rdparty/'}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}
}
project(':api') { // 컴파일 시 core 로딩
dependencies {
compileOnly project(':core')
compileOnly project(':util')
}
}
project(':api2') { // 컴파일 시 core 로딩
dependencies {
compileOnly project(':core')
compileOnly project(':util')
}
}
project(':core') { // core는 bootJar로 패키징 할 필요 없음
**bootJar** { enabled = false }
jar { enabled = true }
}
subproject에 담긴 정의들이 하위 Module들에 대한 정의이다.
공통적으로 필요한 종속성들만 root - build.gradle에 정의한 후 필요에 따라 각 모듈들의 build.gradle에 종속성을 추가하면 된다.
예) api2 project에만 lucy 종속성을 추가하고 싶을 때
각 서비스에 필요한 모듈만 사용할 수 있다.
root - build.gradle
api, api2 - build.gradle
두 정의는 다르기 때문에 둘 다 기입해야 한다.
root
프로젝트의 dependencies
블록은 모든 하위 프로젝트 간의 공통 의존성을 관리하는 데 사용되며, api
프로젝트의 dependencies
블록은 해당 프로젝트 자체의 의존성을 정의하는 데 사용된. 따라서 이러한 코드 블록은 서로 다른 범위와 역할을 가지고 있으며, 다른 것으로 취급된다.
core - build.gradle
두 개의 서버가 실행되고 있다. 8080 / 8081
하나의 core 모듈로 두 서비스가 실행 가능함
Entity
util Module
util Module
https://dkswnkk.tistory.com/691
https://techblog.woowahan.com/2637/
https://hyeon9mak.github.io/woowahan-multi-module/#️-msa-멀티-모듈
멀티 모듈 적용에 있어서 정답은 없는것 같다.
어떻게 나누고의 문제가 아닌 어떻게 사용하고의 문제인것이다.
위에서 정리한 스파게티코드, 의존성, 설정 같은 문제들이 일어나지 않게 잘.. 잘 작성하면 되지 않을까 싶다 ㅋㅋㅋ
아마 회사에서 멀티모듈 적용시키는것 그 외 여러 테스트(multi db connection, security..)가 끝나면 내 업무의 주가 거의 이것이 될것같다.
이직할때 참 도움이 될만한것같은 느낌이다.
싸구려 구조인 프로젝트 -> 멀티모듈 적용시키기..
주니어도 안되는 껍대기 수준 개발자가 이걸 했다면 과연 좋아는 할까.. 열심히 해야겠다.