Skip to content

Instantly share code, notes, and snippets.

@ducky-hong
Created March 24, 2016 17:29
Show Gist options
  • Save ducky-hong/ded795365b4d49d79b06 to your computer and use it in GitHub Desktop.
Save ducky-hong/ded795365b4d49d79b06 to your computer and use it in GitHub Desktop.
gradle guide to hw2

Gradle 기본

자바 프로젝트를 진행하면 일반적으로 다음 과정을 따릅니다.

  1. 자바 소스를 컴파일 하고
  2. 테스트 코드를 돌리고
  3. 컴파일 결과를 JAR로 묶어 배포 위 작업을 스크립트로 만들어서 할 수 있지만 컴파일 할 때 소스 위치 지정, 라이브러리 지정, 테스트 코드 실행, JAR로 어떤 것을 묶을건지 등등 꽤 귀찮습니다. 이런 귀찮은 작업을 빌드 툴이 대신 해줍니다. Gradle은 자바 진영에서 유명한 빌드 툴입니다.

스크립트를 만드는 대신 빌드 툴이 사용할 설정 파일을 만들어야합니다. 설정 파일에는 사용할 라이브러리(의존성이라고 많이 번역합니다), 소스 코드 위치, 플러그인, 플러그인 설정 등 빌드에 필요한 정보를 작성합니다.

다음 코드를 실행하면 일반적인 자바 프로젝트를 만들어줍니다.

$ mkdir example && cd example
$ gradle init --type=java-library

여러가지 파일이 생성됩니다.

  • build.gradle : 빌드 설정 파일입니다. 프로젝트 빌드에 필요한 정보가 있습니다.
  • gradlew, gradlew.bat : gradle wrapper 입니다. gradle wrapper 를 실행하면 해당 프로젝트에 맞는 gradle 버전을 다운 받고 실행합니다. gradle 명령어와 동일하지만, gradle 을 설치하지 않아도 사용할 수 있다는 장점이 있습니다.
  • settings.gradle : 프로젝트가 여러개일 경우 수정합니다. 지금은 지워도 됩니다.
  • src/main/java : 자바 코드 기본 위치입니다.
  • src/test/java : 테스트 코드 기본 위치입니다.

다음은 생성된 빌드 설정 파일입니다. 자바 프로젝트 빌드에 필요한 내용입니다.

// Gradle 은 범용 빌드 툴이기 때문에, 자바 프로젝트를 빌드하려면 'java' 플러그인이 필요합니다.
apply plugin: 'java'

// 라이브러리를 어디서 다운 받을건지 적어줍니다. 
// 왠만한 라이브러리는 중앙 저장소에 다 있습니다.
// jcenter 는 https://bintray.com/bintray/jcenter 입니다.
repositories {
    jcenter()
}

// 자바 프로젝트에서 사용할 라이브러리를 적어줍니다. repositories에서 설정한 저장소에서 라이브러리를 다운받습니다.
// 로컬에 다운 받은 jar 파일 위치를 적어줄 수 있는데, 버전 관리가 귀찮으므로 예시 처럼 적어줍니다.
// 형식은 <scope> '<groupId>:<artifactId>:<version>' 입니다.
dependencies {
    compile 'org.slf4j:slf4j-api:1.7.12' // compile scope 는 소스 컴파일, 클래스 실행 때 해당 라이브러리를 사용한다는 의미입니다.
    testCompile 'junit:junit:4.12' // testCompile scope 는 테스트 소스 컴파일, 테스트 클래스 실행 때 해당 라이브러리를 사용한다는 의미입니다. 메인 코드에서는 사용하지 않습니다.
}

compile task 를 실행하면 메인 코드, 테스트 코드를 컴파일 할 수 있습니다.

$ ./gradlew compile

test task 를 실행하면 테스트 코드를 실행합니다.

$ ./gradlew test

jar task 를 실행하면 컴파일 한 메인클래스를 묶은 jar 파일이 build/libs 폴더에 생성됩니다.

$ ./gradlew jar

위 과정을 하나로 묶은 것이 build task 입니다. 소스를 컴파일 하고 테스트를 실행하고 jar 파일을 만듭니다.

