spring-boot 멀티모듈 설정하기

eden·2022년 5월 10일
0

spring

목록 보기
3/3
post-thumbnail

해당 포스팅은 2022년 5월에 작성되었으며, gradle을 이용한 멀티모듈 프로젝트 세팅에 관한 글입니다.

👹 통합된 단일모듈의 문제

일반적으로 프로젝트를 진행하는경우에 최소한 User API Server가 있을 것이고, API들을 안정적으로 서빙하고 데이터들을 관리할 수 있는 Admin API Server가 존재할 것입니다.

Admin관련 내용들만 별도의 패키지를 구성하여 API를 만들어 하나의 Jar파일에
Admin API와 User API 같이 배포하는 것도 하나의 방법이 될 수 있겠지만,
좋은 방법은 아닐 것이라 생각됩니다.

만약에 Admin API 통해 통계를 뽑아내는상황에서 데이터가 너무 많아 자원들을 모두 사용하게 된다면, 즉시 User API 영향을 줄 것입니다.

이외에도 많은 이유들을 포함하여 대부분의 서비스에서는 admin과 user는 분리하여 빌드하고 배포합니다.

🥴 멀티모듈이 무엇이고 왜 필요한건데?

위와 같은 이유로 프로젝트를 두개로 분리하여 진행한다고 가정했을 때,
개발자라면 직감적으로 불안감을 느끼게 됩니다.
가령 User라는 Entity의 필드로 (name, password)가 존재한다고 했을 때
우선 하나의 프로젝트에서 Entity를 만들고 복사 붙혀넣기를 통해 다른 프로젝트에 적용 시키게 될겁니다.

개발중 엔티티가 변경될때마다 매번 공통되는 부분을 N번 작업을 진행하는 불상사가 발생하게 됩니다.

(?!!!)

👥👥 Springboot 멀티 모듈설정하기

  1. Intellij의 Spring initializer로 프로젝트를 만들어줍니다
  1. 상단 이미지에서 src디렉토리는 사용하지 않기에 삭제해도 좋습니다.
  1. 최상단 프로젝트에서 우클릭으로 공통으로 사용할 모듈을 생성합니다.


  1. 같은 방법으로 user-api, admin-api 모듈을 생성합니다. 우선은 아무런 의존성도 넣지 않았습니다.

  2. core 모듈에 엔티티와 repository를 생성합니다.

  1. 프로젝트 최상단 settings.gradle 파일에 다음과 같이 모듈을 포함합니다.

systemlife명의 rootProject 하위로 core,user,admin 모듈을 포함합니다.

  1. 이후 최상위 프로젝트의 build.gradle 파일을 설정합니다.
buildscript {
    ext {
        springBootVersion = '2.6.7'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath "io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE"
    }
}

subprojects {
    apply plugin: 'java-library'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    group = 'com.chkim'
    version = '1.0'
    sourceCompatibility = '11'

    repositories {
        mavenCentral()
    }

    dependencies { // 서브 모듈에서 공통으로 사용할 의존성들
        compileOnly 'org.projectlombok:lombok:1.18.16'
        annotationProcessor 'org.projectlombok:lombok:1.18.16'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
        testImplementation('org.springframework.boot:spring-boot-starter-test') {
            exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        }
    }
}

project(':user-api') {
    dependencies {
        implementation project(':core')
    }
}

project(':admin-api') {
    dependencies {
        implementation project(':core')
    }
}

위 그레이들 파일에서 중요하게 봐야할 것은 subprojects와 project부분입니다.
우선 project부분은 코드만 보아도 모듈별 의존성 관리에 대한 부분임을 알 수 있고, subprojects 부분은 settings.gradle에서 포함한 모듈들을 전체적으로 관리합니다.

  1. core 모듈 build.gradle 파일 수정
plugins {
	id 'java'
}

group = 'com.chkim'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	api 'org.springframework.boot:spring-boot-starter-web'
	runtimeOnly 'com.h2database:h2'
}

tasks.named('test') {
	useJUnitPlatform()
}

dependencies안 api 키워드는 주목해서 보아야합니다.
위 최상위 프로젝트의 gradle에서 java-library와 관련이 있습니다.
https://developer.android.com/studio/build/dependencies?utm_source=android-studio#dependency_configurations

  1. admin-api, user-api 모듈 build.gradle설정
plugins {
    id 'java'
}

version 'unspecified'

repositories {
    mavenCentral()
}


dependencies {

}

test {
    useJUnitPlatform()
}

admin-api 모듈에서 core모듈의 users 엔티티를 정상적으로 가져와 사용하는 모습. core의 엔티티가 변경된다면 admin-api와 user-api모두 전파됩니다.

🖐 마무리

gradle도 알고쓰자

멀티모듈의 필요성으로 자료들을 찾았을 때 향로님의 블로그를 포함하여 많은 자료들이 있었지만 gradle버전에 따른 차이점들이 많았고 (compile keyword deprecated, api 등) gradle도 좀 더 깊이 이해하고 사용해야 함을 깨달았습니다.

부족한 부분이 있다면 언제든지 댓글 부탁드립니다 :-)

profile
다양한 것에 관심있는 개발자입니다.

0개의 댓글