Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
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 31
Tags more
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[TIL]20241006 Nullable과 Non-Nullable 타입: 코틀린의 null 안전성 본문

Kotlin

[TIL]20241006 Nullable과 Non-Nullable 타입: 코틀린의 null 안전성

최밤빵 2024. 10. 6. 21:29

NPE(NullPointerException)라는 에러는 변수나 객체가 null인 상태에서 메서드를 호출하거나 접근하려고 할 때 발생하는 대표적인 런타임 에러 중 하나다. 자바에서는 null 값을 허용하는 변수와 그렇지 않은 변수를 구분하지 않기 때문에 이 에러를 방지하기 위해 별도의 null 체크를 해야 한다.하지만 코틀린에서는 이러한 문제를 미리 방지할 수 있는 null 안전성 기능을 제공한다. 

 

▶자바에서의 NPE 문제

자바에서는 변수에 null 값을 할당하는 것이 기본적으로 허용된다. 따라서 null이 할당된 변수를 사용할 때 메서드를 호출하거나 필드에 접근하면 NullPointerException이 발생하게 된다.

String name = null;
System.out.println(name.length()); // NPE 발생

→ name에 null을 할당한 후 length() 메서드를 호출하면 런타임 시 NPE가 발생한다. 자바에서 이 문제를 방지하기 위해서는 null 체크를 해야 하는데, 이는 코드가 복잡해지고 실수로 체크를 빠뜨릴 가능성이 있다.

 

if (name != null) {
        System.out.println(name.length());
        }

→ null 체크를 추가하여 NPE를 방지할 수 있지만, 모든 코드에서 일일이 null 체크를 하는 것은 번거롭고 실수를 유발할 수 있다. 이러한 문제를 해결하기 위해 코틀린은 더 안전한 null 처리를 위한 기능을 제공한다.

 

▶코틀린의 Nullable과 Non-Nullable 타입

코틀린에서는 변수에 null을 허용할지 여부를 명시적으로 지정할 수 있다. Non-Nullable 타입은 null을 허용하지 않는 타입이고, Nullable 타입은 null을 허용하는 타입이다. 이를 통해 컴파일 타임에 null 관련 에러를 미리 방지할 수 있다.

 

▷Non-Nullable 타입

코틀린에서는 기본적으로 모든 변수는 Non-Nullable 타입이다. 변수를 선언할 때 그 변수는 null 값을 가질 수 없다는 것을 의미한다. 만약 null을 할당하려고 하면 컴파일 에러가 발생한다.

var name: String = "John"
name = null  // 컴파일 에러: Null을 할당할 수 없음

→ String 타입으로 선언된 변수는 null을 허용하지 않으므로, null을 할당하려고 하면 컴파일 시점에서 오류가 발생한다. 이를 통해 런타임에 NPE가 발생할 가능성을 사전에 차단할 수 있다.

 

▷Nullable 타입

만약 변수에 null 값을 허용해야 한다면, 타입 뒤에 '?' 기호를 붙여서 Nullable 타입으로 선언해야 한다. Nullable 타입은 null을 허용하며, null 값을 가질 수 있다.

var name: String? = "John"  // Nullable 타입 선언
name = null  // 가능: null 값을 할당할 수 있음

→ String? 타입은 Nullable 타입으로, null 값을 가질 수 있다. 하지만 Nullable 타입의 변수는 바로 메서드를 호출할 수 없으며, 이를 안전하게 사용하기 위해 다양한 방법을 제공한다.

 

▶Nullable 타입 안전하게 사용하기

코틀린에서는 Nullable 타입을 안전하게 사용할 수 있도록 여러 가지 방법을 제공한다.

 

▷안전 호출 연산자(?.)

안전 호출 연산자 '?.'를 사용하면, 해당 변수가 null인 경우 메서드를 호출하지 않고 null을 반환하게 된다. 이를 통해 NPE를 방지할 수 있다.

var name: String? = "John"
println(name?.length)  // name이 null이 아니면 length 호출, null이면 null 반환

→ 만약 name이 null이면 name?.length는 null을 반환하고, 그렇지 않으면 정상적으로 length() 메서드를 호출한다.

 

▷엘비스 연산자(?:)

엘비스 연산자 '?:'는 Nullable 값이 null일 때, 기본값을 지정할 수 있도록 한다. 이를 통해 null인 경우에 대비한 값을 간단하게 지정할 수 있다.

var name: String? = null
val length = name?.length ?: 0  // name이 null이면 기본값 0을 사용
println(length)  // 출력: 0

→ name이 null이므로 length에는 기본값인 0이 할당된다. 엘비스 연산자를 사용하면 null에 대한 대체 값을 쉽게 설정할 수 있다.

 

▷Not-Null 단언 연산자(!!)

'!!' 연산자는 변수의 값이 null이 아님을 개발자가 확신할 때 사용하는 연산자이다. 만약 null일 경우, NPE가 발생하므로 이 연산자는 신중하게 사용해야 한다.

var name: String? = "John"
println(name!!.length)  // name이 null이 아니므로 length 호출

→ 이 연산자는 nullable 변수를 Non-Nullable 변수처럼 취급하게 해주지만, null이 들어오는 경우 예외가 발생하기 때문에 꼭 필요한 경우에만 사용해야 한다.

 

▶Nullable과 Non-Nullable의 사용 예시

자바에서 흔히 사용하는 null 체크를 코틀린에서는 아래와 같이 처리할 수 있다.

▷자바 코드

String name = null;
if (name != null) {
        System.out.println(name.length());
        } else {
        System.out.println("name이 null입니다");
}

 

▷코틀린 코드

var name: String? = null
println(name?.length ?: "name이 null입니다")

→ 코틀린은 더 간결하고 명확하게 null 처리를 할 수 있다는 장점이 있다.

 

▶코틀린의 null 안전성 기능의 장점

→ 컴파일 타임에 오류 방지:

Non-Nullable 타입과 Nullable 타입을 명확히 구분하여 컴파일 타임에 null로 인한 오류를 방지할 수 있다.

→ 간결한 코드:

안전 호출 연산자와 엘비스 연산자를 통해 null 체크를 간단하게 처리할 수 있다.

→ NPE 방지:

코틀린의 null 안전성 기능 덕분에 자바에서 흔히 발생하는 NPE 문제를 효과적으로 해결할 수 있다.

 

코틀린의 null 안전성 기능을 통해 자바에서 자주 발생하는 NPE 문제를 효과적으로 해결할 수 있다. Non-Nullable과 Nullable 타입을 명확히 구분하여 null에 대한 처리를 컴파일 시점에서 안전하게 처리할 수 있으며 특히, 안전 호출 연산자 ?., 엘비스 연산자 ?: 등을 사용하여 간결하게 null 처리를 할 수 있다.