$ ./gradlew build

gradle task 실행 후 결과물은 주로 build 폴더에서 확인할 수 있습니다.

HW2 진행에 필요한 빌드 설정 파일

apply plugin: 'java' // 자바 프로젝트 빌드에 필요한 플러그인
apply plugin: 'application' // 서버, 클라이언트 실행 스크립트 만드는데 필요한 플러그인
apply plugin: 'com.google.protobuf' // protobuf 파일을 읽고 message class, grpc class 를 생성하는데 필요한 플러그인
apply plugin: 'idea' // intelliJ 사용에 필요한 플러그인

// application plugin 의 설정 값.
// false 로 하면 해당 프로젝트의 실행 스크립트를 생성하지 않는다.
// 실행 스크립트를 생성하려면 main class name 을 명시해야하는데,
// 이 프로젝트는 Server, Client 두개의 메인 클래스가 있어 각각 실행 스크립트를 따로 만들어야한다.
// 각 실행 스크립트를 만드는 task 는 밑에서 정의한다. (task primeTesterServer, task primeTesterClient)
startScripts.enabled = false

// 현재 빌드 설정 파일에 필요한 설정 값
buildscript {
  // build.gradle 에서 필요한 의존성(플러그인, 라이브러리)을 다운받을 저장소
  repositories {
    mavenCentral()
  }
  // build.gradle 에서 필요한 의존성 명시
  // protobuf-gradle-plugin 은 'com.google.protobuf' 플러그인을 의미한다.
  dependencies {
    classpath 'com.google.protobuf:protobuf-gradle-plugin:0.7.4'
  }
}

repositories {
  mavenCentral()
}
dependencies {
  compile 'io.grpc:grpc-all:0.13.2' // grpc 라이브러리 (따로 jar 파일을 다운 받을 필요가 없다.)
}

// 'com.google.protobuf' 플러그인 설정 값
protobuf {
  protoc {
  	// 어떤 버전의 protoc 를 다운 받을 것인지 적어둔다.
  	// 플랫폼에 맞게 미리 빌드된 바이너리를 다운로드 한다.
    artifact = "com.google.protobuf:protoc:3.0.0-beta-2"
  }
  // protoc 가 사용할 플러그인 정보
  plugins {
    grpc {
      // grpc-java plugin 을 사용.
      artifact = 'io.grpc:protoc-gen-grpc-java:0.13.2'
    }
  }
  protobuf {
  	// protoc 로 생성한 클래스의 위치
  	// 기본은 $buildDir/generated/source.
  	// intelliJ 에서 해당 폴더를 참조할 수 없는 문제가 있어 intelliJ 를 사용하는 경우에만 변경한다.
    generatedFilesBaseDir = "$projectDir/src/generated"
  }
  // 'com.google.protobuf' 는 generateProto task 를 생성하는데,
  // 해당 task 에서 grpc 플러그인을 사용한다고 명시.
  generateProtoTasks {
    all()*.plugins {
      grpc {}
    }
  }
}

