마스터하기 쉬운 Kotlin 기본 문법 총정리: 초보 개발자를 위한 가이드

Kotlin 소개

Kotlin은 JetBrains에서 개발한 현대적인 프로그래밍 언어입니다. 주로 JVM (Java Virtual Machine) 위에서 동작하며, Android 개발을 포함한 다양한 애플리케이션에서 널리 사용됩니다. 간결한 문법, 강력한 타입 시스템, Null-safe 기능 등 여러 가지 장점을 가지고 있어 많은 개발자들 사이에서 인기를 끌고 있습니다.

간결한 문법

Kotlin의 문법은 매우 간결하여 코드의 가독성과 유지보수성이 뛰어납니다. 예를 들어, Java에서 객체를 출력하는 코드를 비교해 보면 쉽게 알 수 있습니다.


public class Person {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person("John", 30);
        System.out.println("Name: " + person.getName());
        System.out.println("Age: " + person.getAge());
    }
}

Kotlin에서는 다음과 같이 작성할 수 있습니다.


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

fun main() {
    val person = Person("John", 30)
    println("Name: ${person.name}")
    println("Age: ${person.age}")
}

Null 안전성

Kotlin은 NullPointerException을 방지하기 위해 강력한 Null-safe 기능을 제공합니다. 변수 선언 시 기본적으로 Null을 허용하지 않으며, Null이 필요한 경우에는 물음표(?)를 사용하여 선언합니다.


var name: String = "John"     // Non-nullable 변수
var nullableName: String? = null   // Nullable 변수

fun printName(name: String?) {
    if (name != null) {
        println("Name is $name")
    } else {
        println("Name is null")
    }
}

fun main() {
    printName(name)           // 출력: Name is John
    printName(nullableName)   // 출력: Name is null
}

데이터 클래스

Kotlin에서 데이터 클래스는 주로 데이터 저장을 목적으로 사용되며, get/set 메서드, equals(), hashCode(), toString() 등의 메서드를 자동으로 생성해 줍니다.


data class User(val name: String, val age: Int)

fun main() {
    val user = User("Alice", 29)
    println(user)
}

변수와 데이터 타입

2.1 변수 선언

Kotlin에서 변수는 `val`과 `var` 키워드로 선언합니다. `val`은 값을 변경할 수 없는 불변 변수(immutable)를 선언할 때 사용하고, `var`는 값을 변경할 수 있는 가변 변수(mutable)를 선언할 때 사용합니다.

“`kotlin
val immutableVariable: String = “This is immutable”
var mutableVariable: Int = 10
“`

변수 타입은 Kotlin의 타입 추론 기능 덕분에 생략할 수도 있습니다.

“`kotlin
val inferredVariable = “Type is inferred as String”
var anotherInferredVariable = 20
“`

2.2 기본 데이터 타입

Kotlin에서는 다양한 기본 데이터 타입을 지원합니다. 대표적인 타입은 다음과 같습니다:

– `Int`: 정수
– `Double`: 실수
– `Boolean`: 참/거짓
– `Char`: 문자
– `String`: 문자열

기본 데이터 타입을 사용하는 예제는 다음과 같습니다:


fun main() {
    val intVar: Int = 42
    val doubleVar: Double = 3.14
    val booleanVar: Boolean = true
    val charVar: Char = 'A'
    val stringVar: String = "Hello, Kotlin!"

    println("Int value: $intVar")
    println("Double value: $doubleVar")
    println("Boolean value: $booleanVar")
    println("Char value: $charVar")
    println("String value: $stringVar")
}

2.3 Null 처리

Kotlin은 안전한 Null 처리를 위해 Null 안전성을 언어 차원에서 지원합니다. 변수를 선언할 때 타입 뒤에 `?`를 붙이면 Null을 허용할 수 있습니다. Null 값을 다룰 때는 안전한 호출 연산자(`?.`), 엘비스 연산자(`?:`), 그리고 `!!` 연산자 등을 사용할 수 있습니다.


fun main() {
    var nullableString: String? = "I can be null"
    nullableString = null

    // Safety call operator
    println(nullableString?.length)  // Output: null
    
    // Elvis operator
    val length = nullableString?.length ?: -1
    println(length)  // Output: -1
    
    // Not-null assertion operator
    try {
        println(nullableString!!.length)
    } catch (e: NullPointerException) {
        println("Caught a NullPointerException")
    }
}

조건문과 반복문

3.1 조건문

Kotlin에서는 다양한 조건문을 사용할 수 있습니다. 대표적인 조건문으로는 `if`와 `when`이 있습니다.

if 조건문

기본적인 `if` 조건문 사용 예제입니다:


fun main() {
    val a = 10
    val b = 20

    if (a > b) {
        println("a is greater than b")
    } else if (a < b) {
        println("a is less than b")
    } else {
        println("a is equal to b")
    }
}

`if`를 표현식으로 사용할 수도 있습니다:


fun main() {
    val max = if (a > b) a else b
    println("The maximum value is $max")
}

when 조건문

`when`은 좀 더 강력한 조건문으로, 여러 조건을 처리할 수 있습니다:


fun main() {
    val number = 3

    when (number) {
        1 -> println("One")
        2, 3 -> println("Two or Three")
        in 4..10 -> println("Between Four and Ten")
        else -> println("Unknown number")
    }

    // when을 표현식으로 사용
    val result = when {
        number % 2 == 0 -> "Even"
        else -> "Odd"
    }
    println("The number is $result")
}

