Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
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
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[TIL]20241007 Safe Call(?.), Elvis 연산자(?:), Not-null Assertion(!!) 활용 본문

Kotlin

[TIL]20241007 Safe Call(?.), Elvis 연산자(?:), Not-null Assertion(!!) 활용

최밤빵 2024. 10. 7. 19:17

코틀린에서 제공하는 대표적인 null 처리 방법으로 Safe Call(?.), Elvis 연산자(?:), 그리고 Not-null Assertion(!!)이 있다. 오늘 개발일지에서는 이 세 가지 null 처리 방법의 구체적인 예시와 함께 차이점을 어제 작성한 개발일지 내용보다 조금 더 자세하게 정리해봤다. 

 

▶Safe Call 연산자(?.)

Safe Call 연산자 '?.'는 null일 가능성이 있는 객체에서 메서드나 프로퍼티에 접근할 때 사용하는 연산자이다. 객체가 null이 아니면 해당 메서드를 호출하거나 프로퍼티에 접근하고, 객체가 null이면 그냥 null을 반환한다. 이를 통해 null 체크를 간단하게 할 수 있다.

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

→ name 변수는 Nullable 타입(String?)이기 때문에 null을 가질 수 있다. Safe Call 연산자를 사용하면 name이 null인지 확인한 뒤에 메서드를 호출하기 때문에 NullPointerException을 방지할 수 있다. 만약 name이 null이라면 name?.length는 null을 반환하고, 그렇지 않으면 length() 메서드가 호출되어 문자열의 길이를 반환한다.

 

▷Safe Call 연산자 장점

  • 코드가 간결해진다. 여러 줄에 걸친 null 체크를 한 줄로 처리할 수 있다.
  • null일 가능성이 있는 객체에 안전하게 접근할 수 있다.
  • NPE를 사전에 방지할 수 있다.

▷Safe Call 연산자 단점

  • null일 때 기본값을 제공하지 않으므로, 추가 처리가 필요할 수 있다.

▶Elvis 연산자(?:)

Elvis 연산자 '?:'는 null 체크 후에 기본값을 지정할 수 있는 연산자이다. 객체가 null이면 ?: 연산자 오른쪽에 있는 값을 반환하고, null이 아니면 해당 객체의 값을 반환한다. 이를 통해 null일 때 사용할 기본값을 간단하게 지정할 수 있다.

var name: String? = null
val length = name?.length ?: 0  // name이 null이면 0 반환, 아니면 length 값 반환
println(length)  // 출력: 0

→ name이 null일 경우 length에는 0이 할당된다. name이 null이 아니라면 name?.length의 값을 사용하고, null이면 0을 반환하는 방식이다. 이처럼 Elvis 연산자는 null일 경우 기본값을 간단히 지정할 수 있어 null 처리에 매우 유용하다.

 

▷Elvis 연산자 장점

  • null일 때 대체할 값을 쉽게 지정할 수 있다.
  • 코드 가독성이 좋으며, null 처리 후 기본값을 설정할 때 자주 사용된다.

▷Elvis 연산자 단점

  • 기본값을 너무 남용하면, null 처리 시의 의도와 다르게 동작할 수 있어 주의가 필요하다.

▶Not-null Assertion 연산자(!!)

Not-null Assertion 연산자 '!!'는 해당 객체가 절대 null이 아님을 보장하는 경우 사용한다. 만약 이 연산자가 붙은 변수가 null이면 바로 NPE가 발생한다. 즉, 개발자가 해당 변수는 절대 null이 아님을 확신할 때 사용하는 연산자이다.

var name: String? = "Kotlin"
val length = name!!.length  // name이 null이 아니라고 보장, 만약 null이면 NPE 발생
println(length)  // 출력: 6

→ !! 연산자를 사용하여 name이 절대 null이 아닐 것이라고 가정하고 length() 메서드를 호출한다. 만약 name이 null이면 NPE가 발생한다. 따라서 이 연산자는 확실히 null이 아닌 경우에만 사용해야 하며, 잘못 사용하면 치명적인 예외를 일으킬 수 있다.

 

▷Not-null Assertion 연산자 장점

  • null이 아닌 값으로 처리할 때 매우 직관적이다.
  • 개발자가 null이 아님을 보장할 수 있을 때 사용하면 간결한 코드를 작성할 수 있다.

▷Not-null Assertion 연산자 단점

  • 잘못 사용하면 런타임에서 NPE가 발생할 수 있다.
  • 남용 시 코드의 안정성이 떨어질 수 있다.

▶세 가지 null 처리 방법의 차이점 비교

연산자 동작 방식 장점 단점
Safe Call (?.) 객체가 null인지 체크하고, null이 아니면 메서드 호출, null이면 null 반환 NPE 방지, 간결한 null 처리 null일 때 기본값 제공 불가
Elvis 연산자 (?:) 객체가 null이면 대체값을 반환, null이 아니면 객체의 값을 반환 null 처리 시 기본값 제공 가능, 가독성 높음 남용 시 예상하지 못한 동작 발생 가능
Not-null Assertion (!!) 객체가 null이 아니라고 단언, null일 경우 NPE 발생 null이 아닌 값으로 처리할 때 직관적 잘못 사용하면 NPE 발생, 안전하지 않음

 

▶코틀린에서의 null 처리 방식 요약

  • Safe Call 연산자는 null 가능성을 가진 변수에서 안전하게 접근할 수 있는 가장 기본적인 방법이다. NPE를 방지하고, 더 안전한 코드를 작성할 수 있다.
  • Elvis 연산자는 null일 때 기본값을 제공할 수 있어 상황에 맞는 값을 제공하면서도 null 처리를 쉽게 할 수 있다.
  • Not-null Assertion 연산자는 null이 아님을 보장할 수 있을 때 사용하지만, 잘못된 사용은 NPE를 유발할 수 있다. 따라서 매우 신중하게 사용해야 한다.

각각의 방법은 null을 안전하게 처리하기 위한 도구이고, 상황에 맞게 적절하게 사용해야 한다. Safe Call과 Elvis 연산자는 null 처리를 보다 간결하고 안전하게 만들어주며, Not-null Assertion은 위험성이 따르지만 확실한 상황에서는 유용하다. 코틀린은 이러한 null 안전성 기능을 통해 자바에서 흔히 발생하는 NPE를 방지하고, 더 안정적인 코드를 작성할 수 있도록 돕는다.