| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 파이썬설치
- 쥬피터노트북
- Jupyter notebook
- 머신러닝
- 주피터노트북
- Anaconda python
- python install
- Keras
- tensorflow?
- deep learning
- 텐서플로우란?
- Machine learning
- Python설치
- 주피터
- 아나콘다
- 쥬피터
- 파이썬
- conda
- 기본경로변경
- TensorFlow
- anaconda 환경변수
- 텐서플로우
- 가상환경
- jupyternotebook
- 텐서플로
- Anaconda
- Python
- nbextensions
- 파이썬 install
- Today
- Total
소소한 개발이야기
[Kotlin #02] Java 개발자를 위한 Kotlin 기본 문법 — 변수, 함수, 조건문 본문

지난 글에서는 Kotlin이 왜 탄생했는지, 그리고 Java와 무엇이 다른지 큰 그림을 살펴봤습니다. 이번 글에서는 예고한 대로 변수, 함수, 조건문이라는 가장 기본적인 문법을 Java와 하나씩 비교하며 정리했습니다. 매일 쓰는 문법이라 처음에 확실히 잡아 두면 이후 내용이 훨씬 편해집니다.
목차
- 변수 선언: val과 var
- Kotlin의 타입 시스템
- 함수 선언
- 조건문: if와 when
- 한눈에 비교하기
- 마무리
1. 변수 선언: val과 var
✅ (1) val은 불변, var는 가변
Kotlin의 변수 선언 키워드는 두 가지뿐입니다. 한 번 값을 넣으면 바꿀 수 없는 val과, 언제든 다시 대입할 수 있는 var입니다. Java로 치면 val은 final이 붙은 변수와 같습니다.
Java
final String name = "Kotlin"; // 불변 변수
int count = 0; // 가변 변수
count = 1;
Kotlin
val name = "Kotlin" // 불변 변수 (Java의 final)
var count = 0 // 가변 변수
count = 1
name = "Java" // 컴파일 에러! val은 재할당 불가
💡 Kotlin에서는 기본적으로 val을 쓰고, 꼭 필요할 때만 var를 쓰는 것이 관례입니다. 값이 바뀌지 않는다는 것이 보장되면 코드를 읽기도, 디버깅하기도 훨씬 쉬워집니다.
✅ (2) 타입 추론과 명시적 타입
타입은 대입하는 값으로 추론되기 때문에 대부분 생략합니다. 필요하다면 변수 이름 뒤에 : 타입 형태로 직접 적을 수 있습니다. Java와 달리 타입이 이름 뒤에 온다는 점이 처음엔 조금 어색하게 느껴집니다.
Kotlin
val language = "Kotlin" // String으로 추론
val version: Int = 2 // 타입을 직접 명시
val price: Double // 선언만 먼저 하고
price = 19.99 // 나중에 한 번만 초기화해도 된다
참고로 Java 10부터 var 키워드로 지역 변수 타입 추론이 가능해졌지만, Kotlin은 지역 변수뿐 아니라 프로퍼티와 함수 반환 타입에서도 추론을 지원합니다.
✅ (3) 상수는 const val
컴파일 시점에 값이 정해지는 상수는 const val로 선언합니다. Java의 static final 상수에 해당합니다.
Java
public static final int MAX_COUNT = 100;
Kotlin
const val MAX_COUNT = 100 // 최상위(top-level)나 object 안에서만 선언 가능
2. Kotlin의 타입 시스템
✅ (1) 원시 타입이 따로 없다
Java는 int와 Integer처럼 원시 타입과 래퍼 클래스가 나뉘어 있습니다. Kotlin에는 이런 구분이 없고 모든 것이 객체입니다. 대신 컴파일러가 가능한 경우 내부적으로 원시 타입으로 바꿔 주기 때문에 성능 걱정은 하지 않아도 됩니다.
Java
int a = 10;
Integer b = 10; // 박싱된 타입
String s = Integer.toString(a);
Kotlin
val a: Int = 10 // 바이트코드에서는 int로 컴파일
val b: Int? = 10 // nullable이면 Integer로 컴파일
val s = a.toString() // Int에서 바로 메서드 호출 가능
✅ (2) 자동 형 변환이 없다
Java에서는 int를 long 변수에 그대로 넣을 수 있지만, Kotlin은 숫자 타입 사이의 암묵적 변환을 허용하지 않습니다. 반드시 toLong() 같은 변환 함수를 명시해야 합니다. 처음엔 번거롭지만, 의도치 않은 형 변환으로 생기는 버그를 막아 줍니다.
Java
int i = 10;
long l = i; // 자동으로 확장 변환
Kotlin
val i: Int = 10
val l: Long = i // 컴파일 에러!
val l2: Long = i.toLong() // 명시적으로 변환해야 한다
✅ (3) 문자열 템플릿
문자열 안에 $변수 또는 ${표현식}을 넣으면 값이 바로 들어갑니다. Java에서 +로 이어 붙이거나 String.format()을 쓰던 코드가 훨씬 간결해집니다.
Java
String msg = "안녕하세요, " + name + "님! 장바구니에 " + items.size() + "개가 있습니다.";
Kotlin
val msg = "안녕하세요, ${name}님! 장바구니에 ${items.size}개가 있습니다."
3. 함수 선언
✅ (1) fun 키워드와 기본 형태
Kotlin의 함수는 fun 키워드로 선언합니다. 변수와 마찬가지로 매개변수 타입과 반환 타입이 뒤에 옵니다. 또한 Java와 달리 클래스 밖에 함수를 바로 선언할 수 있어서, 유틸리티 메서드를 위해 static 클래스를 따로 만들 필요가 없습니다.
Java
public class MathUtils {
public static int add(int a, int b) {
return a + b;
}
}
Kotlin
// 클래스 없이 파일 최상위에 바로 선언 가능
fun add(a: Int, b: Int): Int {
return a + b
}
✅ (2) 단일 표현식 함수
함수 본문이 한 줄짜리 식이라면 중괄호와 return을 생략하고 =로 바로 연결할 수 있습니다. 이때는 반환 타입도 추론됩니다.
Kotlin
fun add(a: Int, b: Int) = a + b
fun isAdult(age: Int) = age >= 19
✅ (3) 기본값 인자와 이름 붙인 인자
Java에서는 매개변수 조합이 다양하면 오버로딩 메서드를 여러 개 만들어야 했습니다. Kotlin은 매개변수에 기본값을 줄 수 있어서 함수 하나로 해결됩니다. 호출할 때 매개변수 이름을 붙이면 순서와 상관없이 원하는 값만 넘길 수 있습니다.
Java
public void createOrder(String item) {
createOrder(item, 1, false);
}
public void createOrder(String item, int quantity) {
createOrder(item, quantity, false);
}
public void createOrder(String item, int quantity, boolean express) {
// 주문 생성 로직
}
Kotlin
fun createOrder(item: String, quantity: Int = 1, express: Boolean = false) {
// 주문 생성 로직
}
createOrder("노트북") // quantity = 1, express = false
createOrder("노트북", 3) // express = false
createOrder("노트북", express = true) // 이름 붙인 인자로 중간 값 건너뛰기
이름 붙인 인자는 true, false처럼 의미를 알기 어려운 값을 넘길 때 특히 가독성이 좋아집니다.
✅ (4) 반환값이 없을 때는 Unit
Java의 void에 해당하는 타입은 Unit입니다. 반환값이 없는 함수에서는 보통 생략합니다.
Kotlin
fun printLog(message: String): Unit { // ": Unit"은 생략 가능
println("[LOG] $message")
}
4. 조건문: if와 when
✅ (1) if는 '문'이 아니라 '식'이다
Kotlin의 if는 값을 반환하는 식(expression)입니다. 그래서 Kotlin에는 삼항 연산자(? :)가 없습니다. if-else 자체가 그 역할을 하기 때문입니다.
Java
String grade = score >= 60 ? "합격" : "불합격";
Kotlin
val grade = if (score >= 60) "합격" else "불합격"
블록을 쓰는 경우에는 블록의 마지막 줄이 반환값이 됩니다.
Kotlin
val discount = if (isMember) {
println("회원 할인 적용")
0.1 // 이 값이 discount에 대입된다
} else {
0.0
}
✅ (2) switch를 대체하는 when
Java의 switch는 break를 빠뜨리면 다음 case로 넘어가는(fall-through) 실수가 잦았습니다. Kotlin의 when은 break가 필요 없고, if와 마찬가지로 값을 반환하는 식으로 쓸 수 있습니다.
Java
String status;
switch (code) {
case 1:
status = "주문 접수";
break;
case 2:
status = "배송 중";
break;
case 3:
case 4:
status = "배송 완료";
break;
default:
status = "알 수 없음";
}
Kotlin
val status = when (code) {
1 -> "주문 접수"
2 -> "배송 중"
3, 4 -> "배송 완료" // 여러 값을 콤마로 묶기
else -> "알 수 없음" // 식으로 쓸 때는 else가 필수
}
✅ (3) when의 다양한 조건
when은 단순한 값 비교뿐 아니라 범위(in), 타입(is), 임의의 조건식까지 받을 수 있습니다. 지난 글에서 소개한 스마트 캐스트도 when과 함께 쓰면 특히 깔끔합니다.
Kotlin
// 범위 검사
val level = when (score) {
in 90..100 -> "A"
in 80..89 -> "B"
in 70..79 -> "C"
else -> "F"
}
// 타입 검사 + 스마트 캐스트
fun describe(obj: Any): String = when (obj) {
is String -> "문자열, 길이 ${obj.length}" // String으로 자동 캐스팅
is Int -> "정수, 두 배는 ${obj * 2}"
else -> "알 수 없는 타입"
}
// 인자 없이 if-else if 체인 대신 사용
val shipping = when {
weight > 30 -> "화물 배송"
weight > 5 -> "일반 택배"
else -> "소형 택배"
}
💡 Java 14부터 도입된 switch 표현식(
case 1 -> ...)도 비슷한 방향으로 발전했지만, Kotlin의when은 범위·타입·임의 조건까지 한 문법 안에서 다룰 수 있다는 점에서 훨씬 유연합니다.
5. 한눈에 비교하기
| 구분 | Java | Kotlin |
|---|---|---|
| 불변 변수 | final String s = "a"; |
val s = "a" |
| 가변 변수 | int n = 0; |
var n = 0 |
| 상수 | static final int MAX = 10; |
const val MAX = 10 |
| 타입 위치 | 이름 앞 (int a) |
이름 뒤 (a: Int) |
| 원시 타입 | int, Integer 구분 |
구분 없음 (Int) |
| 문자열 결합 | "a" + b |
"a$b" |
| 함수 선언 | public int f(int a) |
fun f(a: Int): Int |
| 반환값 없음 | void |
Unit (생략 가능) |
| 오버로딩 대체 | 메서드 여러 개 | 기본값 인자 |
| 삼항 연산자 | a ? b : c |
if (a) b else c |
| 분기문 | switch + break |
when (식으로 사용 가능) |
6. 마무리
이번 글에서 살펴본 문법들은 하나하나 보면 작은 차이지만, 공통된 방향이 있습니다. 불변을 기본으로 하고, 반복되는 코드를 줄이며, 문(statement)보다 식(expression)으로 표현한다는 것입니다. Java 개발자 입장에서는 타입을 뒤에 쓰는 것과 세미콜론을 생략하는 것만 손에 익으면, 나머지는 금방 자연스럽게 느껴질 겁니다.
다음 글에서는 반복문(for, while)과 컬렉션(List, Set, Map)을 Java와 비교하면서, Kotlin의 범위(.., until, step)와 읽기 전용/변경 가능 컬렉션의 차이를 정리해 보겠습니다.
궁금한 점이나 잘못된 내용이 있다면 댓글로 남겨 주세요. 읽어 주셔서 감사합니다! 😊