Google I/O 2017에서 Kotlin을 안드로이드 개발언어로 지원한다는 발표 이후, 날이 갈수록 Kotlin의 인기가 높아지는 것 같습니다.
실제로 현업에서도 Kotlin을 도입하기 시작하는 사례도 많이 볼 수 있고, 개발자 커뮤니티에서 Kotlin으로 개발하던 중 생기는 이슈에 대한 질문과 답이 날이 갈수록 늘어가고 있습니다.
또한, 안드로이드와 관련된 컨퍼런스등에서 발표 후 공유되는 자료들만 보아도, Kotlin을 기준으로 진행되는 사례도 많아지고 있고,
여러 스타트업에서 채용공고의 우대사항으로 Kotlin 사용 경험 우대라는 채용공고도 많아지고 있습니다.

당장 현업에서 모든 회사가 Java로 되어 있던 부분을 Kotlin으로 대체하지는 못하겠지만,
기존에 Objective-C로만 개발을 할 수 있었던 IOS의 어플리케이션도 지금은 Swift라는 언어를 이용하여 개발하는 사례가 많이 늘고 있듯이,
머지 않아 안드로이드도 Java의 대안 언어이자 또 다른 공식 언어인 Kotlin을 이용한 개발이 활발해지지 않을까 하는 생각도 듭니다.

아직까지 저희 개발팀에서는 기존의 Java언어를 이용하여 개발 및 유지보수를 진행하고 있지만,
필요에 따라 컨버팅하는 일이 발생하게 되거나, 혹은 제 개인적인 커리어 관리를 위해 요즘들어 저도 Kotlin 언어를 틈틈히 공부하고 있습니다.

이번 포스팅에서는 간단하게 새로운 Android Project를 생성하고, Kotlin으로 코드를 변환한 후,
기존의 Java와 Kotlin 코드를 비교해보는 글을 작성해볼까 합니다.

이미 많은 블로그들에서 Kotlin 언어에 대한 기본적인 언어의 소개와 장/단점들이 소개되고 있기에,
언어에 대한 설명과 장/단점은 언급하지 않고 바로 Android Studio에서 Kotlin을 시작하는 방법에 대해 작성해보려고 합니다.

Kotlin Plugin 설치

Android Studio 3.0부터는 IDE수준에서 Kotlin을 공식으로 지원하기로 발표되었기 떄문에,
해당부분은 Android Studio 2.x 버전을 사용 중이신 분들을 위해 작성 하였습니다.

Kotlin을 시작하기 위해선 우선 Kotlin Plugin 설치가 필요합니다.
Android Studio의 메뉴 중 Preferences > Plugins로 이동 한 후, kotlin을 검색하여 설치하기만 하면 끝입니다.
저는 이미 설치가 되어 있기에 Uninstall으로 표시되어 있으나, 설치가 필요하신 분은 녹색버튼의 Install이 표출됩니다.
Plugin Install

프로젝트에 Kotlin 설정

Plugin을 정상적으로 설치 한 후에는 Tools > Kotlin 메뉴가 생성 됩니다.
해당 메뉴로 접근해보시면, Configure Kotlin in Project가 있습니다.
해당 메뉴를 선택하여 현재의 프로젝트에 Kotlin을 개발 할 수 있는 환경을 설정할 수 있습니다.
Configure Kotlin

