스팅 시작하기 앞서

 Gradle을 도입한 목표중 하나는 단일 소스 코드로 목적에 맞는 다양한 APK 생성입니다. 모듈 내부에서 디버그, 릴리즈와 같은 빌드 타입별로 세부사항을 변경하거나, lite, full 버전 과 같이 기능 일부를 비활성화 할 수 있습니다.(feature 변경) 

 빌드 변형은 빌드타입과 제품특성을 합한 개념입니다. 어떤 모듈에 3가지 빌드타입과 4가지 제품 특성이 존재한다면 빌드 변형은 3*4=12가지 경우입니다. 이번 포스팅에서 빌드타입에 대해 살펴보도록 하겠습니다.


빌드타입

build type 에는 debug와 release가 존재합니다. 디버깅이 포함된 apk이냐 마켓에 배포할 apk냐에 따라 구분되어집니다. 

debug build는 default대로 진행하면 되고, release 빌드때는 pro guard 를 비활성화 하였습니다.

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

다음과 같이  minifyEnabled true로 하면 프로가드가 활성화됩니다. 소스코드난독화하여 역컴파일을 방지하게 됩니다.

프로젝트 폴더에들어가서 gradlew :app:assemble 명령을 치면 빌드가 완료되고나서 debug, release apk 가 생성됨을 확인하실 수 있습니다.

또한, 그렇게 하기 귀찮으시면 gradle 콘솔(안드로이드 프로젝트)을 열어서 assemble 태스크를 실행하시면 되겠습니다. app모듈에 build 그룹에 있습니다.


다음과 같이 assemble task를 실행시키고나면, debug용도와 release용도의 apk가 생성됨을 확인하실 수 있습니다.




앱 서명 첨부하기

release 용을 빌드할떄는 앱서명(siging)에 관한정보를 직접 지정하여 등록하셔야 합니다. signing을 할때 module build.gradle을 수정하는데, android 블록아래에 signingConfigs를 입력합니다. 물론 siginingConfigs는 buildTypes 블록보다 먼저 정의되어야 합니다.


signingConfigs{
release{
storeFile file('app.keysave')
storePassword 'keypass'
keyAlias 'key'
keyPassword 'mypassword'
}
}


buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

그런데 문제는, 앱서명에 관한정보를 직접 썼다는게 보안상의 문제로 될수있습니다. 그러므로 담당자 서버의 환경변수에 별도로 지정하는게 좋겠습니다.