3.2 반복문

Kotlin에서는 `for`와 `while` 반복문을 사용할 수 있습니다.

for 반복문

기본적인 `for` 반복문 사용 예제입니다:


fun main() {
    val items = listOf("apple", "banana", "kiwi")

    for (item in items) {
        println(item)
    }

    for (index in items.indices) {
        println("Item at $index is ${items[index]}")
    }
}

while 반복문

기본적인 `while`과 `do-while` 반복문 사용 예제입니다:


fun main() {
    var x = 5

    while (x > 0) {
        println(x)
        x--
    }

    x = 0
    do {
        println("x is now $x")
        x++
    } while (x < 5)
}

함수와 람다

4.1 함수 정의

Kotlin에서 함수 정의는 `fun` 키워드를 사용합니다. 함수는 기본적으로 반환 타입과 매개변수를 가질 수 있습니다.

기본적인 함수 정의 예제:


fun main() {
    println(sum(3, 4))
    println(maxOf(5, 10))
}

fun sum(a: Int, b: Int): Int {
    return a + b
}

fun maxOf(a: Int, b: Int): Int {
    return if (a > b) a else b
}

단일 표현식 함수의 경우 return 문 대신 표현식을 사용할 수 있으며, 반환 타입을 추론할 수 있습니다:


fun sum(a: Int, b: Int) = a + b

4.2 고차 함수

고차 함수는 함수를 매개변수로 받거나 반환하는 함수입니다.

고차 함수의 예제:


fun main() {
    val result = higherOrderFunc(5, 10, ::sum)
    println("The result is $result")

    val lambdaResult = higherOrderFunc(5, 10) { a, b -> a * b }
    println("The lambda result is $lambdaResult")
}

fun higherOrderFunc(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

fun sum(a: Int, b: Int): Int {
    return a + b
}

4.3 람다식

람다식은 익명 함수로, 코드를 간결하게 작성할 수 있는 방법입니다. 중괄호 `{}` 안에 인자 리스트와 표현식을 작성합니다.

기본적인 람다식의 예제:


fun main() {
    val sumLambda: (Int, Int) -> Int = { x, y -> x + y }
    println(sumLambda(3, 4))

    val items = listOf(1, 2, 3, 4, 5)
    val doubledItems = items.map { it * 2 }
    println(doubledItems)

    val filteredItems = items.filter { it % 2 == 0 }
    println(filteredItems)
}

람다식을 사용하는 또 다른 예제:


fun main() {
    val greeting: (String) -> Unit = { name -> println("Hello, $name!") }
    greeting("Kotlin")

    val multiplyLambda: (Int, Int) -> Int = { a, b -> a * b }
    println(multiplyLambda(3, 5))
}

클래스와 객체지향 프로그래밍

5.1 클래스 선언

Kotlin에서의 클래스 선언은 `class` 키워드를 사용해 정의할 수 있습니다.

기본적인 클래스 선언 예제:


fun main() {
    val person = Person("John", 25)
    println(person.name)
    println(person.age)
    person.introduce()
}

class Person(val name: String, var age: Int) {
    fun introduce() {
        println("Hi, I'm $name and I'm $age years old.")
    }
}

하나의 파일에 여러 클래스를 정의하는 경우:


fun main() {
    val rectangle = Rectangle(5.0, 3.0)
    println("Area: ${rectangle.area()}")

    val circle = Circle(4.0)
    println("Area: ${circle.area()}")
}

class Rectangle(val width: Double, val height: Double) {
    fun area() = width * height
}

class Circle(val radius: Double) {
    fun area() = Math.PI * radius * radius
}

5.2 상속

Kotlin에서 클래스 상속은 `:` 기호를 사용합니다. 기본적으로 모든 클래스는 기본 상속금지 상태이므로, 상속을 허용하려면 `open` 키워드를 사용해야 합니다.

상속의 예제:


fun main() {
    val dog = Dog("Buddy", 5)
    dog.sound()
}

open class Animal(val name: String, val age: Int) {
    open fun sound() {
        println("Some generic animal sound")
    }
}

class Dog(name: String, age: Int) : Animal(name, age) {
    override fun sound() {
        println("Bark")
    }
}

5.3 인터페이스

인터페이스는 클래스가 구현해야 하는 메서드와 프로퍼티를 정의할 수 있습니다. `interface` 키워드를 사용해 정의합니다.

인터페이스 예제:


fun main() {
    val myCar = Tesla()
    println("CarName: ${myCar.name}")
    myCar.startEngine()
}

interface Car {
    val name: String
    fun startEngine()
}

class Tesla : Car {
    override val name = "Tesla Model S"
    override fun startEngine() {
        println("Tesla engine started")
    }
}

5.4 데이터 클래스

데이터 클래스는 주로 데이터를 저장하는 용도로 사용하는 클래스입니다. `data` 키워드를 사용해 정의합니다.

데이터 클래스의 예제:


fun main() {
    val user = User("Alice", 30)
    println(user)

    val copiedUser = user.copy(age = 31)
    println(copiedUser)

    val (name, age) = user
    println("Name: $name, Age: $age")
}

data class User(val name: String, val age: Int)

Leave a Comment