들어가며
Kotlin은 JetBrains가 만든 JVM 기반 언어로, 2017년 Google I/O에서 Android 공식 언어로 채택된 이후 백엔드 서버 개발에서도 빠르게 확산되고 있다. Java와 100% 상호 운용이 가능하면서도, 훨씬 간결하고 표현력 있는 문법을 제공한다.
이 글에서는 Kotlin의 핵심 문법을 실무·알고리즘 관점에서 정리하고, 코딩 테스트에서 바로 쓸 수 있는 노하우를 함께 담았다.
1. 변수 선언: val vs var
val name: String = "Kotlin" // 불변 (Java의 final)
var count: Int = 0 // 가변
// 타입 추론: 명시 생략 가능
val pi = 3.14
var score = 100
Kotlin
복사
2. Null 안전성 (Null Safety)
Kotlin의 타입 시스템은 null 가능 여부를 타입에 명시한다.
var a: String = "hello"
// a = null // 컴파일 에러
var b: String? = "world"
b = null // OK
// 안전 호출 연산자 ?.
val length = b?.length // b가 null이면 null 반환
// 엘비스 연산자 ?:
val len = b?.length ?: 0 // null이면 0 반환
// 단언 연산자 !! (null이면 NPE 발생 — 꼭 필요한 경우만)
val forced = b!!
Kotlin
복사
3. 함수 선언
// 기본 함수
fun add(a: Int, b: Int): Int {
return a + b
}
// 단일 표현식 함수
fun multiply(a: Int, b: Int) = a * b
// 기본값 매개변수
fun greet(name: String, greeting: String = "Hello") = "$greeting, $name!"
// 명명된 인수
greet(name = "Kotlin", greeting = "Hi")
Kotlin
복사
4. 컬렉션과 함수형 API
Kotlin 컬렉션은 listOf, mutableListOf, mapOf, setOf 등으로 생성하며, Java Stream 없이도 강력한 함수형 처리가 가능하다.
val numbers = listOf(3, 1, 4, 1, 5, 9, 2, 6)
// 필터 + 변환 + 합산
val result = numbers
.filter { it > 3 }
.map { it * 2 }
.sum() // 40
// groupBy: 알고리즘에서 빈도 계산에 유용
val freq = numbers.groupBy { it } // Map<Int, List<Int>>
val countMap = numbers.groupingBy { it }.eachCount() // Map<Int, Int>
// sorted / sortedBy
val sorted = numbers.sortedDescending()
val words = listOf("banana", "apple", "cherry")
val byLength = words.sortedBy { it.length }
Kotlin
복사
5. 데이터 클래스 (data class)
data class Point(val x: Int, val y: Int)
val p1 = Point(1, 2)
val p2 = p1.copy(y = 10) // 불변 복사
println(p1 == Point(1, 2)) // true (구조적 동등성)
println(p1) // Point(x=1, y=2)
Kotlin
복사
equals(), hashCode(), toString(), copy()가 자동 생성된다.
val visited = mutableSetOf<Point>()
visited.add(Point(0, 0))
visited.contains(Point(0, 0)) // true
Kotlin
복사
6. 확장 함수 (Extension Function)
기존 클래스를 수정하지 않고 새 함수를 추가하는 Kotlin의 킬러 기능이다.
fun Int.factorial(): Long {
var result = 1L
for (i in 2..this) result *= i
return result
}
println(10.factorial()) // 3628800
// 알고리즘: IntArray에 swap 추가
fun IntArray.swap(i: Int, j: Int) {
val tmp = this[i]; this[i] = this[j]; this[j] = tmp
}
val arr = intArrayOf(3, 1, 2)
arr.swap(0, 2) // [2, 1, 3]
Kotlin
복사
7. when 표현식
Java switch의 강화판. 값, 범위, 타입 체크까지 처리한다.
fun grade(score: Int): String = when {
score >= 90 -> "A"
score >= 80 -> "B"
score >= 70 -> "C"
else -> "F"
}
// 타입 체크
fun describe(obj: Any): String = when (obj) {
is Int -> "정수: $obj"
is String -> "문자열 길이: ${obj.length}"
is List<*> -> "리스트 크기: ${obj.size}"
else -> "알 수 없음"
}
Kotlin
복사
8. 구조 분해 (Destructuring)
val (x, y) = Point(3, 7)
// 맵 순회
val map = mapOf("a" to 1, "b" to 2)
for ((key, value) in map) {
println("$key -> $value")
}
// 인덱스와 값 동시 접근
val list = listOf("x", "y", "z")
for ((index, value) in list.withIndex()) {
println("$index: $value")
}
Kotlin
복사
9. 알고리즘 실전 패턴 모음
BFS 탬플릿
import java.util.LinkedList
fun bfs(graph: Array<IntArray>, start: Int): IntArray {
val dist = IntArray(graph.size) { -1 }
val queue = LinkedList<Int>()
dist[start] = 0
queue.add(start)
while (queue.isNotEmpty()) {
val cur = queue.poll()
for (next in graph[cur]) {
if (dist[next] == -1) {
dist[next] = dist[cur] + 1
queue.add(next)
}
}
}
return dist
}
Kotlin
복사
우선순위 큐 (최소 힙)
import java.util.PriorityQueue
// 기본: 오름차순
val minHeap = PriorityQueue<Int>()
// 내림차순 (최대 힙)
val maxHeap = PriorityQueue<Int>(compareByDescending { it })
// 커스텀 정렬: (거리, 노드)
val dijkstra = PriorityQueue<Pair<Int, Int>>(compareBy { it.first })
dijkstra.add(Pair(0, start))
Kotlin
복사
2D 배열 초기화
// 크기 n×m, 0으로 초기화
val dp = Array(n) { IntArray(m) { 0 } }
// 특정 값으로 초기화
val inf = Array(n) { IntArray(m) { Int.MAX_VALUE / 2 } }
Kotlin
복사
입출력 빠르게 처리하기
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.StringTokenizer
fun main() {
val br = BufferedReader(InputStreamReader(System.`in`))
val sb = StringBuilder()
val (n, m) = br.readLine().split(" ").map { it.toInt() }
repeat(n) {
val st = StringTokenizer(br.readLine())
val a = st.nextToken().toInt()
val b = st.nextToken().toInt()
sb.appendLine(a + b)
}
print(sb)
}
Kotlin
복사
10. Java와 Kotlin 문법 비교 요약
기능 | Java | Kotlin |
불변 변수 | final int x = 1 | val x = 1 |
Null 체크 | if (s != null) | s?.length ?: 0 |
데이터 객체 | @Data (Lombok) | data class |
문자열 보간 | "Hello " + name | "Hello $name" |
타입 체크 | instanceof | is |
삼항 연산자 | a > b ? a : b | if (a > b) a else b |
반복 범위 | for (int i=0; i<n; i++) | for (i in 0 until n) |
마무리
Kotlin은 문법 자체가 알고리즘 풀이에 유리하게 설계되어 있다. val/var 구분, Null 안전성, 강력한 컬렉션 API, data class의 자동 구현 등이 모두 버그를 줄이고 코드를 짧게 만들어준다.
처음엔 Java 문법에 Kotlin 특성을 하나씩 얹는 방식으로 익히고, 익숙해지면 함수형 API와 확장 함수를 적극 활용해보자. 같은 로직을 Java와 Kotlin으로 번갈아 짜보는 것도 빠른 학습법이다.