signingConfigs{
release{
storeFile file('app.keysave')
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}

그리고 환경변수를 윈도우에서 설정해줍시다. 예로들어 KEYSTORE_PASSWORD라는 환경변수를 읽어오기 위해서는 ORG_GRADLE_PROJECT_KEYSTORE_PASSWORD 라고 환경변수 이름을 짓고, 변수값을 넣어서 생성하면 gradle에서 환경변수로 값을 얻어오실 수 있습니다.


제품 특성

빌드타입이 빌드의 속성을 변경하는것이라고 앞서 설명드렸습니다. 제품 특성은 리소스 교체 혹은 특정 feature를 활성화 또는 비활성화 시킬 수 있습니다. module build.gradle에 기술하시면 되겠습니다.



제품 특성 생성 해보기

제품 특성 생성하려면 android 블록에 productFlavor 블록을 추가합니다. lite와 full이라는 제품 특성 추가해보겠습니다.


productFlavors{
lite{
applicationId 'com.lite.HelloWorld'
}
full
}

.



제품 특성 확인


추가된 제품 특성을 확인하려면 Android Studio IDE 좌측 하단에 세로방향으로 위치한 Build Variants 창을 활용합니다. app모듈에 build Varient를 선택해보시면, full,lite 조합 release, debug로 나오는것은 확인하실수있습니다. 2*2 =4가지경우가있네요. 원하시는 값을 선택후 build apk를 하였더니 아래그림처럼, app-gull-release apk가 생성됨을 확인할 수 있었습니다.





제품 특성 활용

제품특성을 간단히 적용하려면 AndroidManifest.xml 을 변경한후 재빌드 하면 되긴합니다. 엄청 번거롭죠. 그러나 제품특성을 활용하면 더욱 쉽고 간편하게 적용시킬 수 있습니다. 예를든다면 lite 버전의 로고와 app label을 변경합니다.  app 모듈의 src폴더 아래 lite 폴더를 만들고 AndroidManifest.xml 파일을 추가합니다. Project View로 진행하시면 됩니다.



프로젝트뷰로 다음과 같이 lite폴더에 AndroidManifest.xml 파일을 추가하였습니다.

그리고 Android 뷰로 돌아오면 lite버전의 AndroidManifest.xml 파일이 추가된것을 확인하실 수 있습니다. 추가된 파일에는 (lite)라고 추가됨을 확인하실 수 있습니다. 

제품특성은 module build.gradle의 android.defaultConfig블록의 속성값을 공유하게 됩니다. defaultConfig블록은 간단히 요약하면 AndroidManifest.xml 의 내용 중 gradle로 재정의할 수 있는 속성들입니다. 또한 제품특성은 소스 코드를 재정의할 수 있습니다. 변경량은 최소화 하는게 좋습니다.




제품 특성으로 특정기능 활성화 (Feature On)

 제품특성을 활용하면 전체 app,의 기능 중 일부를 활성화 또는 비활성화 할 수 있습니다. 예를들어 full 제품 특성에서는 현재 시간 표시 기능을 활설화 하고 demo제품 특성에서는 현재시간을 보여주지 않게 합니다. 모듈 build.gradle에서 BuildConfig변수를 활용하면 됩니다.


productFlavors{

   full{

  buildConfigField "boolean", "SHOW_CURRENT_TIME", "true"

  }

   lite{

   buildConfigField "boolean", "SHOW_CURRENT_TIME", "false"

  }

}


SHOW_CURRENT_TIME이라는 boolean 변수를 추가했습니다. 내용을 입력하고 SYNC NOW버튼을 누르면 변수가 자동으로 생성되어 소스코드에서 참조할 수 있습니다.


 if(BuildConfig.SHOW_CURRENT_TIME){

  

}


실제확인하려면 app/build/generated/source/buildConfig/lite/debug/com/프로젝트 폴더에 BuildConfig클래스를 열어봅니다. applicationid등 빌드스크립트가 생성한 다양한 변수가 있는것을 확인하실 수 있습니다.




Android application Test 방법


크게 2가지가 있습니다. 안드로이트 테스트(Instrumentation Test)와 Local PC의 JVM을 활용하는 새로운 개념의 Local Unit Test 입니다. 


참고) 로컬 유닛 테스트는 로컬 JVM을 활용하기 때문에 타깃 디바이스와 연결피 필요없습니다. 그리고 테스트 코드의 전체 실행속도가 향상되는 효과가 있습니다. 안드로이드 테스트에서는 APK를 생성하여 타깃 디바이스에 설치하고 실행하는 과정에서 시간 소모가 많은 편입니다.



Gradle을 활용화여 안드로이드 테스트 코드와 로컬 유닛테스트코드를 실행하는 방법을 알아보겠습니다.




로컬 유닛 테스트

app module의 build.gradle을 보시겠습니다. dpendencies부분에 아래와 같이 testCompile이 웬만하면 디폴트로 지정되어있으실겁니다.


dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
}

그리고 ExampleUnitTest 클래스를 보시면 아래와 같이 코드가 미리작성되어있는것을 확인하실 수 있습니다. Junit4에서는 테스트코드에 @Test라는 애너테이션을 부착합니다.

public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}

로컬유닛 테스트 코드를 실행하는 방법은 간단합니다. 패키지명을 우크릭하고 "Run Tests in 프로젝트명" 클릭하면 Run창에 테스트 결과가 출력됩니다. 

해당 unitTest 클래스 오른쪽 마우스로누르고, run "ExampleUnitTest" 선택시 정상적으로 테스트됩니다.


로컬유닛테스트를 실행할때 호출되는 중요한 Gradle Task는 다음과 같습니다.


:app:mockableAndroidJar UP-TO-DATE

:app:compileDebugUnitTestSources UP-TO-DATE


1. mock(app:mockableAndroidJar ) 테스크는 안드로이드의 android.jar 파일을 mock 인터페이스로 컴파일합니다. 로컬 유닛 테스트가 동작하려면 안드로이드 코드에 대한 mock 인터페이스가 필요합니다. mock 인터페이스 호출 시, 가짜객체를 주입하는 경우도 있습니다. 가짜 객체(mock object)를 이용한 테스트 기법은 구글문서를 참고하십시오.


mock 테스트 실행결과는 /build/generated/mockable-android-26.jar(26은 버전명) 입니다. 


2. complieDebugUnitTestSources 태스크입니다. 태스크 이름자체대로 디버그 모드로 로컬 유닛 테스트 코드를 컴파일합니다. 릴리즈 모드일때는 릴리즈 이름에 맞게 테스크가 실행되는것을 확인하실 수 있습니다. 



또한, 콘솔에서도 테스트코드를 실행하실 수 있습니다. HTML로 결과가 출력되는데요.  프로젝트 폴더에서 cmd창을 연 후,


> gradlew :app:testDebug 

와같이 치신후 엔터를 누르고, app/build/reports/tests/debug 폴더에 테스트 결과를 확인하실 수 있습니다.