해당 메뉴를 클릭하면 다음과 같은 팝업창이 생성됩니다.
Selection Kotlin Version
현재 프로젝트에서 사용될 Kotlin의 버전을 선택 한 후, Ok버튼을 눌러주면 Gradle에 몇줄의 코드가 추가되며,
Gradle의 Sync를 맞춰주면 프로젝트에서 Kotlin을 이용한 Android의 개발 준비가 완료됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Project Level Gradle
buildscript {
ext.kotlin_version = '1.1.4-3'
// code...
dependencies {
// code...
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// App Level Gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
// code...
}
dependencies {
// code...
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}

Project Level의 build.gradle에서는 Kotlin의 버전을 명시해주는 코드와 classpath를 추가하는 코드가 생성되며,
App Level의 build.gradle에서는 Kotlin과 관련된 plugin과 dependency 관련 코드가 추가 됩니다.

MainActivity Java -> Kotlin Convert

Class 또는 Activity를 새롭게 작성해 볼 수 있지만, 빠르게 훓어보기 위해서 프로젝트 생성 시 만들어진 MainActivity Class를 Kotlin으로 컨버팅해보았습니다.
IDE를 이용한 컨버팅을 위해서 Android Studio의 메뉴 중 Code > Convert Java file to Kotlin file 메뉴를 사용하면 됩니다.
듣기로는 IDE 수준에서 생각보다 수준 높은 컨버팅을 지원하는 기능이라고는 하지만, 실제로 Kotlin에 숙련도가 생기면 자동으로 컨버팅 되는 코드가 마음에 들지 않는다는 이야기도 있습니다.
하지만, 저희는 Kotlin의 문법을 우선은 구경해보는 것이 목적이기에 자동으로 컨버팅되는 것으로도 충분 할 것 같습니다.
Convert Code

Kotlin 훑어보기

성공적으로 변경이 완료된 후에는 개개인에 따라 조금은 낯선 코드들로 변경되었을 것 같습니다.
그럼 지금부터, 기존에 작성된 Java코드와 Kotlin코드가 어떻게 다른지 훓어보도록 하죠!

처음으로는 Class의 선언부 부터 한번 살펴보도록 하겠습니다.

1
2
3
4
5
// Java Code
public class MainActivity extends AppCompatActivity {}
// Kotlin Code
class MainActivity : AppCompatActivity() {}

크게 달라진 부분은 없지만, AppCompatActivity상속하는 코드가 달라졌습니다.
기존의 Java에서는 Class를 상속받기 위해 extends 키워드를 사용하였던것 과는 달리
Kotlin에서는 : (콜론)을 이용하여 상속을 받는 것을 볼 수 있습니다.
언뜻보아 Swift에서 Class를 상속받는 문법과 비슷해 보입니다.

그리고 미세한 차이이지만 Java에서 있던 접근제한자인 public 키워드도 Kotlin에서는 사라진 것을 볼 수 있습니다.
Kotlin에서는 명시적으로 open하지 않은 Class는 기본적으로 final이라고 합니다.

다음으로는 Activity가 시작되면 제일 먼저 실행되는 메서드인 onCreate()를 살펴보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Java Code
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
// Kotlin Code
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar = findViewById(R.id.toolbar) as Toolbar
setSupportActionBar(toolbar)
val fab = findViewById(R.id.fab) as FloatingActionButton
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
}

첫번째 차이점, method 선언부입니다.
Java에서는 오버라이드된 메서드에 대하여 @Override 어너테이션을 이용하여 해당 메서드가 오버라이드 되었음을 명시하고 있지만,
Kotlin에서는 method의 선언부 앞에 override 키워드를 붙여 해당 메서드가 오버라이드 되었음을 명시하고 있습니다.

Kotlin문서를 조금이라도 보셨다면 아시겠지만, 보시지 않은 분들은 조금은 낯선 메서드 선언법 같지 않나요?
Kotlin에서는 다음과 같이 method를 선언합니다.

1
2
3
fun methodName(parameter: Type) : retun Type {
// your code
}

Kotlin에서는 fun 키워드를 이용하여 메서드를 선언하고, 메서드의 명칭, 매개변수의 명칭과 타입, 그리고 마지막으로 :과 함께 해당 메서드 실행에 따른 반환되는 데이터의 타입을 명시하여 메서드를 선언할 수 있습니다.

하지만 위의 onCreate()메서드에서는 리턴 타입이 없지 않느냐? 라는 의문점을 가질 수 있을 것 같은데요,
Java에서 void 키워드는 리턴되는 값이 없음을 나타내듯 Kotlin에서는 Unit 키워드를 명시해주면 해당 메서드는 반환값이 없음을 나타낼 수 있습니다.
Unit 키워드는 생략할 수 있으므로 onCreate()메서드에서는 생략되었습니다.

두번째 차이점, 메서드의 매개변수입니다.
Java에서 메서드로 들어오는 매개변수들은 Type parameter의 형태로 데이터 타입을 먼저 명시하고 변수명을 명시하였다면,
Kotlin에서는 Java와는 반대로 parameter: Type의 형태로 변수명을 먼저 명시하고 : 이후에 해당 매개변수의 데이터 타입을 명시되어 있습니다.

그리고, 여기서 조금 더 자세히 들여다보면 Kotlin에서의 Bundle객체 타입에 대하여 ?라는 키워드가 하나 더 붙어 있습니다.
기본적으로 Kotlin은 null을 허용하지 않도록 설계되었고, null을 사용하게 되더라도 안전하게 사용할 수 있도록 설계 되었다고 합니다.
때문에, Kotlin에서 null이 될 수 있는 부분에 대해서는 개발자가 이를 미리 인지하고 ? 키워드를 데이터 타입과 함께 선언하여 null이 될 수 있음을 미리 선언해두어야 합니다.

그렇기에, 안드로이드 개발자라면 기본적으로 모두 알고 있듯, onCreate()메서드로 들어오는 Bundle객체인 savedInstanceState는 null이 될 수 있기에 null을 허용할 수 있도록 Bundle?과 같은 형식으로 선언되었다는 것을 알 수 있습니다.

세번째 차이점, 변수의 선언 및 타입캐스팅입니다.
xml에 선언된 View를 찾아오는 코드를 보면 문법의 차이가 확연히 나타나는 것을 볼 수 있습니다.
우선 Java에서는 볼 수 없었던 val이라는 키워드 입니다.
Kotlin에서의 변수 선언은 val(or var) name: Type = literal과 같은 문법으로 선언하게 됩니다.
Kotlin에서는 데이터의 변동유무에 따라, val 또는 var과 같은 키워드를 이용하여 변수를 선언하게 되는데,
valvalue의 약어로 immutable(불변의) 데이터를 저장하기 위한 변수에 사용되며,
varvariable의 약어로 mutable(변하기 쉬운) 데이터를 저장하기 위한 변수에 사용됩니다.

