with ChatGPT 시리즈는 ChatGPT의 내용과 개인의 생각을 토대로 학습해 보는 컨텐츠입니다.
Kotlin에서는 변수를 선언할 때 var과 val 두 가지 키워드를 사용합니다.
이 둘의 차이를 이해하고, 실무에서 val이 선호되는 이유를 살펴보겠습니다.
🔥 1. var vs val 차이점
키워드 | 설명 | 변경 가능 여부 | Java와 비교 |
var | 가변 (Mutable) 변수 | ✅ 변경 가능 | private String name = "John"; |
val | 불변 (Immutable) 변수 | ❌ 변경 불가능 | final String name = "John"; |
var name = "Alice" // 변경 가능
name = "Bob" // ✅ 가능
val age = 25 // 변경 불가능
age = 30 // ❌ 오류 발생 (val cannot be reassigned)
- var은 변경 가능한 변수로 선언됨
- val은 한 번 할당되면 변경 불가능한 불변 변수
🛡️ 2. 실무에서 val을 선호하는 이유
✅ 1️⃣ 불변성을 유지하여 코드 안정성 증가
val을 사용하면 예기치 않은 값 변경을 방지하여 코드의 안정성을 높일 수 있습니다.
val user = User("Alice")
// user = User("Bob") ❌ 변경 불가능
- val을 사용하면 객체 참조를 변경할 수 없음 (다만 내부 프로퍼티 변경은 가능)
✅ 2️⃣ 멀티스레드 환경에서 동기화 이슈 방지
멀티스레드 환경에서 var을 사용하면 동시 접근 시 데이터 일관성 문제가 발생할 수 있습니다.
var counter = 0 // ❌ 여러 쓰레드에서 동시에 접근 시 문제 발생
fun increment() {
counter++
}
반면, val을 사용하면 쓰레드 간 값 변경을 방지할 수 있습니다.
val counter = AtomicInteger(0) // ✅ 안전한 접근
fun increment() {
counter.incrementAndGet()
}
- 불변성을 유지하면 멀티쓰레드 환경에서 동기화 비용을 줄일 수 있음
함수형 프로그래밍에서 얻을 수 있는 두 번째 유익은 안전한 동시성이다. 다중 스레드 프로그램에서는 적절한 동기화 없이 같은 데이터를 여러 '행위자'가 변경하는 경우 가장 많은 문제가 생긴다. 불변 데이터 구조와 순수 함수를 사용한다면 안전하지 않은 데이터 변경이 발생하지 않는다고 확신할 수 있으므로 복잡한 동기화 방법을 적용하지 않아도 된다.
- 코틀린 인 액션, 49p
✅ 3️⃣ 함수형 프로그래밍과 친화적
Kotlin은 함수형 프로그래밍(FP)의 철학을 따르는 언어이며, val은 불변성을 강조합니다.
val numbers = listOf(1, 2, 3, 4, 5)
val squared = numbers.map { it * it }
- val을 사용하면 데이터의 상태를 변경하지 않고 함수형 스타일로 처리 가능
함수형 프로그래밍에서는 입력이 같으면 항상 같은 출력을 내놓고 다른 객체의 상태를 변경하지 않으며 함수 외부나 다른 바깥 환경과 상호작용하지 않는 순수 함수를 사용한다. 이런 핵심 개념을 사용하는 함수형 스타일로 프로그램을 작성하면 어떤 유익이 있을까? 첫째로 간결성을 들 수 있다. 함수형 코드는 그에 상응하는 명령형 코드에 비해 더 간결하며 우아하다. 변수의 값을 변경하고 루프나 조건 분기에 의존하는 대신 (순수) 함수를 값처럼 활용할 수 있으면 더 강력한 추상화가 가능하다.
- 코틀린 인 액션, 48p
✅ 4️⃣ 예상치 못한 버그 예방
변수를 var로 선언하면 예기치 않게 값이 변경될 위험이 있습니다.
var username = "Alice"
if (someCondition) {
username = "Bob" // ❌ 예기치 않은 변경 발생 가능
}
반면, val을 사용하면 변경을 허용하지 않음으로써 의도한 값을 유지할 수 있습니다.
val username = "Alice" // ✅ 의도한 값 유지
✅ 5️⃣ 컴파일러 최적화 가능
val을 사용하면 컴파일러가 더 많은 최적화를 수행할 수 있음
예를 들어, val은 Java의 final 키워드로 변환되므로 성능이 향상될 수 있습니다.
final String name = "Alice"; // val이 자동으로 final 처리됨
🚀 3. 언제 var을 사용해야 할까?
val을 선호하는 것이 일반적이지만, 모든 경우에 var을 배제할 수는 없습니다. 아래는 var이 유용한 경우입니다.
✅ 1️⃣ 객체의 상태를 변경해야 할 때
var score = 10
score += 5 // 값 변경 필요할 때
✅ 2️⃣ 반복문에서 값이 변할 때
var sum = 0
for (i in 1..10) {
sum += i
}
✅ 3️⃣ UI 변경이 필요한 경우 (예: 안드로이드 ViewModel)
var uiState = "Loading..."
uiState = "Success"
변경이 필요한 상황이 아니라면 항상 val을 우선적으로 고려해야 함
🔥 var vs val 정리 요약
키워드 | 특징 | 추천 사용 사례 |
var | 변경 가능 | 값이 변해야 하는 경우 (카운터, UI 상태) |
val | 변경 불가능 | 객체 참조 유지, 함수형 프로그래밍, 멀티쓰레드 환경 |
항상 val을 먼저 사용하고, 필요한 경우에만 var을 고려하자!
🤔 추가로 생각해 볼 질문들
- Kotlin에서 val을 사용해도 내부 프로퍼티가 변경 가능하다면, 진정한 불변 객체(Immutable Object)를 만들려면 어떻게 해야 할까?
- Kotlin의 const val과 일반 val의 차이점은?
- 자바에서 final 키워드를 쓰면 Kotlin의 val과 완전히 동일한 효과일까?
- 컬렉션을 val로 선언하면 내부 원소는 변경할 수 있을까? (val list = mutableListOf(1, 2, 3))
- 안드로이드 개발에서 ViewModel을 사용할 때, var과 val 중 어느 것이 더 적절할까?