안드로이드 테스트

안드로이드 테스트코드는 Activity, Fragment, ButtonView, TextView 등 UI컴포넌트와, 유틸리티클래스와 같은 Java클래스 모두 테스트할 수 있습니다. 다만 에뮬레이터나, 타깃 디바이스에서 실행해야하는 제약이 있습니다 .

저는 MainActivityTest라는 클래스를 만들고 아래와 같이 코드작성 후, 실시해보겠습니다.

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
public MainActivityTest() {
super(MainActivity.class);
}


public void testHelloLabel(){
Activity ac = getActivity();

}

app 모듈의경우 /app/src/androidTest/java 폴더에 위치하고있습니다. 실행하는 방법은 로컬 유닛테스트와 유사합니다.

오른쪽마우스 누르고, run "MainActivityTest" 를 실행합니다.


:app:compileDebugAndroidTestSources

이번에 실행된 gradle test는 unitTest가 아닌, AndroidTest로 바뀐것을 확인하실 수 있습니다.


콘솔에서도 역시 확인하실 수 있습니다.

gradlew :app:connectedAndroidTest + 엔터 치시면됩니다.gradle 콘솔창에 뜨듯이 진행후, 완료구문을 확인하실 수 있습니다.



.


Espresso 연동하기

Espresso는 Android Testing Support Library에 편입되었습니다. 강력한 테스팅 도구이죠. 연동하는 방법을 살펴보시겠습니다.


app모듈의 build.gradle의 내용 추가입니다.


defaultconfig{


  testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}


그다음 denependencies블록에 추가할 내용입니다.


androidTestCompile 'com.android.support.test:runner:0.4.1'

androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'


compile 'com.android.support:appcompat-v7:23.0.1'




로컬 유닛 테스트의 제약사항

로컬 유닛테스트 같은 경우 andoir.util.Log 클래스에 대한, mock 인터페이스가 제공되지안항 오류를 낼때가있습니다.

이를 피하려면  모듈 build.gradle에 다음 내용을 추가해야합니다.


android{

    

   testOptions{

unitTests.returnDefaultValues = true

   }


}

근본적으로 해결하려면 PowerMock과 같은 라이브러리를 활용하여 log 클래스의 static 메서드를 위한 가짜 객체를 주입하는 방법이 있습니다. PowerMock 관련 문서를 참조하시기 바랍니다.





들어가기 앞서

 Gradle 에서는 프로젝트를 단일 프로젝트나 멀티 프로젝트로 구성할 수 있습니다. 멀티프로젝트는 하위 폴더에 여러개의 Module을 추가할 수 있습니다. Android Studio 는 프로젝트를 생성하면 자동으로 멀티 프로젝트로 구성되고, 하위에는 App Module이 추가되어 있습니다. 



Android Library Module 만들기
 안드로이드 라이브러리 모듈은 com.android.libaray 플러그인이 필요하고, 그결과 AAR파일을 생성 할 수 있습니다. 
AAR파일은 JAR파일과 비슷해보일 수 있지만 다른점은, 하나의 앱처럼 안드로이드 화면을 포함할 수 있다는 점입니다. JAR 파일은 순수 로직만 포함할 수 있습니다. 하지만 AAR파일은 res폴더의 xml 이미지, 리소스등을 포함할 수 있기때문에 안드로이드 화면을 표현할수 있게 됩니다. 

다음은 안드로이드 라이브러리 모듈을 생성하는 과정입니다. 안드로이드 스튜디오에서 [File -> New -> New Module]을 선택합니다. 그 이후 안드로이드 라이브러리 모듈을 선택하고 이름은 MyLibModule이라고 하겠습니다.

그리고 build.gradle에 settings.gradle에 보시면 include된것을 확인하실 수 있습니다.
include ':app', ':mylibmodule'
또한 build->makd module 'mylibmodule' 을선택하면 aar파일이 생성되는것을 outputs 폴더에서 확인하실 수 있습니다.


Gradle 로컬 저장소 만들기에 앞서
 현업에서 상용프로젝트를 개발할때, 라이브러리를 gradle을 이용해서 참조해서 사용하는 경우가 있습니다. 그런데 jcenter나 maven center에 올려버리면 보안상 문제가 생길 우려가 엄청납니다. 그러므로 사내에 로컬 저장소를 만들어서 운영해야 할 것입니다.


Gradle 로컬 저장소 만드는 방법
 Gradle에서 로컬 저장소를 지정하는 방법을 배워보겠습니다. 
공동작업을 위해서는 프로젝트 폴더 하위에 로컬 저장소를 두는것이 일반적입니다. 먼저 프로젝트 홈폴더를 환경변수에 등록하겠습니다. 

