Kotlin에서 Swing을 이용한 Desktop GUI App 만들기

|

간단한 GUI Application 구현하기

package com.snowdeer

import java.awt.BorderLayout
import java.awt.Dimension
import java.lang.Thread.sleep
import javax.swing.JFrame
import javax.swing.JScrollPane
import javax.swing.JTextArea

fun main(args: Array<String>) {
    val textArea = JTextArea()
    textArea.text = "Hello, SnowDeer"
    val scrollPane = JScrollPane(textArea)

    val frame = JFrame("Hello, SnowDeer")
    frame.contentPane.add(scrollPane, BorderLayout.CENTER)
    frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
    frame.size = Dimension(600, 400)
    frame.setLocationRelativeTo(null)
    frame.isVisible = true
}

Kotlin에서 실행가능한 jar 생성하기

|

Executable jar 생성하기

터미널에서 java -jar 명령어를 이용해서 간단하게 실행할 수 있는 jar 파일을 생성하는 예제입니다.


Main.kt

여기서는 com.snowdeer라는 패키지를 만들고 그 안에 Main.kt 파일을 생성했습니다.

package com.snowdeer

import java.lang.Thread.sleep

fun main(args: Array<String>) {
    println("Hello SnowDeer.")

    val t = Thread() {
        while (true) {
            println("Thread is Running ...")
            sleep(2000)
        }
    }

    t.start()
}


build.gradle

buildscript {
    ext.kotlin_version = '1.3.61'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: 'java'
apply plugin: 'kotlin'

group 'com.snowdeer'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

jar {
    manifest {
        attributes 'Main-Class': 'com.snowdeer.MainKt'
    }
    archiveName 'helloKotlin.jar'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

위에서 dependencies 구문 안에 compile 키워드를 확인해야 합니다. 안드로이드 스튜디오에서 사용하던 gradle에서는 compile 명령어가 deprecated되어서 impelementation 키워드를 대신 사용하라고 되어 있지만, 사용하는 gradle 버전에 따라서는 compile만 사용해야 정상 동작되는 경우가 있습니다.


빌드 및 실행

이후 터미널에서 다음 명령어를 이용해서 빌드 및 실행을 해봅니다.

$ ./gradlew clean build

$ java -jar build/libs/helloKotlin.jar


application 플러그인 추가

만약 gradle 명령어를 이용해서 실행을 해보고 싶으면 다음과 같이 apply plugin: 'application'mainClassName = "com.snowdeer.MainKt"를 추가해줍니다.

buildscript {
    ext.kotlin_version = '1.3.61'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'application'

group 'com.snowdeer'
version '1.0-SNAPSHOT'

mainClassName = "com.snowdeer.MainKt"
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

jar {
    manifest {
        attributes 'Main-Class': 'com.snowdeer.MainKt'
    }
    archiveName 'helloKotlin.jar'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

그 이후 터미널에서

$ ./gradlew run

명령어를 이용해서 바로 실행도 가능합니다.


IntelliJ에서 설정하는 방법

intelliJ에서 IDE의 run 메뉴를 통해 실행하는 방법은 다음과 같습니다.

  • 메뉴의 Run > Run을 누른다음 Edit Configuration 선택
  • 왼쪽의 + 버튼을 눌러서 Gradle 항목 선택
  • Gradle project 항목 옆의 버튼을 눌러서 실행할 프로젝트 선택
  • Argumentsrun 명령어 추가

또는 다음과 같이 할 수도 있습니다.

  • 메뉴의 Run > Run을 누른다음 Edit Configuration 선택
  • 왼쪽의 + 버튼을 눌러서 Application 항목 선택
  • Main Class를 선택. 위 예제에서는 com.snowdeer.MainKt 선택
  • use classpath of module에서 실행할 모듈 선택

Circular View path error

|

만약

Circular view path [list]: would dispatch back to the current handler URL [/list] again.

와 같은 오류가 발생하면 build.gradle.kts 파일에

implementation("org.springframework.boot:spring-boot-starter-thymeleaf")

종속성 추가가 되어 있는 지를 체크해 볼 필요가 있습니다.

그리고 잊지 말고 gradle sync를 해줘야 반영이 됩니다.

Property 읽어오기

|

yaml 파일 생성

application.yaml

resources 디렉토리 아래에 application.yaml 파일을 생성하고 다음 내용을 입력합니다.

property:
  snowdeer:
    age: 40
    name: snowdeer
    address: Seoul


값 읽어오기

Controller 클래스에서 값을 바로 읽어들여도 상관없지만, 여기서는 Wrapping 클래스를 별도로 생성했습니다.

AppProperties.kt

import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component

@Component
class AppProperties {

    @Value("\${property.snowdeer.age}")
    lateinit var age: Integer

    @Value("\${property.snowdeer.name}")
    lateinit var name: String

    @Value("\${property.snowdeer.address}")
    lateinit var address: String

}


HelloController.kt

import com.snowdeer.sample.board.AppProperties
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class HelloController {

    @Autowired
    lateinit var appProperties: AppProperties

    @GetMapping
    fun hello(): String {
        return "Hello ${appProperties.name}"
    }
}

별도 Front-end 서버없이 구동하는 React Hello World

|

Hello.html

<head>
    <script src="https://fb.me/react-0.14.3.js"></script>
    <script src="https://fb.me/react-dom-0.14.3.js"></script>
</head>

<body>
<div id="content">ccc</div>
<script>
    var h1=React.createElement('h1', null, 'Hello, snowdeer')
    ReactDOM.render(
        h1,
        document.getElementById('content')
    )
</script>

</body>