1. 서론

 

CQRS 구성을 위해 일반적으로 Command, Query 두가지 Application을 구성합니다. 이때 Application 사이 매개체 역할을 Event가 담당합니다. 따라서 Event 정보를 알기 위해서는 Event 정보가 두 App에 모두 포함되어야 합니다.

 

 

일반적인 프로젝트 구조라면 동일한 소스 코드가 두 App에 모두 존재해야되므로 Event의 변경사항이 있을 때 양쪽 Application의 구조를 바꿔야합니다. 더군다나 Axon에서는 Event 클래스의 패키지 구조가 동일해야되는 제약사항이 존재합니다. 따라서 이러한 문제를 해결하기 위한 다양한 방법중 Gradle을 활용해서 MultiProject 구성을 하고자 합니다. 

 

 

즉 Event 클래스만 모은 공통 모듈을 작성하고, Command, Query에서 이를 참조하도록 구성합니다. 이렇게 별도 모듈로 분리함으로서 변경 사항 발생시 공통 모듈에만 변경을 가하면 양쪽 App에 적용되므로 소스 관리가 용이해집니다.

 

자세한 내용은 Gradle 공식 문서를 참조하시기 바라며, 이번 포스팅에서는 기본적인 Gradle Multi Project 구성 방법에 대해서 알아보겠습니다.

 

참고 블로그

와이케이 마구잡이님 블로그

jojoldu님 블로그


2. Gradle 프로젝트 생성

 

1. IntellJ에서 Create New Project 를 클릭합니다.

 


2. Spring 프로젝트를 만들기 위해서 Spring Initializr를 선택합니다. 이후 Java SDK 버전 선택한 다음 Next 버튼을 눌러 다음 단계로 진행합니다.

 


3. Gradle 프로젝트 생성을 위해 Type을 Gradle Project로 설정합니다. 이후 Group과 Artifact를 본인 프로젝트 구성에 맞게 기입하니다. 마지막으로 Java version을 PC에 설치된 Java 버전과 동일하게 설정 후 Next 버튼을 선택합니다.

 


4. 의존성은 나중에 별도 추가할 예정이므로 Next 버튼을 눌러 다음 단계로 이동합니다.

 


5. Project 이름 설정 후, Finish 버튼을 선택합니다.

 


6. Gradle 설정 화면에서 특별하게 변경해야할 사항이 없다면 기본 설정 상태에서 OK 버튼을 선택합니다.

 


7. 의존성이 정상적으로 추가되면 아래 이미지 하단과같이 sync가 정상적으로 이루어짐을 확인할 수 있습니다. 지금 생성한 프로젝트는 root 프로젝트이므로 src 폴더 전체를 선택 후 삭제합니다.

 

 


3. Multi Module 구성하기

 

1. 프로젝트내 모듈은 3가지(Command, Query, Common)입니다. 따라서 이를 구성하기 위해서 root 프로젝트 내 settings.gradle 파일을 연 후에 아래 이미지와 같이 sub module명을 기입합니다.

 


2. 이제부터 프로젝트 구성을 위해서 구조 변경이 필요합니다. 먼저 root 프로젝트에 있는 build.gradle 파일을 엽니다. 이후 AS-IS로 되어있는 구조를 TO-BE 형태로 변경합니다.

 

AS-IS

plugins {
    id 'org.springframework.boot' version '2.2.2.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

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

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
    useJUnitPlatform()
}

 

TO-BE

buildscript {
    ext {
        springBootVersion = '2.2.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

allprojects {
    group = 'com.cqrs'
    version = '0.0.1-SNAPSHOT'
}

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

    sourceCompatibility = '11'

    repositories {
        mavenCentral()
    }

    dependencies {
        testImplementation('org.springframework.boot:spring-boot-starter-test') {
            exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        }
    }

    task initSourceFolders {
        sourceSets*.java.srcDirs*.each {
            if (!it.exists()) {
                it.mkdirs()
            }
        }
        sourceSets*.resources.srcDirs*.each {
            if (!it.exists()) {
                it.mkdirs()
            }
        }
    }
}

project(':command') {
    dependencies {
        compile project(':common')
    }
}

project(':query') {
    dependencies {
        compile project(':common')
    }
}

 

변경한 build.script 내용을 설명하면 다음과 같습니다.

 

buildscript 블록 : 나머지 스크립트를 빌드하는 과정에서 필요한 외부 라이브러리를 classpath에 추가하는 기능을 담당합니다. subprojects 내에서 플러그인 적용(apply plugin)이 가능한 이유 또한 buildscript를 통해 라이브러리를 classpath에 추가시켰기 때문입니다.

 

allprojects 블록 :  root 프로젝트(demo)와 하위 프로젝트(command, query, common)에 모두 적용되는 빌드 스크립트 기준을 작성합니다.

 

subprojects 블록 : 하위 프로젝트(command, query, common)에만 적용되는 빌드 스크립트 기준을 작성합니다.

  • sourceCompatibility : java 버전을 명시합니다.
  • repositories : 저장소 설정을 담당합니다. 
  • initSourceFolders task : sub module별로 기초 디렉터리가 존재하지 않으면, 자동 생성해주도록 설정합니다.

 

projects 블록 : Command, Query App은 빌드시에 공통 모듈(Common)이 포함되어야 함으로 빌드시에 추가하도록 설정합니다.

(※ : 가 들어간 이유는 Root 프로젝트 기준으로 각 모듈은 한단계 아래 계층에 존재하기 때문에 이를 구별하기 위함입니다.)


3. intellij 우측 gradle 탭을 엽니다. 이후 root 프로젝트 > Tasks > build > build를 더블클릭하여 build를 시도합니다. build 수행하면 root 프로젝트에 src 폴더를 지웠기 때문에 build 실패가 발생하지만, 좌측탭에 command, common, query 폴더가 생긴 것을 확인할 수 있습니다.

 


4. sub module 폴더 내에 build.gradle 파일을 생성합니다.


5. Command, Query App에서는 Spring Web MVC를 사용하기 때문에 build.gradle에 의존성을 추가합니다.

 


6. Command 모듈에서 패키지 생성을 위해 src > main > java 디렉토리 선택 후 [Alt + Insert] 키를 누릅니다. 이후 package 탭을 선택합니다.

 


7. 임의의 package 명을 입력한 후 OK 버튼을 누릅니다.

 


8. 생성된 package 하위에 App 실행을 위한 main 클래스를 작성합니다.

 


9. App을 구동하여 정상 작동하는지 확인합니다.

 


10. 5~9번 작업을 query 모듈에도 반복합니다.

 

 

위와 같이 정상적으로 수행된다면 Multi Project 기초 구성은 끝났습니다.


4. 마치며

이번 포스팅에서는 각 모듈별 기초적인 의존성 추가 및 모듈 구성을 했습니다. 다음 포스팅에서는 데모 프로젝트 진행을 위해서 각 모듈별 필요한 의존성 추가 및 코드 구현을 본격적으로 하겠습니다.

 

+ Recent posts