ORG_GRADLE_PROJECT_HOME 환경변수는 gradle 스크립트에서 $PROJECT_HOME으로 참조할 수 있습니다.

다음과 같이 Project의 build.gradle을 변경합니다.

allprojects{
   reposotories{
     jcenter()
     mavne{
      url "file://($PROJECT_HOME)./myReposiroy"
     }
   }

}


참조할 수 있는 로컬 저장소가 생성되었습니다. URL은 위의 "file://($PROJECT_HOME)./myReposiroy" 와 같습니다.

그다음 mylibmoudle을 빌드한 결과를 로컬 저장소에 업로드할 수 있도록 uploadArchives 블록을 정의합니다.

mylibmoudle 모듈의 build.gradle 파일 아래쪽에 다음 내용을 추가합니다.


apply plugin: 'maven'

group ='com.exam.mylibmodule'

version = '1.0'


uploadArchives {

  repositories{

     mavenDeployer{

         repository( url: "file://($PROJECT_HOME)./myReposiroy")

      }

   }

 

}


업로드할 저장소의 URL과 그룹이름, 버전을 지정하면됩니다. group, version, repository url을 확인하실 수 있습니다.


uploadArchives 태스크를 실행해야합니다. 해당 프로젝트 폴더로 가서 gradlew :mylibmodule:uploadArchives 라고 치시면, 해당 태스크를 실행하고 .aar파일이 지정했던 repository에 생성되는것을 확인하실 수 있습니다. 




마지막으로 로컬저장소에 배포된 .aar파일을 참조하도록 하겠습니다.

app모듈에서 build.gradle을 아래와 같이 변경하면 되겠습니다.


dependencies{

  compile 'com.exam.mylibmoudle:mylibmodule:1.0@aar'

}


이제 app moudle에서 library module 의 액티비티를 직접 실행하실수있습니다. 라이브러리르 모듈을 참고하기 때문이죠.

이상입니다.




- 들어가기 앞서.

 안드로이드 앱을 개발하다보면, 다양한 외부라이브러리를 참조해야할 경우가 발생합니다. 이를 프로젝트에서의 dependency(의존성) 이라고 합니다. 과거 이클립스의 경우에는 라이브러리 파일을 다운로드하여 프로젝트의 libs 폴더에 복사하고 다시지정하는 과정이 매우 번거로웠습니다. 하지만 gradle 에서는 이런 문제점을 해결하였습니다. 그만큼 gradle은 이전에 문제가 되었던 많은 부분들을 보완한것을 알 수 있습니다.



- 가장 기본적 Gradle 외부라이브러리 참조 방법

 app module의 dependencies 블록에 ㅂ외부 라이브러리를 지정합니다. 외부 라이브러리를 지정할때 compile 명령을 사용합니다. 

http://fsd-jinss.tistory.com/36 앞서 생성했던 안드로이드 그래들 프로젝트에서의 app module gradle dependencies 부분을 살펴 보시겠습니다.

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) //1
testCompile 'junit:junit:4.12'                                     //2
compile 'com.android.support:appcompat-v7:26.0.0-alpha1'            //3
}


1. libs폴더의 JAR파일을 추가하는 방법입니다.

2. 테스트 빌드시 참조하는 라이브러리 입니다.

3. 로컬에 없는, 외부라이브러리를 참조합니다. Gradle 에서 외부 라이브러리를 참조하기 위해서는 다음 세가지 정보가 필요합니다.


- group Id : 라이브러리 패키지 이름이 필요합니다. (com.android.support)

- arifact id : 라이브러리 이름이 필요합니다. (appcompat)

- version   : 참조하는 버전명이 필요합니다. (v7:26.0.0-alpha1)




다른 모듈 소스코드 참조하기


아래는 라이브러리 모듈(library module, app module 말고요)의 소스코드 참조하는 방법입니다.

dependencies {

  compile project(':mylibrary')

}


다음은 하위폴더에 위치한 라이브러리 모듈의 소스코드를 참조하는 방법입니다.

lib_modules 폴더 하위에 mylibrary가 위치한다면 다음과 같이 기술합니다.

dependencies {

  compile project(':lib_modules:mylibrary')

}


디버그 모드와 릴리즈 모드 참조하기

 dependencies {

 debugCompile 'com.abcd.test:myTest-android:1.3'

 releaseCompile 'com.abcd.test:myTest_release-android:1.3'

}

디버그 컴파일과 릴리즈 컴파일로 구분합니다.



안드로이드 유닛 테스트 참조하기

dependencies {
androidTestCompile 'junit:junit:4.12'
}

참고로 androidTestCompile은 안드로이드 UI 테스팅할때 사용하는 명령어로, testCompile과 구별됩니다.



공개라이브러리 참조하기 - JAR 파일

