Kotlin 함수 | 함수 정의, 람다, 고차 함수
이 글의 핵심
Kotlin 함수: 함수 정의, 람다, 고차 함수. 함수 정의·람다식.
들어가며
함수는 일급 객체로 다루어져, 변수에 담고 고차 함수의 인자로 넘기기 쉽습니다. 람다·익명 함수 문법이 짧아, 컬렉션 연산과 잘 맞습니다.
1. 함수 정의
기본 함수
Kotlin 함수의 기본 형태입니다:
// 1. 반환값 없는 함수
fun greet(name: String) {
// fun: 함수 선언 키워드
// greet: 함수 이름
// (name: String): 매개변수 (이름: 타입)
// 반환 타입 생략 시 Unit (void와 유사)
println("안녕하세요, $name님!")
// $name: 문자열 템플릿 (변수 삽입)
}
greet("홍길동") // 안녕하세요, 홍길동님!
// 2. 반환값 있는 함수 (블록 본문)
fun add(a: Int, b: Int): Int {
// : Int : 반환 타입 명시 (필수)
return a + b
// return 키워드로 값 반환
}
val result = add(10, 20)
println(result) // 30
// 3. 표현식 함수 (단일 표현식)
fun add(a: Int, b: Int) = a + b
// = 뒤에 표현식 작성
// 반환 타입 자동 추론 (Int)
// return 키워드 불필요
// 간결하고 읽기 쉬움
// 표현식 함수 예시
fun max(a: Int, b: Int) = if (a > b) a else b
fun square(x: Int) = x * x
fun isEven(x: Int) = x % 2 == 0
println(max(10, 20)) // 20
println(square(5)) // 25
println(isEven(4)) // true
// 4. Unit 반환 (명시적)
fun printSum(a: Int, b: Int): Unit {
// Unit: 반환값이 없음을 명시 (생략 가능)
// Java의 void와 유사하지만 실제로는 싱글톤 객체
println(a + b)
// return 생략 가능 (자동으로 Unit 반환)
}
// Unit 생략 (권장)
fun printSum(a: Int, b: Int) {
println(a + b)
}
함수 선언 위치:
// 최상위 함수 (파일 레벨)
fun topLevel() {
println("최상위 함수")
}
class MyClass {
// 멤버 함수 (클래스 내부)
fun memberFunction() {
println("멤버 함수")
}
// 지역 함수 (함수 내부)
fun outer() {
fun inner() {
println("지역 함수")
}
inner() // 지역 함수 호출
}
}
기본 매개변수
fun greet(name: String = "Guest", greeting: String = "안녕하세요") {
println("$greeting, $name님!")
}
greet() // 안녕하세요, Guest님!
greet("홍길동") // 안녕하세요, 홍길동님!
greet("홍길동", "Hello") // Hello, 홍길동님!
greet(greeting = "Hi") // Hi, Guest님!
가변 인자
// 실행 예제
fun sum(vararg numbers: Int): Int {
return numbers.sum()
}
println(sum(1, 2, 3)) // 6
println(sum(1, 2, 3, 4, 5)) // 15
// 배열 전달
val nums = intArrayOf(1, 2, 3)
println(sum(*nums)) // spread 연산자
2. 람다식
기본 문법
// 람다 정의
val sum = { a: Int, b: Int -> a + b }
println(sum(10, 20)) // 30
// 타입 추론
val multiply: (Int, Int) -> Int = { a, b -> a * b }
// 단일 매개변수 (it)
val square: (Int) -> Int = { it * it }
println(square(5)) // 25
람다 활용
Kotlin의 컬렉션 함수와 람다를 함께 사용하는 예제입니다:
val numbers = listOf(1, 2, 3, 4, 5)
// 1. filter: 조건에 맞는 요소만 선택
val evens = numbers.filter { it % 2 == 0 }
// { it % 2 == 0 }: 람다 표현식
// it: 암묵적 매개변수 (단일 매개변수일 때 사용)
// it % 2 == 0: 짝수 판별 조건
//
// 동작:
// 1 → false (제외)
// 2 → true (포함)
// 3 → false (제외)
// 4 → true (포함)
// 5 → false (제외)
println(evens) // [2, 4]
// 명시적 매개변수 사용
val evens2 = numbers.filter { num -> num % 2 == 0 }
// num: 명시적 매개변수 이름
// it 대신 의미 있는 이름 사용 가능
// 2. map: 각 요소를 변환
val doubled = numbers.map { it * 2 }
// 각 요소에 2를 곱함
// [1, 2, 3, 4, 5] → [2, 4, 6, 8, 10]
println(doubled) // [2, 4, 6, 8, 10]
// map 실전 예시: 객체 변환
data class User(val name: String, val age: Int)
val users = listOf(
User("홍길동", 25),
User("김철수", 30)
)
val names = users.map { it.name }
println(names) // [홍길동, 김철수]
// 3. forEach: 각 요소에 대해 작업 수행 (반환값 없음)
numbers.forEach { println(it) }
// 출력:
// 1
// 2
// 3
// 4
// 5
// forEach는 반환값이 없으므로 체이닝 불가
// map/filter와 달리 부수 효과(side effect)를 위해 사용
// 4. reduce: 배열을 하나의 값으로 축약
val sum = numbers.reduce { acc, num -> acc + num }
// acc: 누적값 (accumulator)
// num: 현재 요소
//
// 동작:
// acc=1 (첫 요소), num=2 → 1+2=3
// acc=3, num=3 → 3+3=6
// acc=6, num=4 → 6+4=10
// acc=10, num=5 → 10+5=15
println(sum) // 15
// fold: 초기값 지정 가능
val sum2 = numbers.fold(0) { acc, num -> acc + num }
// 0: 초기값
// reduce는 첫 요소가 초기값, fold는 명시적 초기값
// 실전 예시: 문자열 연결
val words = listOf("Hello", "World", "Kotlin")
val sentence = words.reduce { acc, word -> "$acc $word" }
println(sentence) // Hello World Kotlin
체이닝 예제:
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = numbers
.filter { it % 2 == 0 } // 짝수만: [2, 4, 6, 8, 10]
.map { it * it } // 제곱: [4, 16, 36, 64, 100]
.filter { it > 20 } // 20 초과: [36, 64, 100]
.sum() // 합계: 200
println(result) // 200
3. 고차 함수
함수를 매개변수로
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
val result1 = calculate(10, 5) { a, b -> a + b } // 15
val result2 = calculate(10, 5) { a, b -> a * b } // 50
함수를 반환
fun makeMultiplier(factor: Int): (Int) -> Int {
return { number -> number * factor }
}
val double = makeMultiplier(2)
val triple = makeMultiplier(3)
println(double(5)) // 10
println(triple(5)) // 15
4. 확장 함수
기본 확장
// String에 함수 추가
fun String.addExclamation() = "$this!"
println("Hello".addExclamation()) // Hello!
// Int에 함수 추가
fun Int.isEven() = this % 2 == 0
println(4.isEven()) // true
println(5.isEven()) // false
실전 확장 함수
// List 확장
fun <T> List<T>.secondOrNull(): T? {
return if (size >= 2) this[1] else null
}
val list = listOf(1, 2, 3)
println(list.secondOrNull()) // 2
// String 확장
fun String.isValidEmail(): Boolean {
return matches(Regex("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"))
}
println("test@example.com".isValidEmail()) // true
5. 스코프 함수
let
val name: String? = "홍길동"
name?.let {
println("이름: $it")
println("길이: ${it.length}")
}
apply
// 실행 예제
data class Person(var name: String = "", var age: Int = 0)
val person = Person().apply {
name = "홍길동"
age = 25
}
also
val numbers = mutableListOf(1, 2, 3)
.also { println("초기 리스트: $it") }
.also { it.add(4) }
.also { println("최종 리스트: $it") }
run
// 실행 예제
val result = "Hello".run {
println(this)
length
}
println(result) // 5
with
val person = Person("홍길동", 25)
with(person) {
println(name)
println(age)
}
6. 인라인 함수
kotlin 예제 코드입니다.
inline fun measureTime(block: () -> Unit) {
val start = System.currentTimeMillis()
block()
val end = System.currentTimeMillis()
println("실행 시간: ${end - start}ms")
}
measureTime {
Thread.sleep(1000)
}
7. 실전 예제
예제 1: 함수형 프로그래밍
data class User(val name: String, val age: Int, val city: String)
fun main() {
val users = listOf(
User("홍길동", 25, "서울"),
User("김철수", 30, "부산"),
User("이영희", 28, "서울"),
User("박민수", 35, "서울")
)
// 서울에 사는 30세 미만 사용자
val result = users
.filter { it.city == "서울" }
.filter { it.age < 30 }
.map { it.name }
println(result) // [홍길동, 이영희]
}
예제 2: DSL 스타일
class HTML {
private val content = StringBuilder()
fun head(block: () -> Unit) {
content.append("<head>")
block()
content.append("</head>")
}
fun body(block: () -> Unit) {
content.append("<body>")
block()
content.append("</body>")
}
override fun toString() = content.toString()
}
fun html(block: HTML.() -> Unit): HTML {
return HTML().apply(block)
}
val page = html {
head { }
body { }
}
정리
핵심 요약
- 함수:
fun, 표현식 함수, 기본 매개변수 - 람다:
{ a, b -> a + b },it - 고차 함수: 함수를 매개변수/반환
- 확장 함수: 기존 클래스에 함수 추가
- 스코프 함수: let, apply, also, run, with
다음 단계
관련 글
- JavaScript 함수 | 함수 선언, 화살표 함수, 콜백, 클로저 완벽 정리
- Python 함수 | 매개변수, 반환값, 람다, 데코레이터 완벽 정리
- Swift 함수와 클로저 | 함수 정의, 클로저, 고차 함수
- C++ std::function vs 함수 포인터
- C++ 기본 인자
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. Kotlin 함수: 함수 정의, 람다, 고차 함수. 함수 정의·람다식로 흐름을 잡고 원리·코드·실무 적용을 한글로 정리합니다. Kotlin·함수·람다 중심으로 설명합니다. Start now. 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. Kotlin 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- Swift 함수와 클로저 | 함수 정의, 클로저, 고차 함수
- Kotlin 변수와 타입 | val, var, 기본 타입 완벽 정리
- JavaScript 클래스 | ES6 Class 문법 완벽 정리
이 글에서 다루는 키워드 (관련 검색어)
Kotlin, 함수, 람다, 고차함수 등으로 검색하시면 이 글이 도움이 됩니다.