일반적인 개발환경에서 한개의 Project만으로 구성되는 경우는 거의 없습니다.
간단히 다음과 같은 구조를 알아보도록 하겠습니다.
bookstore
- common : dependency none
- commonTest : dependenced common
- domain : dependenced common, test dependenced commonTest
- publicWeb : dependenced domain, common, test dependenced commonTest
- privateWeb : dependenced domain, common, test dependenced commonTest
이와 같은 '간단한' 프로젝트 구성이 있다고 할 때, 이런 구성에 있어서 기존 maven은 multiple project를 구성해서, 선행 project들을 local repository 등에 배포 후, dependency를 얻어와야지 되는 문제가 발생한다. 또한 각각의 project를 통해 생성되는 xml, wsdl등을 만약에 다른 project에서 이용한다면 maven에서는 매우 힘든 일을 거쳐야지 된다. (하는 방법은 잘 모르겠습니다.)
Gradle은 이와 같은 문제를 project dependency를 이용해서 쉽게 해결하고 있습니다. 이런 subproject들을 가진 project의 구성은 project의 folder와 동일하게 구성됩니다.
이러한 folder구조를 만들어주고, root project에서 gradle setupBuild 를 실행시켜줍니다.
지금까지 주로 사용하고 있던 build.gradle 파일뿐 아니라, sub project가 있는 부분은 settings.gradle 파일을 이용해서 구성합니다.
settings.gradle파일안에 다음과 같이 sub projects들을 모두 추가해줍니다.
rootProject.name = 'GradleBookStore' include 'common', 'commonTest', 'domain', 'privateWeb', 'publicWeb'
include 시에 순서는 상관이 없습니다. 또는 다음과 같은 코드를 이용해서 처리가 가능합니다.
rootProject.name = 'GradleBookStore'
String[] modules = ['common', 'commonTest', 'domain', 'privateWeb', 'publicWeb'] include modules
GradleBookStore project를 rootProject라고 칭하고, 나머지 project들은 모두 subproject라고 칭합니다.
1. 공통 설정
rootProject를 비롯한 모든 project에 필요한 설정이 필요할 때가 있습니다. maven repository설정 및 모든 공용 library들이 바로 여기에 속하겠지요.
모든 project에서 사용될 설정은 다음과 같이 수정합니다.
allprojects { apply plugin: 'java' repositories { mavenCentral() } dependencies { compile 'org.slf4j:slf4j-api:1.7.5' testCompile "junit:junit:4.11" } }
allprojects로 설정이 들어가게 되면, 모든 project들은 위 속성을 모두 가지게 됩니다. 이는 모든 sub project 폴더 안에 build.gradle 파일을 만들어주고, 위 내용을 적어주는 것과 동일한 효과를 가지고 옵니다.
2. SubProject 설정
위 공통설정과 비슷하지만 하나의 차이가 있습니다. 공통 설정으로 넣는 경우, root project 역시 java project로 구성이 됩니다. root project 역시 코드를 가질 수 있는 구조가 되게 됩니다. 그런데 이와 같은 구조는 현업에서는 잘 사용되지 않는 편입니다. root project의 경우에는 project의 이름으로 만들어주고, 내부에 subproject들로 구성이 되는 것이 일반적이지요.
따라서, 대부분의 project들은 allprojects 보다는 subprojects를 주로 사용하게 되는 것이 일반적입니다.
3. 특정 project 설정
특정 project에 설정을 해주는 방법은 두가지가 있습니다.
1) subproject의 build.gradle을 작성해주는 것
2) root project의 build.gradle에서 configure를 이용하는 방법
첫번째 방법의 경우, 매우 단순합니다. 그냥 build.gradle 파일을 만들어서 넣어주면 됩니다. 그렇지만, root project의 build.gradle에서 configure를 이용하는 방법은 조금 생각을 해봐야지 됩니다. configure의 경우에는 약간 이름과 다르게, filtering을 지원하는 방법입니다. 특정 project에서 사용할 설정을 넘겨주는 것을 담당합니다. 지금 구성되어 있는 project 중에서 publicWeb, privateWeb의 경우 war plugin을 이용해서 web으로 구성할 예정입니다. 이 경우에는 다음과 같이 구성을 하면 됩니다.
task webProjects << { subprojects.findAll { project.project.name.endsWith('Web') } } configure(webProjects) { apply plugin: 'war' task isWar << { println "${project.name} is web project" } }
project의 이름이 Web으로 끝나는 project에서만 war plugin을 적용한 코드입니다. task를 작성해서, target이 되는 project가 무엇인지를 확인시켜줘야지 됩니다. groovy에서는 마지막에 실행된 내용이 return 값이기 때문에 전체 build가 실행이 될때, subproject중에서 이름이 'Web'으로 끝나는 project만이 configure에 있는 속성이 적용됩니다.
이 부분을 잘 사용한다면, android project에서 target project의 모든 classes 파일들을 test project의 classes 폴더로 copy 해와서 처리를 하는 것이 가능하게 됩니다.
4. Project간의 종속성 설정
Gradle에서 가장 강력한 기능중 하나입니다. project간의 종속성을 설정은 기존 maven에 비하여 가장 강력한 기능입니다.
Project의 종속성은 만들어진 jar를 상대 project에서 이용하게 됩니다. 그리고, 하나의 Project에만 사용되는 설정이기 때문에, 이는 각 subproject의 build.gradle 파일을 이용합니다.
위에서 이야기드린 것 처럼, 각각의 dependency를 다시 보면 다음과 같습니다.
bookstore
- common : dependency none
- commonTest : dependenced common
- domain : dependenced common, test dependenced commonTest
- publicWeb : dependenced domain, common, test dependenced commonTest
- privateWeb : dependenced domain, common, test dependenced commonTest
* common의 경우에는 dependecy가 없기 때문에 build.gradle의 내용이 없습니다.
domain jar를 gradle :domain:build를 통해 build 할때, 다음과 같은 코드가 동작합니다.
c:\workspace\GradleBookStore>gradle :domain:build
:common:compileJava UP-TO-DATE
:common:processResources UP-TO-DATE
:common:classes UP-TO-DATE
:common:jar UP-TO-DATE
:domain:compileJava UP-TO-DATE
:domain:processResources UP-TO-DATE
:domain:classes UP-TO-DATE
:domain:jar UP-TO-DATE
:domain:assemble UP-TO-DATE
:commonTest:compileJava UP-TO-DATE
:commonTest:processResources UP-TO-DATE
:commonTest:classes UP-TO-DATE
:commonTest:jar UP-TO-DATE
:domain:compileTestJava UP-TO-DATE
:domain:processTestResources UP-TO-DATE
:domain:testClasses UP-TO-DATE
:domain:test UP-TO-DATE
:domain:check UP-TO-DATE
:domain:build UP-TO-DATE
:common:compileJava UP-TO-DATE
:common:processResources UP-TO-DATE
:common:classes UP-TO-DATE
:common:jar UP-TO-DATE
:domain:compileJava UP-TO-DATE
:domain:processResources UP-TO-DATE
:domain:classes UP-TO-DATE
:domain:jar UP-TO-DATE
:domain:assemble UP-TO-DATE
:commonTest:compileJava UP-TO-DATE
:commonTest:processResources UP-TO-DATE
:commonTest:classes UP-TO-DATE
:commonTest:jar UP-TO-DATE
:domain:compileTestJava UP-TO-DATE
:domain:processTestResources UP-TO-DATE
:domain:testClasses UP-TO-DATE
:domain:test UP-TO-DATE
:domain:check UP-TO-DATE
:domain:build UP-TO-DATE
compile시에 필요한 project가 먼저 build가 되고, 그걸 이용해서 새로운 jar가 만들어지고 있는 것을 알 수 있습니다.
특정 project만을 처리하는 것 역시 가능합니다. 기존 maven에서 문제가 되던 project -> local repository -> another project 의 build문제를 해결하고 있음을 알 수 있습니다.