2. Null-safety
널 처리와 Null-safety
코틀린은 **“널이 될 수 있는 타입은 완전히 다른 타입”**으로 취급합니다. ?
를 붙여야만 null 가능, 그에 맞는 도구(?.
, ?:
, !!
)를 제공합니다. 자바와 달리 컴파일 단계에서 null 안전성 확보가 가능하다는 점이 핵심입니다.
1) Null은 왜 문제인가?
Java의 대표적인 버그 원인: NPE (NullPointerException)
Java에서는 모든 참조형 변수에 기본적으로 null이 들어갈 수 있습니다.
방어 코드:
if (obj != null)
을 반복적으로 작성 → 가독성/생산성 저하
코틀린은 이 문제를 “언어 차원”에서 풀어냅니다.
2) Nullable vs Non-nullable 타입
val a: String = "kotlin"
// a = null // 컴파일 에러
val b: String? = null // ? 붙여야 null 가능
String
→ null 불가능String?
→ null 허용
👉 자바에서 String
하나만 있던 것이 코틀린에선 두 개로 분리됨.
👉 덕분에 컴파일러가 null 가능성을 추적할 수 있습니다.
3) Safe Call (?.
)
?.
)“null일 때는 그냥 건너뛰자”라는 의도를 코드로 표현합니다.
val len: Int? = b?.length
b
가 null → 결과는 nullb
가 non-null →length
실행
4) Elvis 연산자 (?:
)
?:
)null일 때 기본값을 지정할 수 있습니다.
val len = b?.length ?: 0
b
가 null →len = 0
b
가 non-null → 문자열 길이
→ Java의 ternary
연산자 패턴 (b != null ? b.length() : 0)
을 훨씬 간결하게 표현.
5) Non-null 단언 (!!
)
!!
)val len = b!!.length
“개발자가 확신하니 그냥 non-null로 취급해!”
만약 null이라면 → NPE 발생
👉 지양할 것. “자바 스타일” NPE를 그대로 불러옵니다. 정말 확신이 있을 때만 사용하세요.
6) 스마트 캐스트 (Smart cast)
코틀린은 null 체크 후 자동으로 타입을 좁혀줍니다.
if (b != null) {
println(b.length) // 여기선 String으로 캐스트됨
}
자바였다면 if (b != null) { System.out.println(b.length()); }
와 같지만,
코틀린은 별도의 캐스팅 없이 안전하게 접근 가능합니다.
7) 플랫폼 타입 (Platform type)
자바와 연동할 때 등장하는 개념입니다 .
// Java
String getName(); // @Nullable 붙어있지 않음
// Kotlin
val name = obj.name // 타입은 String!
자바에서 null 가능성이 명시되지 않으면, 코틀린은 “플랫폼 타입”(
String!
)으로 인식이 경우 컴파일러가 null 여부를 알 수 없어, 개발자가 책임지고 처리해야 함
해결책: 자바 코드에
@Nullable
/@NotNull
붙이기, 또는 코틀린 쪽에서?
/!!
로 방어
8) 실무 예시
A. API 응답 DTO
data class UserDto(
val id: Long,
val name: String,
val nickname: String?, // 옵션 필드
val email: String? // 서버에서 null 가능
)
→ nullable을 타입에 드러내므로 API 클라이언트가 강제적으로 null 처리.
B. Repository 패턴
fun findUser(id: Long): User? {
return db.findById(id) // 없으면 null
}
val user = repo.findUser(1) ?: throw NotFoundException()
→ Elvis 연산자로 “없으면 바로 예외”를 던지는 패턴.
9) 체크리스트 & 관용구
기본은 non-null 타입
null 가능성 있으면 반드시
?
표기null 접근:
?.
(safe call)기본값 제공:
?:
(elvis)정말 확신 있을 때만
!!
자바 interop → “플랫폼 타입 주의”
DTO는 null 가능성을 타입에서 바로 드러내라
Android 생명주기/DI 초기화 등은
lateinit
또는 safe call로 처리
10) 미니 치트시트
선언:
val s: String? = null
safe call:
s?.length
elvis:
s?.length ?: 0
not-null 단언:
s!!.length
(주의)null 체크 후 스마트 캐스트:
if (s != null) println(s.length)
자바 interop: 어노테이션으로 null 정보 명확히
Last updated