본문 바로가기
개발

코틀린 시작하기

by 상5c 2023. 6. 18.

코틀린 기초 문법에 대해 간단히 정리하고 넘어가고자 한다.
필자는 자바 개발자이며 코틀린을 다뤄보지 않은 자바 개발자의 시점에서 작성하는 글임을 밝힌다.
글은 기억보관용으로 두서없이 작성하였다.

코틀린 프로젝트 생성하기

Intellij로 Java 프로젝트 생성하듯 생성하면 된다.

편의를 위해 스프링 이니셜라이저를 사용했고, 다른 의존성을 추가하지 않았다.

gradle-kotlin을 선택하면 build.gradle.kotlin 파일이 생성된다.

코틀린 파일 생성하기

폴더 우클릭 - New - kotlin을 선택하면 코틀린 파일을 생성할 수 있다.

Class / File / Interface / Data class / Enum class 등의 분류로 선택지가 나온다.

코틀린의 경우 Class가 아니어도 파일을 생성할 수 있어 File이라는 선택지가 존재한다.

클래스, 메서드, 변수

class Sample {

    fun hello(): String {
        var variable = "Hello, world!"
        val value = "constant"

        return variable + value
    }
}

클래스 생성은 자바와 같다. class 키워드와 클래스명을 적고 중괄호를 추가한다. (중괄호를 추가하지 않아도 되는데 이는 나중에)

메서드는 fun 키워드 뒤에 메서드명, 파라미터, 본문을 적는다. 클래스 하위에 fun 키워드가 있으면 메서드고 클래스에 포함되지 않아도 함수 형태로 존재할 수 있다.

예를 들어 main문은 클래스 없이 그냥 존재한다.

fun main(args: Array<String>) {
    val sample = Sample()
    println(sample.hello("Hello", 1))
}

new 키워드 없이 객체를 생성하는 것도 볼 수 있다.
변수와 상수는 var와 val로 구분한다. var는 “바”로, val은 “밸”로 읽는다. 각각 variable과 value의 약자이다.

  키워드 풀 스펠링 발음 변경
변수 var variable 가능
상수 val value 불가능

또다른 특징으로 코틀린은 세미콜론이 없어도 된다(있으면 안되는게 아니고 없어도 된다)
세미콜론은 추가하지 않는 편이다. (IDE가 빼도 된다고 알려준다)

클래스가 갖는 변수는 프로퍼티라고 부른다

class Hello(
    val name: String,
    val age: Int
)

자바랑 비교해보면 이런 모양이다.

class Hellojava {
    private final String name;
    private final String age;

    public Hellojava(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public String getAge() {
        return age;
    }
}

코틀린에서 getter, 생성자 등 보일러플레이트를 줄이고 간결하게 표현되는 것을 느낄 수 있다.

파라미터에 이름을 붙여서 전달도 가능하다.

fun main(args: Array<String>) {
    val hello = Hello(age = 1, name = "name")
    println(hello.age) // 1
}

네임드 파라미터라고 호칭한다. 장점은 선언부와 호출부의 파라미터 위치가 달라도 이름을 따라 값이 저장되기 때문에 명확한 값 전달이 가능해진다.

추가로, 디폴트 파라미터도 존재한다. 네임드 파라미터와 조합하면 자바에서 매우 귀찮았을 상황들을 많이 해결해준다.

class Hello(
    val name: String = "sang5c"
    val age: Int
)

fun main(args: Array<String>) {
    val hello = Hello(age = 1)
    println(hello.age) // 1
    println(hello.name) // sang5c
}

위의 예제를 보면 프로퍼티(멤버 변수)를 getter 대신 프로퍼티 명으로 접근하는 것을 볼 수 있다. 이와 관련된 자세한 내용은 다음 기회에.

코틀린은 기본으로 null을 담을 수 없다. null을 변수에 담고싶으면 ?를 붙여야 한다.

var str: String? = null
println(str?.length) // null

선언할 때 ?를 붙여 null이 담길 수 있음을 알리고, 사용할 때도 ?를 붙여 null이 발생 가능함을 인지했다고 알려야 한다. (붙이지 않으면 컴파일 에러가 발생한다)

자바로 바꿔보면 이렇다.

String str = null;
if (str == null) {
  System.out.println(null);
}
else {
    System.out.println(str.length());
}

이와 관련해서 또 편한 연산자인 엘비스 오퍼레이터 라는 것도 제공한다.

엘비스 프레슬리의 머리와 닮았다고 해서 붙여진 이름이다.

val result = str?.length ?: 0 // 0

좌항이 null이 아니라면 좌항의 결과 값이 result에 저장되고, 아니라면 엘비스 연산자 우측 값이 result에 저장된다. 자바와 비교해봤을 때 간결해지는 것들이 매우 많다고 느껴진다.

값이 로직상 null이 아니라면 강제로 not null 처리가 가능하다.

var result = str!!

이후로는 값이 null이 아니라고 판단하게 된다. (실제로 null이라면 NPE가 발생하니 주의)

반복문

자바와 비슷하게 사용 가능하다. in 키워드로 for-each 반복문을 사용한다.

val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
    println(item)
}

예제를 만들기 애매해서 공식 홈페이지의 코드를 가져왔다.

반복 내에서 index가 같이 필요하면 list 기본 함수(?)인 indices를 호출하여 반복문을 돌리고 인덱스를 통해 리스트에 접근하여 값을 읽을 수 있다.

val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
    println("item at $index is ${items[index]}")
}

참고로, 해당 함수는 IntRange를 반환하는 함수다.

While문은 사용법이 같아 생략한다.

이외에도 Range, When 등 편한 문법이 많이 있다. 아래는 범위에 x가 속하는지 확인하는 문법이다.

val x = 10
val y = 9
if (x in 1..y+1) {
    println("fits in range")
}