// 'application' 플러그인에는 CreateStartScripts task 가 있다.
// 해당 task 를 상속하고 실행할 mainClassName 을 명시하면 실행 스크립트를 build/install/<projectName>/bin 에 만들어준다.
// 실행 스크립트 없이 Server를 실행하려면 다음과 같은 긴 명령을 쳐야한다.
// CLASSPATH=$APP_HOME/lib/20091613.jar:$APP_HOME/lib/grpc-all-0.13.2.jar:$APP_HOME/lib/commons-cli-1.3.1.jar:$APP_HOME/lib/grpc-netty-0.13.2.jar:$APP_HOME/lib/grpc-auth-0.13.2.jar:$APP_HOME/lib/grpc-protobuf-nano-0.13.2.jar:$APP_HOME/lib/grpc-core-0.13.2.jar:$APP_HOME/lib/grpc-protobuf-0.13.2.jar:$APP_HOME/lib/grpc-okhttp-0.13.2.jar:$APP_HOME/lib/grpc-stub-0.13.2.jar:$APP_HOME/lib/netty-codec-http2-4.1.0.CR3.jar:$APP_HOME/lib/google-auth-library-oauth2-http-0.3.0.jar:$APP_HOME/lib/guava-18.0.jar:$APP_HOME/lib/protobuf-javanano-3.0.0-alpha-5.jar:$APP_HOME/lib/jsr305-3.0.0.jar:$APP_HOME/lib/protobuf-java-3.0.0-beta-2.jar:$APP_HOME/lib/okio-1.6.0.jar:$APP_HOME/lib/okhttp-2.5.0.jar:$APP_HOME/lib/netty-codec-http-4.1.0.CR3.jar:$APP_HOME/lib/netty-handler-4.1.0.CR3.jar:$APP_HOME/lib/google-auth-library-credentials-0.3.0.jar:$APP_HOME/lib/google-http-client-1.19.0.jar:$APP_HOME/lib/google-http-client-jackson2-1.19.0.jar:$APP_HOME/lib/netty-codec-4.1.0.CR3.jar:$APP_HOME/lib/netty-buffer-4.1.0.CR3.jar:$APP_HOME/lib/netty-transport-4.1.0.CR3.jar:$APP_HOME/lib/httpclient-4.0.1.jar:$APP_HOME/lib/jackson-core-2.1.3.jar:$APP_HOME/lib/netty-common-4.1.0.CR3.jar:$APP_HOME/lib/netty-resolver-4.1.0.CR3.jar:$APP_HOME/lib/httpcore-4.0.1.jar:$APP_HOME/lib/commons-logging-1.1.1.jar:$APP_HOME/lib/commons-codec-1.3.jar
// java -classpath "$CLASSPATH" edu.kaist.cs492.PrimeTesterServer
task primeTesterServer(type: CreateStartScripts) {
  mainClassName = "edu.kaist.cs492.PrimeTesterServer" // 실행할 메인 클래스 이름
  applicationName = "prime-tester-server"
  outputDir = new File(project.buildDir, 'tmp')
  classpath = jar.outputs.files + project.configurations.runtime
}

// Client 실행 스크립트 생성 task
task primeTesterClient(type: CreateStartScripts) {
  mainClassName = "edu.kaist.cs492.PrimeTesterClient"
  applicationName = "prime-tester-client"
  outputDir = new File(project.buildDir, 'tmp')
  classpath = jar.outputs.files + project.configurations.runtime
}

// 생성된 실행 스크립트를 실행 가능한 퍼미션으로 변경
applicationDistribution.into("bin") {
  from(primeTesterServer)
  from(primeTesterClient)
  fileMode = 0755
}

// intelliJ 에서 위 protobuf 설정에서 변경한 generatedFilesBaseDir 폴더를 참조하도록 설정.
idea {
  module {
    sourceDirs += file("${projectDir}/src/generated/main/grpc")
    sourceDirs += file("${projectDir}/src/generated/main/java")
  }
}

com.google.protobuf 플러그인이 어떻게 proto 파일을 읽어 클래스를 생성하는지는 --info 옵션으로 확인할 수 있습니다.

$ ./gradlew generateProto --info
...
[/Users/user/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protoc/3.0.0-beta-2/19ea442c926d24b3651428549894e4565ee79922/protoc-3.0.0-beta-2-osx-x86_64.exe, -I/Users/user/workspace/kaist/admin/20091613/src/main/proto, -I/Users/user/workspace/kaist/admin/20091613/build/extracted-protos/main, -I/Users/user/workspace/kaist/admin/20091613/build/extracted-include-protos/main, --java_out=/Users/user/workspace/kaist/admin/20091613/src/generated/main/java, --grpc_out=/Users/user/workspace/kaist/admin/20091613/src/generated/main/grpc, --plugin=protoc-gen-grpc=/Users/user/.gradle/caches/modules-2/files-2.1/io.grpc/protoc-gen-grpc-java/0.13.2/d345714a2473bf47c9fdbb1af07a12432e84410f/protoc-gen-grpc-java-0.13.2-osx-x86_64.exe, /Users/user/workspace/kaist/admin/20091613/src/main/proto/prime_tester.proto]
...

참조

Gradle 관련해서 훌륭한 문서가 많습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment