빙응의 공부 블로그

[Kotlin] 코틀린(Kotlin) 기본 문법 (Java 개발자 관점) 본문

Kotlin

[Kotlin] 코틀린(Kotlin) 기본 문법 (Java 개발자 관점)

빙응이 2025. 11. 4. 21:49

저는 평소 자바를 중심으로 개발해왔습니다. 이번에 코틀린을 배우고 활용할 기회가 생겨, 새로운 언어로의 도전을 통해 개발 역량을 넓혀가고자 합니다.


1. 변수 

1-1 변수 선언

Kotlin은 변수 선언 때 val(불변), var(가변) 키워드를 통해 타입 추론을 지원합니다.

아래처럼 가변, 불변을 정하고 타입 추론 기능이 기본 탑재되어 있습니다. 

val name: String = "김병웅" // 읽기만 가능
var age: Int = 20           // 읽기/쓰기 가능
var address = "충북"         // 타입 추론 (String)

 

 

Javafinal 키워드를 직접 적어 변수의 불변성을 지정해줘야 하며, 타입을 항상 명시해야 합니다.

final String name = "김병웅"; // 읽기만 가능
int age = 20;               // 읽기/쓰기 가능

1-2 Null 안정성 허용 변수

Kotlin은 기본적으로 null을 허용하지 않으며, ?를 붙여야만 null을 허용합니다. 그렇기에 컴파일 시 null 예외를 잡으며 null에 대한 자바보다 강력한 안정성을 제공합니다.

var nullableName: String? = null // Null 허용
// var nonNullName: String = null // 컴파일 오류

 

 

Java는 기본적으로 null을 허용하며, 런타임 중에 null에 대한 예외가 발생합니다. (NullPointException)

String nullableName = null; // 가능

 

1-3 Null 체크와 삼항연산자

Kotlin은 safe Call ?. 와 Elvis Operator ?:로 null 체크를 안전하고 간결하게 처리할 수 있습니다.

val name: String? = null

// 1. Safe Call (?.): name이 null이면 null 반환
val nameLength = name?.length

// 2. Elvis Operator (?:): name이 null이면 0 반환
val lengthOrDefault = name?.length ?: 0

 

Javaif문이나 3항 연산자로 수동 체크해야 합니다. 물론 Optional을 이용해서 사용할 수 있지만 코드의 길이가 길어지며 객체 생성 오버헤드가 존재합니다. 

String name = null;

// Safe Call 흉내
Integer nameLength = (name != null) ? name.length() : null;
// Optional 버전
Optional<Integer> nameLengthOpt = Optional.ofNullable(name)
                                          .map(String::length);

// Elvis Operator 흉내
int lengthOrDefault = (name != null) ? name.length() : 0;
// Optional 버전
int lengthOrDefaultOpt = Optional.ofNullable(name)
                                 .map(String::length)
                                 .orElse(0);

 


2. 흐름 제어

2-1 IF 표현식

Kotlinif문 자체가 값을 반환하는 표현식으로 사용될 수 있습니다. 그렇기에 3항 연산자가 불필요합니다.

(클린 코드 관점을 봤을 때 Kotlin도 if문이 복잡해지면 분리하는게 맞습니다.)

val msgType = 1
val msg = if (msgType == 1) "안녕" else "잘가"

 

Javaif는 문장이며 값을 변환할 수 없습니다. 그렇기에 3항 연산자를 사용해야합니다.

int msgType = 1;
String msg = (msgType == 1) ? "안녕" : "잘가";

2-2 Switch 표현식

Kotilnwhen은 자바의 switch를 대체하며, break가 필요 없고 표현식으로 값 변환이 가능합니다.

val inputType = 2
val result = when (inputType) {
    1 -> "1"
    2, 3 -> "2 or 3" // 여러 조건
    in 1..100 -> "1..100 OK" // 범위
    else -> "not"
}

 

Javaswitch문을 사용합니다. (Java 14w+부터는 switch 표현식이 추가되어 Kotlin과 유사합니다.)

int inputType = 2;
String result;

switch (inputType) {
    case 1:
        result = "1";
        break;
    case 2:
    case 3:
        result = "2 or 3";
        break;
    // 범위(in) 처리가 번거로움
    default:
        result = "not";
}

2-2 FOR 반복문

Kotlinfor-in 구문과 범위 연산자를 사용하여 매우 직관적으로 사용할 수 있습니다.

val list = listOf(1, 2, 3)

// 값 기반
for (value in list) { ... }

// 1부터 100 까지
for (i in 1..100) { ... }

// 1 부터 10 까지,  2씩 증가
for (i in 2..10 step 2) { ... } 

// 10부터 1 까지 감소
for (i in 10 downTo 1) { ... }

 

Java는 전통적인 for 문 또는 for-each 문을 사용합니다.

List<Integer> list = List.of(1, 2, 3);

// 값 기반
for (Integer value : list) { ... }

// 1부터 100 까지
for (int i = 1; i <= 100; i++) { ... }

// 10부터 1 까지 감소
for (int i = 10; i >= 1; i--) { ... }

3. 함수

3-1 함수 선언

Kotlin의 함수 선언은 fun 키워드를 사용하며, 반환 타입이 뒤에 옵니다. 표현식 본문(단일 라인)을 지원합니다.

// 기본
fun basicFunc(name: String): Int {
    return name.toInt()
}

// 표현식 본문 (반환 타입 추론 가능)
fun simpleFunc(name: String) = name.toInt()

 

Java의 함수 선언은 반호나 타입이 앞에 오며, 항상 {} 블록이 필요합니다.

public int basicFunc(String name) {
    return Integer.parseInt(name);
}

3-2 기본 매개변수

Kotlin은 파라미터에 기본값을 설정할 수 있으며, 오버로딩을 줄여줍니다.

fun simpleFunc(name: String = "김찬정", age: Int): String {
    return "$name, $age"
}

// 호출 가능
simpleFunc(20)           // name 생략 → "김찬정", 20
simpleFunc("홍길동", 25)  // name 직접 지정

 

Java는 이러한 기능이 없으며, 메서드 오버로딩을 통해 수동으로 구현해야합니다.

public String simpleFunc(String name, int age) {
    return name + ", " + age;
}

// 오버로딩
public String simpleFunc(int age) {
    return simpleFunc("김찬정", age);
}

 

3-2 명명된 매개변수

Kotlin은 파라미터 순서와 상관없이 이름을 명시하여 값을 전달할 수 있습니다.

// simpleFunc(name = "김잔정", age = 10)
simpleFunc(age = 10, name = "김잔정") // 순서 변경 가능

 

Java는 반드시 파라미터 순서를 지켜야합니다.

 

3-3 확장 함수

Kotlin은 상속 없이 기존 클래스에 새 함수를 추가할 수 있습니다. (해당 함수는 변수의 스코프 개념과 동일하게 적용됩니다.)

// String 클래스에 lastChar() 함수를 추가
fun String.lastChar(): Char {
    return this[this.length - 1]
}

val last = "Hello".lastChar() // 'o'

 

Java는 이러한 기능 없이, static 유틸리티 클래스로 구현해야 합니다.

// StringUtils.java
public class StringUtils {
    public static char lastChar(String str) {
        return str.charAt(str.length() - 1);
    }
}

// 사용 (객체지향적이지 않음)
char last = StringUtils.lastChar("Hello");

4. 클래스

4-1 클래스 선언

Kotlin은 다음과 같이 클래스를 선언합니다. 접근제어자 또한 자바와 동일하게 작동합니다. 또한 생성자, Getter, Setter를 자동으로 만들어 줍니다.

class SimpleClass(val name: String, var address: String, var age: Int = 41)
// val -> 읽기 전용 프로퍼티 (getter만 생성)
// var -> 읽기/쓰기 가능 (getter + setter 생성)

 

Java는 필드, 생성자, Getter, Setter를 모두 수동으로 작성해야 합니다. (Lombok 사용 시 단축 가능)

public class SimpleClass {
    private final String name;
    private String address;
    private int age;

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

    // ... Getters and Setters ...
}

4-2 companion object (static 멤버)

Kotlinstatic 키워드 대신 companion object 블럭을 사용합니다.

class MyClass {
    companion object {
        const val PI = 3.14 // 컴파일 상수
        fun create() = MyClass() // 팩토리 메서드
    }
}

// 사용
val pi = MyClass.PI
val instance = MyClass.create()

 

Javastatic 키워드를 사용합니다.

public class MyClass {
    public static final double PI = 3.14; // 상수

    public static MyClass create() {
        return new MyClass();
    }
}

// 사용
double pi = MyClass.PI;
MyClass instance = MyClass.create();

 

4-3 데이터 클래스

Kotlin은 DTO(VO)를 위해 data 키워드를 제공합니다. equals(), hashCode(), toString(), copy() 등을 자동 생성합니다.

data class Entity(val id: Long, val name: String)

 

Java도 JAVA 16+에서 record라는 동일한 기능을 제공합니다.

// Java 16+
public record Entity(Long id, String name) {}

// Java (Lombok)
// @Data
// public class Entity {
//     private final Long id;
//     private final String name;
// }

 

4-4 상속

Kotlin의 클래스는 기본적으로 final(상속 불가)입니다. open 키워드를 붙여야 상속이 가능합니다.

open class Parent { // 1. 상속 허용
    open fun work() { ... } // 2. 오버라이드 허용
}

class Child : Parent() { // 3. 상속
    override fun work() { ... } // 4. 오버라이드
}

 

Java의 클래스는 기본적으로 상속 가능(open)입니다. final을 붙여야 상속을 막을 수 있습니다.

 

public class Parent { // 1. 기본이 open
    public void work() { ... } // 2. 기본이 open
}

public class Child extends Parent { // 3. 상속
    @Override
    public void work() { ... } // 4. 오버라이드
}

 


 

 

 

여기까지가 기본적인 문법입니다. 말 그대로 기초입니다. 그 다음 포스팅은 심화 문법에 대해 알아보겠습니다.

주제 : 객체 초기화, 코루틴, 컬렉션, 고차함수, 람다, 예외, sealed class 등입니다.

'Kotlin' 카테고리의 다른 글

[Kotlin] 코틀린(Kotlin) 심화 문법 (Java 개발자 관점)  (0) 2025.11.05