모두의 kotlin

모두의 Kotlin

Kotlin에 대한 간단한 소개부터 Kotlin을 적용한 MDM(Mobile Device Management) 개발에 대해 간략히 소개드리고자 합니다.

[TOC]


1. Kotlin 이란?

kotlin_logo

Kotlin은 JetBrain 사에서 2011년 7월에 발표한 프로그래밍 언어입니다. 현재 안드로이드에서 Java와 함께 공식 언어로 지정되어 있는 언어이기도 합니다. JVM 상에서 동작하여 Java와 마찬가지로 Windows, Mac, Ubuntu 등 다양한 플랫폼에서 사용이 가능합니다. 또 컴파일 시 Java와 마찬가지로 .class 파일로 만들어지기 때문에 기존 Java 코드와 완벽하게 호환이 가능합니다.

2. Kotlin의 특징

kotlin_adavantages

[Image. JetBrain Kotlin 소개]

1) 변수 선언 시 타입이 필요하지 않다

String name = "Amy";
int age = 20;
boolean isMen = false;

[code1. Java 변수 선언]

C, C++, Java 변수 선언 시 일반적으로 선언할 변수의 형식을 먼저 선언합니다. 변수에 들어갈 값을 형태에 따라 자료형을 지정해줘야 하는데 컴파일 시 잘못된 값이 들어갈 경우 컴파일 에러가 발생합니다.

String name = 1; // Compile Error
String name = "Amy"; //Compile Success

[code2. Java 자료형에 따른 컴파일 성공 여부]

이런 언어들은 컴파일 시 타입에 대한 속도를 결정하기 때문에 속도가 증가하고 타입 에러로 인한 문제를 초기에 발견할 수 있다는 장점이 있습니다.

var name = "Amy"
var age = 20
val isMen = false
val gender:String = if(isMen) "Men" else "Women"

[code3. Kotlin 변수 선언]

반면, Kotlin은 변수 선언 시 별도의 자료 선언이 필요하지 않습니다. 타입 추론(Type Inference)을 이용하여 변수의 타입을 추론합니다. 값 할당 시 변수의 타입이 결정이 되기 때문에 변수 선언 때마다 타입을 써줄 필요가 없기 때문에 프로그래머가 빠른 코드 작성이 가능합니다.

그렇다고 Kotlin 변수 선언 시 타입을 선언할 수 없는 것은 아닙니다. code3의 gender 변수를 확인하면 알 수 있듯이 변수명:변수타입으로 타입을 지정하여 프로그램 구성 역시 가능합니다.

Kotlin은 변수 선언 시 var/ val 키워드를 이용하여 변수 선언을 진행합니다. var은 variable의 축약어로 읽기/쓰기가 가능한 변수입니다. val은 valuable의 축약어로 읽기만 가능한 변수입니다. Java의 final에 해당한다고 볼 수 있습니다.

2) 변수의 자동적인 Null-Check

프로그래밍을 하다보면 변수에 Null 값이 들어가는 경우가 종종 발생합니다. Java의 경우 모든 변수에 Null 값이 들어갈 수 있습니다. Null 값이 들어가지 않은 상태에서 프로그래밍 로직을 타기 위해서는 if문을 이용하여 처리하거나 Annotation을 이용하여 해당 변수에 Null 값이 들어가지 않는다는 것을 명시합니다.

if(activity != null){
    doSomething();
} 

[code4. if문을 이용한 Null 처리]

@NonNull
String name;

[code5. Annotation을 이용한 Null 처리]

Kotlin에서는 변수 선언 때부터 Null 값 여부를 지정할 수 있습니다. Non-Null/Nullable 타입이 존재합니다. Non-Null은 Null 값을 가질 수 없는 변수를 의미하고 Nullable은 Null 값을 가질 수 있는 변수를 의미합니다.

Kotlin에서 사용되는 모든 변수 타입은 기본적으로 Non-Null입니다. 변수에 Null 값을 넣게 되면 컴파일 시 에러가 발생하게 됩니다. 변수에 Null을 적용하기 위해서는 변수 선언 시 변수 타입 뒤에 ?를 붙여 해당 자료형이 Nullable한 변수라는 것을 명시해야 합니다.