HTTP 클라이언트와 웹소켓 클라이언트를 지원하는 AndroidSync 참조 예입니다. github에 Gradle에서 간편하게 추가하는 방식을 소개하고있습니다.

 dependencies{

 compile 'com.koushikdutta.async:androidasync:2.+'

}



공개라이브러리 참조하기 - AAR 파일

AAR파일을 참조해야하는 경우가 있습니다.  @aar을 끝에 붙여주면 됩니다.


dependencies{

  complie 'com.abcd:andrid-xxx:1.0.1@aar'

}



로컬에 있는 AAR파일 참조하기

로컬에 AAR을 복사하여 참조하는 경우도 있을 수 있습니다. 이럴때는 libs 폴더에 복사후 gradle을 통해 참조할 수 있습니다. 

이때 module build.gradle 파일의 dependencies 블록만 변경해서는 안되고, repositories 블록도 함께 변경해야 합니다.

repositories{
flatDirs{
dirs 'libs'
}
}


다음 예는 mylibrary 모듈의 패지 이름과 aar파일 예시이름 버전 1.0으로 로컬에 있는 경우 예입니다. 

dependencies{

  compile 'com.example.mylibray:myTest:1.0@aar'

}

.



.so(JNI)파일 참조하기

so 파일을 참조해야하는 경우도 있습니다. libs폴더 하위에 x86, armeabi-v7a 등 폴더를 만들고 그에맞는 .so파일을 복사하면 됩니다. (JNI 참고하세요)

아래와 같이 작성하시면 되겠습니다.

sourceSets는 안드로이드 앱을 gradle로 빌드하기 위해 사전에 약속된 폴더 구조입니다. 메인소스의 jniLibs.srcDirs 항목을 libs로 지정합니다.


android {

 sourceSets{

    main{

     jniLibs.srcDirs = ['libs']

    }

  }


}


그 외의 경우.

Gradle은 외부라이브러리르 가져올때, 그라이브러리가 내부적으로 참조하는 다른라이브러리도 함께 땡겨옵니다. 이럴 때exclude group 으로 특정 참조그룹을 제외시킬 수 도 있습니다. 현재 프로젝트와 의도지않게 가져오는 라이브러리의 버전 충돌문제로 사용하는 편입니다.


compile('xxx.xxx.xx:2.2.2'){

 exclude group: 'com.xxx'

}


transitive 옵션을 줄 수 있습니다. aar을 붙여 참조하게되면 transitive 옵션은 false 로 변경됩니다. (aar의 경우 그런것 같습니다.)

명시적으로 true값을 준다면, aar 파일이 필요로 하는 라이브러리를 추가로 땡겨 오게 됩니다.


compile('xxx.xxx.xx:2.2.2'){

transitive = true or false

}



'개발 Support > Gradle' 카테고리의 다른 글

안드로이드 Gradle Test  (0) 2017.07.12
안드로이드 Gradle 멀티 프로젝트 사용  (0) 2017.07.10
Gradle Task와 생명주기  (0) 2017.07.10
Android studio Gradle 프로젝트 생성  (0) 2017.07.09
Gradle 개요  (0) 2017.07.08

시작하기 앞서

 Gradle의 기본단위는 Task 입니다. Android Studio는 쉽게 빌드하는 것처럼보이지만, 내부적으로 모두 Gradle Task가 동작합니다. Gradle Task와 Task의 생명주기에 관해 알아보도록 하겠습니다.


프로젝트 빌드하고 실행

 안드로이드 스튜디오에서 기본적으로 빌드하려면 build -> make project 하면 됩니다. 

안드로이드 스튜디오 오른쪽화면을 보면 Gradle Projects가 있습니다. Sync버튼을 누르면 Gradle 관점에서 모듈별 Task목록들을 보실 수 있습니다.

저는 GradeTest라는 프로젝트를 생성했었습니다. 생성할때 처음 기본 모듈이름은 app이라고 안드로이드 스튜디오에서 기본적으로 설정됩니다.

모듈은 콜론으로 구분합니다. 그래서 :app으로 되어있는것을 보실 수 있습니다. 


app 모듈의 build그룹을 열어서, assembleDebug를 더블클릭하여 실행해봅시다. 

앞으로는 프로젝트를 직접 빌드하기보다는 Module 단위로 빌드를 진행합니다. 멀티프로젝트에서는 각 Module이 빌드의 주체가 됩니다.

빌드가 성공된것읗 확인할 수 있습니다.

또한, Project이름 > app > build > outputs > apk 폴더에 빌드된 apk 파일을 확인하실 수 있습니다.

 

 