한가지 더 차이점을 찾아보면, 타입 캐스팅을 위한 코드의 부분입니다.
Java에서는 타입캐스팅을 위해 괄호와 함께 타입을 명시하여 Type name = (Type) xxxx의 형태로 사용되었지만,
Kotlin에서는 as 키워드를 이용하여 val name = xxx as Type의 형태로 타입캐스팅을 할 수 있습니다.

네번째 차이점, Lambda식의 지원입니다.
드디어 onCreate()메서드 부분의 끝이 왔네요! setOnClickListener부분이 보이시나요?
Java에서도 RetroLambda와 같은 라이브러리를 이용하면 Lambda식을 사용할 수 있었지만, Kotlin은 외부의 라이브러리 도움없이 기본적으로 Lambda식을 지원합니다.

안드로이드 개발자 포지션으로 전향한지 몇년되진 않았지만, 안드로이드 개발을 하다보면 Lambda식 지원의 부재가 아쉬울 때가 가끔 있었습니다.
안드로이드 프레임워크에서 강제(?)하는 보일러 플레이트로 인해 click listner등을 이용하다 보면 반복적인 불필요한 코드가 많이 발생합니다.
그럴때마다 가끔은 Lambda식을 사용할 수 있었다면 불필요한 코드가 많이 줄었을 것 같은데...라는 아쉬움이 많았지만, 위에서 언급한 RetroLambda와 같은 추가적인 외부 라이브러리를 포함하기는 꺼려했었기에 아쉬운대로 안드로이드 프레임워크에서 제공하는 기본틀 그대로 개발을 해왔었습니다. 아마 저와 비슷한 분들이 많을 것 같은…
하지만, Kotlin에서는 Lambda식을 기본적으로 지원하고 있으니, 저와 같은 성향을 가진 개발자분들에게는 희소식일 것 같습니다.
언제가 될지 모르겠지만, Kotlin을 도입하여 본격적으로 개발하는 날이 오게 되면 Lambda식을 이용하여 불필요한 코드의 제거, 가독성의 향상 등 많은 이점들을 경험할 수 있을 것 같다는 기대가 됩니다.

여기까지 Class의 선언부터 onCreate()메서드까지의 코드를 한번 살펴보았습니다.
그 외의 메서드인 onCreateOptionMenuonOptionsItemSelected에 관련된 코드도 더 있지만,
이미 onCreate()메서드에서 Java와 Kotlin을 비교하며 적어내려간 설명을 이해하셨다면,
언급되지 않은 남은 코드들은 이미 스스로 분석이 가능할 것이라고 믿어 의심치 않습니다.
나머지 부분에 대해서는 독자분들에게 숙제로 남겨두고 싶네요!

마무리

단순히 Android에서 Kotlin을 사용하는 방법에 대해서 짧게 써내려가고 싶었는데,
사람의 욕심은 끝이 없듯 쓰다보니 조금이라도 더 설명해 드리고 싶어 긴 글이 되었습니다 :(

저 또한, 아직 본격적으로 Kotlin을 적용해보지 않았고, 이제 막 시작하는 Kotlin Beginner이기에 잘못 설명된 부분도 없지 않아 있을 것 같습니다.
하지만 나누면 좋다라는 말이 있듯이 부족한 실력에도 혹시 Android에서 Kotlin을 시작하고 싶어하시는 분들을 위해 포스팅을 남겨보았습니다.

앞으로 틈틈히 못다한 Kotlin 문법에 대한 스터디와 병행하며 개인적인 Android 프로젝트에 Kotlin을 적용해보고,
Kotlin을 이용한 Android 개발이 Java로 개발할 때와 어떤 다른점과 이점이 있기에 여러 스타트업에서 Kotlin 경험자를 선호하기 시작하였는지 알아 볼 계획입니다.

이미 많은 Kotlin 능숙자분들이 계시고 블로그에 좋은글을 공유해주시는 분들이 계시기에 Kotlin과 관련된 글을 많이 써내려가진 않을 것 같지만,
경험을 통해 얻을 수 있었던 이점이나 소소한 Tip이 생기면 블로그를 통해 공유해보도록 하겠습니다!

여하튼, Kotlin을 본격적으로 적용해보진 않았지만,
단순히 플러그인을 설치하고, IDE의 도움을 받아 코드를 Kotlin으로 컨버팅 해보는 것만으로도 Kotlin의 몇가지 매력을 볼 수 있었던 것 같습니다.
앞으로도 Kotlin의 많은 매력을 느낄 수 있길 기대해보며 포스팅을 마무리하겠습니다.
Kotlin Beginner 파이팅!