var name1:String = null // Error!
var name2:String? = null // Success!

[code6. 변수 Null Check]

3) 함수형 프로그래밍

함수형 프로그래밍 소개에 앞서 Kotlin의 함수 선언에 대해 소개해 드리고자 합니다. 함수 선언시 fun 키워드를 이용합니다. 매개변수를 선언할 시에는 매개변수의 이름 뿐만 아니라 타입 역시 명시해야 합니다. 함수가 결과 값을 리턴하는 경우에는 리턴 타입 역시 선언해줘야 합니다.

String getName() {
    return "Amy";
}

[code7. Java 함수 선언]

fun printName() {
    println("Amy")
}

[code8. Kotlin 단순 함수 선언]

fun setName(name:String){
    this.name = name
}

[code9. Kotlin 매개 변수가 포함된 함수 선언]

fun getName() : String{
    return "Amy"
}

[code10. Kotlin 리턴이 포함된 함수 선언]

Kotlin은 함수형 프로그래밍입니다. Python과 마찬가지로 Kotlin은 함수가 일급객체(First-Class Object)입니다. 일급객체는 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 의미합니다. Kotlin에서는 String, Boolean, Integer 등과 같이 함수가 변수에 할당될 수 있고 다른 함수의 결과 값으로 리턴될 수 있습니다. funtion 타입으로 리턴되는 것은 괄호로 묶은 변수 타입 리스트와 화살표를 통해 알아볼 수 있습니다.

fun safeDivide(numerator: Int, denominator: Int) : Double {
    if (denominator == 0) 
    	return 0.0 
    else 
    	return numerator.toDouble() / denominator
}

[code11. ]

val f:(Int, Int) -> Double = ::safeDivide

[code12. 함수를 변수에 할당]

Kotlin에 대한 더 자세한 내용은 공식 홈페이지를 참조해주시길 바랍니다.

3. MDM Agent에 Kotlin 적용

1) MDM 이란?

Mobile Device Management의 준말로 기업형 모바일 단말 관리 서비스를 의미합니다.

MDM은 기업 자산인 모바일 단말기를 위해 원격 기기 잠금 및 해제, 앱 삭제, 데이터 관리 등 다양한 기능을 제공합니다.

MDM을 도입하게 되면 모바일 디바이스를 통한 보안 누출을 방지 및 디바이스 분실 시 정보 유출을 방지할 것이라 보고 있습니다.

2) Kotlin을 이용한 MDM Agent 개발

class LogoutEvent{
    private String userID;
    private boolean isLogout;
    private int isFirst;
    ...
    public void setUserID(String userID) { this.userID = userID; }
    public String getUserID() { return  userID; }
    ...
}

[code13. Java로 작성된 데이터 클래스]

Java로 데이터 클래스를 작성을 하였을 때 필드의 정의된 값 변경 조회를 위하여 각 변수에 대해 getter/setter를 생성해주었습니다. 각 변수마다 메소드를 생성해주기 때문에 불필요하게 코드의 길이가 길어지고 데이터 클래스를 한 눈에 파악하기 어려웠습니다.

@Entity(tableName = "logout")
data class LogoutEvent (@PrimaryKey val userID:String, var isLogout:Boolean, var isFirst:Int = 0)

[code14. Kotlin으로 작성된 데이터 클래스]

다음의 코드는 실제 MDM Agent 구현 때 사용된 LogoutEvent 클래스입니다. code 13의 Java 코드와 달리 별도의 getter/setter 메소드를 작성하지 않았습니다. Kotlin에서는 정의된 필드에 대해서 접근자 메소드를 자동으로 생성해줍니다. 위에서 val로 선언된 userID는 getter, var로 선언된 isLogout, isFirst는 getter, setter가 가능한 필드가 됩니다.

Kotlin에서는 필드의 이름을 직접적으로 접근하더라도 자동으로 getter/setter 메소드 호출로 변환하여 줍니다. Java를 이용했다면 setIsLogout(), getIsFirst() 등의 메소드를 직접 호출했어야 합니다. 이처럼 Kotlin을 이용하여 데이터 클래스를 간단히 구현할 수 있었고, 별도의 getter/setter 메소드를 구현해 줄 필요가 없어 코드량이 확연히 줄어 클래스를 파악하기 더 용이하였습니다.