Gradle Task 개념

 Module의 개수가 늘어나면 안드로이드 Gradle 플러그인에서 제공하는 Task 외 새로운 Task 를 추가하여 활용하게 됩니다. Task의 개념을 알고있으면 유용하게 써먹을 수 있게 됩니다.


Task 에서 Log 출력

 sayHi라는 Task를 추가해보겠습니다. 또한 Hello MyGradle 문구를 출력하는 Task를 만들도록하겠습니다. 문자열 출력할때는  ''를 사용해도되고 ""를 사용해도됩니다. "" 같은경우는 내부변수를 문자열에서 참조할때 사용하기도 합니다.



안드로이드 스튜디오 프로젝트에서, app module(프로젝트 모듈말고!)의 build.gradle을 열고 task를 추가해봅시다.


task sayHi << {

   println 'hello MyGradle'

}


그리고 오른쪽 gradle project창에서 싱크버튼을 누릅니다. Other 그룹을 펼쳐보면 sayHi Task가 생성된것을 확인할 수 있습니다. 거기서 더블클릭하면 sayHi Task 가 실행됩니다. 아래와 같이 app:sayHi task가 실행되면서, hello MyGradle이 출력되는것을 확인할 수 있습니다.


참고로 위에서 작성한코드는 아래코드와 같은 코드입니다. doLast부분이 들어가는것을 주의깊게 보세요. 뒤에서 설명합니다.

task hello {
    doLast {
        println 'Hello world!'
    }
}



Task 그룹 지정

Gradle Task는 그룹을 가질 수 있습니다. 앞서만들었던 sayHi를 help 그룹에 편입시켜 보겠습니다.

task sayHi(group: "help")<< {
println 'hello MyGradle'
}

sayHi는 help그룹에 어울리않으니 다른 그룹을 생성해서 지정해보겠습니다. insa 그룹을 생성하고 지정했습니다.

def insa = 'insa'
task sayHi(group: insa)<< {
println 'hello MyGradle'
}


sayHi Task가 insa 그룹에 편입된것을 확인하실 수 있습니다.


Task 설명 지정하기

Task가 어떤일을 하는 지 설명을 해야할 필요가 있겠죠? description을 넣고 설명을 달았습니다.

def insa = 'insa'
task sayHi(group: insa, description: "my insa is hello")<< {
println 'hello MyGradle'
}

Gradle 내장태스크 tasks를 실행하면 다음과 같이 설명글을 볼 수 있습니다.

insa 그룹의 tasks들이 출력되고, sayHi Task의 설명을 확인하실 수 있습니다.


Insa tasks

----------

sayHi - my insa is hello

.



Task에 dependency 지정하기

 어떤 task를 내 task 보다 먼저 실행되도록하려면 dependsOn 이라는 속성을 지정하면 됩니다.

meetPerson Task를 먼저 실행하고 sayHi Task를 진행하도록 하겠습니다.

def insa = 'insa'
task sayHi(group: insa, description: "my insa is hello",
dependsOn: 'meetPerson')<< {
println 'hello MyGradle'
}

task meetPerson(group: insa) << {
println "I met person"
}

동기화를 해보고 sayHi를 실행해보겠습니다.

meetPerson Task 실행되고, sayHi Task가 실행되는것을 확인하실 수 있습니다.



Gradle 생명주기

Gradle 생명주기는 초기화 단계, 설정 단계, 실행 단계로 구분됩니다.



초기화단계

 프로젝트 build.gradle에 해당하는 Project Instance를 생성합니다. 앞서 봤던 buildscript, allprojects 블록등도 포함됩니다.



설정단계

 Project객체의 detail한 값을 설정합니다. 하위 프로젝트에 공통으로 적용되는 내용은 앞선 포스팅에서 설명했던 allprojects() 을 통해 전달됩니다. 사용자 정의 task의 경우 doFirst()에 넣은 내용이 이때 실행됩니다.



실행단계

설정 단계를 마치고, 각 Task는 이제 실행되기만 하면됩니다. 사용자 정의 Task 의 경우 doLast() 또는 <<에 넣은 내용이 이때 실행되게 됩니다. 


만약 sayHi task에서 doFirst()와 doLast()를 각각 새로 정의했다면 doFirst()에 넣은 내용은 설정단계에서, doLast()에 넣은 내용은 실행단계에서 실행됩니다.

def insa = 'insa'
task sayHi(group: insa) {
doFirst{
println 'Look at me'
}
doLast{
println 'hello MyGradle'
}

}


:app:sayHi

Look at me

hello MyGradle


BUILD SUCCESSFUL



Look at me가 실행되고 Hello MyGradle이 출력되는것을 확인하실 수 있습니다.
참고로 위의 코드에 dependsOn: 'meetPerson' 을 넣으면, 

meetPerson Task가 실행되고, Look at me 다음 hellot MyGradle이 실행됩니다. 






