요즘 오랜만에 안드로이드를 다시 보고 있다. 한 때 스타트업을 하면서 빡씨게 개발하곤 했는데, 커리어가 바뀌면서 자연스레 잊혀져갔다. 최근에는 주로 서버 개발과 데이터 엔지니어링 위주로만 하다가 문득 다시 한번 안드로이드 앱을 개발해보고 싶은 마음이 들었다.
2014년, 스타트업 했을 당시 이클립스로 시작해서 안드로이드 스튜디오 2.0 으로 개발했었는데.. 다시 보니 꽤나 많은 것들이 달라져 있었다. 안드로이드 버전이 올라갔고 문서화, 라이브러리 지원도 꽤 잘되어 있어서 놀랐다. 무엇보다도 개발 언어에 차이가 있었는데 당시 자바로만 개발이 가능했으므로 (크로스플랫폼 제외) 당연히 요즘도 자바로 개발하겠거니 했는데, Kotlin
이라는 언어가 나오고 안드로이드 진영에서 적극 권장하더라. 요즘은 대부분 Kotlin
으로 개발하는 추세이고 코드 예시도 Kotlin
이 먼저 나오는 상황이다.
새로운 언어를 배우고 적용하기까지 상당 시간이 걸릴듯하여 보류하고 있었는데 문득 언어 자체가 어떻게 생겨먹었는지 궁금하기도하고 공식 문서에도 잘 나와있길래 한번 훑어보았다. 기본적인 Syntax를 살펴보고 내가 알고있는 자바, 스칼라와 비교해서 어떤 차이가 있는지 보겠다.
1. 변수선언
val name: String = "Hello Kotlin"
var count: Int = 10
val
, var
키워드로 변수 선언 가능하다.
- val : immutable
- var : mutable
var
는 재할당이 가능하시만 val
는 불변이기 때문에 재할당 불가능함.
var count = 10
count = 20
키워드, 타입 정의 방식이 스칼라와 동일.
2. 타입추론
name 문자열 변수 선언 시 타입을 명시했지만 생략이 가능하다.
val name: String = "Hello Kotlin"
val name = "Hello Kotlin"
초기값을 할당할 때 Kotlin Compiler
가 값을 타입을 추론하기 때문. 이는 컴파일 타임에 정해지고 후에 변경되지 않는다. (정적 타입 언어)
val name = "Hello Kotlin"
// Compile error
name.inc()
name이 string
으로 추론되어 문자열 타입으로 지정되었는데 다른 메서드를 쓰면 당연히 컴파일 오류 (inc는 Int 메서드)
이 역시 스칼라와 동일하다.
3. Null Safe
Null 문제는 프로그래밍 할 때 항상 신경써야 한다. 반환된 값의 속성을 참조할 때 값 자체가 Null이면 NPE에 직면한다. 이를 피하기 위해 방어처리를 해야하는 수고로움이든다. 이를 해결하기 위해 언어차원에서 Kotlin
은 기본적으로 Null을 포함할 수 없다.
// Compile Error (Null 할당 불가)
val name: String = null
Nullable
유형으로 지정해야 Null 할당이 가능. 하지만 NPE를 야기할 수 있기 때문에 주의를 요한다. 스칼라와 자바8은 Optional
또는 Option
타입을 제공하여 Null에 대한 처리를 할 수 있도록 한다.
// Nullable 타입
val name: String? = null
Nullable 타입을 ?
로 지정하는 방식이 꽤나 간결하다.
4. 조건문
if
, else if
, else
키워드로 자바와 스칼라와 동일하다.
if (value % 2 == 0) {
println("value is even num")
} else {
println("value is odd num")
}
조건문은 변수에 바로 붙어서 사용 가능하다.
val level = if (result >= 90) {
"수"
} else if (result >= 80) {
"우"
} else if (result >= 70) {
"미"
} else {
"탈락"
}
하지만 위와 같이 조건문이 많아지는 경우 when
을 사용하는 것이 좋다.
val level = when {
result >= 90 -> "수"
result >= 80 -> "우"
result >= 70 -> "미"
else -> "탈락"
}
스칼라의 패턴매칭과 유사하다. 꽤 유용함.
5. 함수
하나 이상의 표현식을 함수로 정의할 때 fun
키워드를 사용한다.
fun getLevelString(result: Int): String {
val level = when {
result >= 90 -> "수"
result >= 80 -> "우"
result >= 70 -> "미"
else -> "탈락"
}
return level
}
파라메터 지정, 반환 타입을 명시해야하고 반환 할 때는 return
사용.
스칼라와 유사하나 return 키워드와 반환 타입을 반드시 써야하는 점에서 약간의 차이는 있다.
5.1. 함수 단순화
위와 같이 단순한 함수의 경우 =
로 바로 대입할 수 있다. 이 때는 return 키워드와 타입을 생략해도 된다.
fun getLevelString(result: Int): String = when {
result >= 90 -> "수"
result >= 80 -> "우"
result >= 70 -> "미"
else -> "탈락"
}
5.2. 고차 함수
함수를 값으로 사용 가능하니 고차 함수를 정의할 수 있다.
fun intParser(text: String, mapper: (String) -> Int): Int {
return mapper(text)
}
함수 파라메터 제외한 나머지 파라메터를 받은 경우는 익명함수를 전달 가능하다.
val parsedInt = intParser("32134", {input ->
input.toInt()
}
val parsedInt = intParser("32134") {input ->
input.toInt()
}
// 이미 정의된 `functions` 함수
val parsedInt = intParser("32134", functions)
6. 클래스
class
키워드로 일반적인 클래스와 같이 속성을 정의한다.
class Car {
val name: String = "Benz"
}
name은 val
키워드이므로 외부에서 할당할 수 없기 때문에 private variable
의 효과를 지닌다.
class Car(val name: String)
생성자를 직접 내부 함수로 쓰지않고 선언할 때 정의할 수 있다. 전반적으로 스칼라와 유사함.
6.1. 인스턴스
val car = Car("Benz")
new
키워드 없이 바로 인스턴스를 생성한다.
7. 호환성
코드는 JVM Byte Code
로 컴파일되기 때문에 JVM
위에서 동작한다. 자바와의 상호 호환성이 좋아서 직접 자바로된 코드를 호출 가능하며 같은 프로젝트 내에서 혼합하여 사용 가능하다.
Kotlin → Java
Java → Kotlin
기존에 자바로 된 레거시 코드가 있어도 쉽게 적용 가능한 것이 큰 장점이다. feature별로 하나씩 리팩토링하면서 도입해나가면 좋을 것 같다.
마무리
현업에서 스칼라로 주로 개발하기 때문에 스칼라와 비교를 하면서 실펴봤다. 30분간 훑어보니 스칼라와 꽤 유사해 보였고 이 때문인지 크게 이질감이 느껴지지는 않았다. 세부적인 차이점은 더 깊이 알아봐야겠지만 이정도 진입장벽이라면 그냥 코틀린을 공부하면서 하나씩 개발하는 편이 더 좋을 것 같다^^.
댓글