logoutEvent.isLogout = false
logoutEvent.isFirst = 1

[code15. Kotlin 필드 값 변경]

앞서 Kotlin의 특징을 소개할 때 Kotlin은 변수 자체적으로 Null 체크가 가능하다 소개드렸습니다. 기존 Java에서는 객체 내의 메소드 사용을 위해서는 객체의 null 여부를 먼저 확인해야했습니다. 보통 null 체크를 위해 if 문을 사용하게 되고 한번의 실행을 위해 코드가 길어지는 상황이 발생합니다.

Kotlin에서 Nullable 변수에 접근할 때 2가지 방식으로 확인할 수 있습니다. Java와 마찬가지로 if 문을 활용하는 방법과 Kotlin에서의 safe call인 ?.를 이용하는 방법입니다. 실행하고자 하는 변수의 값이 null 아닐 때만 호출할 수 있게 합니다. 아래의 예시 코드를 보면 알 수 있다 싶이 context 변수의 값이 null이 아니면 getSystemService 메소드를 실행시키고 context 변수 값이 null일 경우 메소드가 실행이 안되고 null이 리턴됩니다.

context?.getSystemService(Context.AUDIO_SERVICE)

[code16. safe call]

Kotlin은 어떠한 Wrapping 과정이 필요 없이 Java와 완벽히 호환됩니다.

swift_header_bridge

iOS에서도 Objective-C 언어를 사용하다 새롭게 Swift를 도입하였습니다. 하지만 Swift와 Objective-C는 완벽히 호환되지 않습니다. 대표적으로 Swift는 헤더 파일이 없습니다. 하지만 Objective-C 같은 경우는 처음 생성될 때부터 헤더 파일을 별도로 작성합니다. 이 때문에 Swift로 작성된 코드에서 Objectvie-C로 작성된 코드를 접근하기 위해서는 별도의 Bridge Header라는 파일을 작성할 필요가 있습니다.

Kotlin에서도 Java 파일을 import를 할 때 별도의 작업이 필요할까요? 답은 아닙니다. 간단한 예시를 통해 보여드리겠습니다. 다음 코드는 Kotlin으로 작성된 BaseActivity 입니다. 해당 클래스는 AppCompatActivity를 상속 받아 구현하였습니다. AppCompatActivity의 코드를 확인해보면 해당 코드는 Java로 작성되었다는 것을 확인할 수 있습니다. Java로 작성된 라이브러리, 클래스들을 자유롭게 사용할 수 있어 기존의 사용하던 유용한 라이브러리의 유지가 가능하고 라이브러리 선택의 폭이 넓어져 유용하였습니다.

open class BaseActivity : AppCompatActivity() {
    private val backPressHandler: BackPressHandler = BackPressHandler(this)
    override fun onBackPressed() {
        backPressHandler.onBackPressed()
    }
}

[code17. BaseActivity.kt]

4. 개발후기

Lemp 파트에서는 MDM Agent를 개발하면서 처음으로 Kotlin을 도입해보았습니다. Kotlin이라는 생소한 언어였지만 낮은 러닝 커브 덕분에 빠른 시간 안에 적응할 수 있었습니다.

또한, Kotlin이 기본적으로 제공하는 변수 추론, 확장 함수, 함수형 프로그래밍 등은 개발자가 코드를 더 효율적으로 작성할 수 있게 도와줘 일의 생산성을 올려줍니다.

개인적으로는 Kotlin에서 제공해주는 요소를 이용하여 코드를 작성하다보니 코드가 많이 간결하게 변했습니다. 코드가 간결하게 변해 읽기가 편했고 파일의 작성요지를 더 쉽게 파악하기 쉽다고 느꼈습니다.

현재 코틀린은 안드로이드에서 가장 많이 사용되고 있긴 하지만 다양한 분야에서 많이 활용될 수 있습니다. 현재는 코틀린의 웹서버 프레임워크인 ktor가 주목을 받고 있는 상태여서 관심 있으신 분들은 한 번 사이드 프로젝트로 사용해 보셨으면 좋겠습니다.


References