시작하기 앞서

드디어 첫 gradle 프로젝트 생성 실습입니다. 차근차근 진행 해봅시다.


- Hello World 안드로이드 스튜디오 프로젝트 생성

안드로이드 스튜디오를 실행합니다. 그리고 File -> new -> New Project를 누릅니다. 음 API24 정도로 선택합니다. Activity 는 Blank Activity로 선택하겠습니다. 저흰 액티비티가 중요한게 아니니깐요.

 그리고 프로젝트 표시는 Android View로 하도록 하겠습니다. 왜냐하면 안드로이드 앱의 Gradle 스크립트를 잘표현해주기 때문입니다.



- Gradle 구성요소 소개

 

(1) app모듈

 안드로이드 스튜디오는 멀티프로젝트를 생성하게 됩니다. Gradle 프로젝트 하위에는 적어도 1개 이상의 모듈을 포합합니다. 최초 생성되는 모듈 이름은 app입니다. 새로운 모듈을 추가할때는 File -> New -> New Module 을 선택하면됩니다.


(2) manifest 폴더

AndroidManifest.xml 파일을 표시합니다. 앱이름과 권한 과 같은 프로젝트 메타정보를 담고 있습니다. 모듈별로 AndroidManifest.xml 파일을 포함하게 됩니다.


(3) java 폴더

소스코드와 테스트 코드가 있습니다.


(4) Gradle Scripts

안드로이드 스튜디오에서의 gradle sciprt을 포함하고있습니다.



- 프로젝트 build.gradle (여기선 Project: HelloWorld)

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir

} 

 직접 까서 보겠습니다.

프로젝트 build gradle은 다수의 모듈이 존재할떄 전체 모듈에 공통적으로 적용하는 부분을 기술하는 부분입니다.


크게 두부분으로 구성되어있습니다. 

buildscirpt은 빌드 스크립트를 구동하는 부분입니다. 외부저장소와 의존성 부분을 지정합니다. 외부저장소로 jcenter, mavenCentral 이 있습니다.

요즘은 jcenter를 많이 사용한다고 합니다. 또한 dependencies(의존성부분) 에는 안드로이드 gradle의 플로그인 버전을 기술합니다.


그외에는 전체 프로젝트 공통으로 사용할수 있는 task 를 정의합니다. 기본적으로 clean 태스크가 추가되며, 단순히 build 폴저를 제거하는 역할을 하고있습니다. app과 같은 하위 Module의 build 폴더도 모두 제거한답니다. 모듈이 다수이면 다수모듈의 build 폴더가 제거되겠지요?



- 모듈 build.gradle (여기선 Module:app)

apply plugin: 'com.android.application'

android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.example.pjh.helloworld"
minSdkVersion 24
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'

} 

 크게 네 부분으로 구분됩니다. 


첫번째는 모듈의 plugin 부분입니다.

안드로이드 App module 은 com.android.application을 지정합니다.

안드로이드 library module은 com.android.library를 지정합니다.

동시에 플러그인을 2개 지정할수는 당연히 없습니다.


두번째는 android로 AndroidManifest.xml을 재설정 한다고 생각하시면 됩니다.

gradle에서 설정한게 manifest보다 우선시 됩니다. 


세번째는 buildTypes에는 빌드 타입에 따라 다른 동작을 지정할 수 있습니다.

빌드타입에 따라 다른 동작을 지정할 수 있습니다. debug와 release가 있습니다. debug는 개발단계에서 사용되며, release는 마켓이나 외부에 배포할때 사용합니다. 


네번째는 의존성부분(dependencies) 입니다.

libs폴더에있는 모든 jar파일 의존성에 추가합니다.

또한 compile은 module을 빌드 할 때 포함하는 외부라이브러리입니다. 로컬에 존재하지 않는 경우, 앞서 지정한 저장소였던 jcenter(프로젝트 gradle에서) appcompat 지원 라이브러리를 다운로드합니다.




Gradle은 저장소위치와 라이브러리 버전등을 지정하면 빌드 시 자동으로 해당 버전또는 최신버전을 포함하므로 개발자는 신경 쓰지 않아도 되는 엄청난 강점을 가지고 있습니다. 계속해서 Gradle 포스팅을 하도록 하겠습니다.


'개발 Support > Gradle' 카테고리의 다른 글

안드로이드 Gradle Test  (0) 2017.07.12
안드로이드 Gradle 멀티 프로젝트 사용  (0) 2017.07.10
Android Gradle 외부 라이브러리 추가  (0) 2017.07.10
Gradle Task와 생명주기  (0) 2017.07.10
Gradle 개요  (0) 2017.07.08

Gradle 개요


Gradle 블로그를 포스팅하기 앞서 왜 gradle에 관한 블로그를 포스팅하는지 이유를 말씀드리고싶네요. 현업에서 일하고 있는데, gradle을 항상 남이 짜놓은걸 그대로 받아서 빌드돌려서 개발만 하다가, 이제는 제대로 스터디해서 내기호에 맞게 수정하고싶은 마음이 생겼습니다. 또한, gradle이 강력한 빌드 툴이라는 말을 계속 들어서 언젠가는 해야겠다는 마음먹었는데 드디어 행동에 옮기게 되었습니다. 부디 저와 같이 스터디하여 gradle을 master하도록 합시다.


Gradle OverView



Gradle은 Gradle 사에서 만든 범용 빌드 도구중에 하나입니다. 안드로이드에서 빌드 뿐만 아니라, java, c/c++ 등의 모든 범용 언어를 지원합니다. 그러므로 엄청 강력한 툴이지요. 그래서 Gradle을 한번 배워두면 다른언어로 개발하더라도 빌드 스크립트를 처음부터 다시 작성할 필요없이 재사용하실 수 있습니다. 누차 강조하지만 꼭 gradle을 배워보도록 합시다.


다음은 gradle의 주요 특징 4가지 입니다.


1. Polyglot Build

Gradle은 각 언어를 플러그인으로 구별합니다. java는 java, java 웹 프로젝트는 war, 안드로이드 앱은 com.android.application 플로그인을 사용하면 됩니다.


2. 도구통합

gradle은 이클립스, 안드로이드 스튜디오 와 같은 IDE에서 정말 편리하게 사용할 수 있도록 창을 제공하고있습니다. 또한 젠킨스와 함께 활용할 수 도있습니다. 소스코드가 git에 업로드되면 서버에서 CheckStyle, FindBugs 등의 플러그인을 활용하여 소스코드가 잠재적으로 가진 문제를 검출하여 개발자에게 통보하거나 위험한 코 드를 merge할 수 없도록 강제적으로 할 수 있습니다.


3. 외부 라이브러리 관리 자동화

Gradle의 또다른 장점중 하나는 개발자가 더는 외부라이브러리를 관리하지 않아도 된다는 점입니다. 개인적으로 이점이 가장 마음에 듭니다. 이클립스에서 개발했던 과거의 경우에는 libs 폴더에 원하는 외부라이브러리 파일을 직접 복사하였지만, Gradle 에서는 단순히 외부 저장소 위치와 라이브러리의 그룹, 이름, 버전 등을 지정해주면 알아서 다운로드하고 빌드에 포함시키게 됩니다. 이얼마나 편하고 좋습니까.


4. 고성능 빌드

Gradle은 점진적 빌드, 빌드캐싱, 병렬 빌드 기능을 지원하는 고성능 빌드를 지향합니다. 하지만 실제로 우니도우 환경에서 안드로이드 앱을 빌드해보면 gradle 메모리 사용량이 많고 빌드시 CPU 점유율이 엄청 높게 잡힙니다. 실무에서 권장하는 사양은 메모리 8GB와 SSD 장착입니다. 메모리 4GB에서 모듈의 수가 늘어나면 Out of memery 현상이 발생합니다. 또한 heap이 부족하다고 난리치기도 한답니다.(진짜 경험)







안드로이드 스튜디오에서 Gradle의 특징을 살펴보겠습니다.



1. 멀티 프로젝트 구조

안드로이드 스튜디오에서 프로젝트를 생성하면 멀티 프로젝트로 생성됩니다. app이라는 폴더가 있는데 이를 Gradle에서는 모듈이라고 부릅니다. gradle에서는 app 모듈뿐만 아니라 새로운 모듈을 추가하여 모듈별로 src 폴더를 포함하게 됩니다.


2. src폴더 구조가 다름

androidTest, main, test 폴더를 확인하실 수 있습니다. Test 폴더는 Local Unit Test 를 지원합니다.


3. libs 폴더

이클립스 libs 폴더에는 빌드하는데 필요한 외부라이브러리를 직접 포함시켜야 했습니다. 하지만 gradle에서는 의존성 관리를 gradle이 담당하므로 libs 폴더를 사용하지 않아도됩니다. 필요한 스크립트 파일에서 외부라이브러리의 저장소와 버전등을 지정하면 빌드할 때 알아서 해당 버전을 다운로드하여 포함합니다. 또한, +옵션등을 적용하면 최신버전을 자동으로 다운로드 할 수 있습니다.


4. bin 폴더

gradle에서 빌드를하면 build/output/apk 폴더에 apk 파일이 위치하게됩니다. 혹은 AAR파일도 있게 됩니다.



정독 해주셔서 감사합니다.

+ Recent posts