프로그래밍안드로이드 개발자

Kotlin에서 안전 호출 연산자('?.')는 어떻게 작동하며 nullable 타입을 다룰 때 언제 사용해야 할까요?

Hintsage AI 어시스턴트로 면접 통과

답변.

안전 호출 연산자 '?.'는 Kotlin에서 null 값을 다루기 위한 주요 도구 중 하나로, 잠재적으로 없는 값을 안전하게 사용할 수 있도록 언어의 안전성과 편리함을 높이기 위해 도입되었습니다.

문제의 역사: Java에서는 null 값이 종종 오류(NullPointerException)의 원인이 됩니다. Kotlin은 nullable 및 not-nullable 변수를 명시적으로 구분하는 엄격한 타입 시스템을 도입하고 이를 편리하게 사용할 수 있는 도구와 함께 제공했습니다.

문제: null일 수 있는 객체를 다룰 때 NullPointerException을 피하고, 코드의 가독성과 간결성을 희생하지 않으려면 어떻게 해야 할까요?

해결책: '?.' 연산자는 nullable 변수를 섬세하게 다룰 수 있게 해주며, 객체가 null이 아닐 때만 호출을 수행하고 null일 때는 null을 반환합니다(또는 추가적인 로직을 수행합니다).

코드 예시:

val user: User? = getUser() val name = user?.name // user가 null이 아니면 user.name을 반환, 그렇지 않으면 null user?.printInfo() // user가 null이 아니면 printInfo()가 호출됨

주요 특징:

  • 명시적 null 검사( if (object != null) { ... } )를 피할 수 있음
  • 중첩된 검사를 대체하는 간결하고 편리한 대안
  • let 및 Elvis 연산자와 함께 null 사례를 처리할 수 있음

함정 질문.

안전 호출 연산자 '?.'를 할당의 왼쪽에서 사용할 수 있나요?

아니요. '?.' 연산자는 속성이나 변수를 안전하게 설정하기 위해 사용할 수 없으며, 오직 접근이나 호출을 위한 것입니다. 다음은 유효하지 않습니다:

user?.name = "Alex" // 컴파일 오류

속성 할당은 명시적 검사로 안전하게 수행할 수 있습니다:

user?.let { it.name = "Alex" }

null을 만났을 때 안전 호출 연산자의 체인은 무엇을 반환하나요?

체인의 '?.' 중 하나가 null이면 표현식의 결과는 null이 되고, 이후의 안전 호출은 수행되지 않습니다.

예시:

user?.address?.zipCode // user 또는 address가 null일 경우, 결과는 null

Unit을 반환하는 함수와 함께 안전 호출 '?.'를 사용할 수 있나요?

네, 객체가 null이 아닐 때만 호출이 발생하며, 객체가 null일 경우 Unit 대신 null이 반환됩니다.

예시:

user?.clearData() // user가 null일 경우 아무 일도 일어나지 않음

일반적인 실수 및 안티-패턴

  • '?.' 뒤에 '!!'를 사용 — 안전 호출의 의미가 상실되고 NullPointerException을 초래할 수 있음.
  • null을 처리하지 않고 긴 '?.' 체인을 작성 — 결과는 추가적인 검사가 없으면 작업하기 불편할 수 있음.

실제 사례

부정적인 케이스

개발자가 null일 수 있는 객체에서 긴 안전 호출 체인 뒤에 '!!'를 사용:

val country = user?.address?.city?.country!!

장점:

  • 간결함.

단점:

  • 체인 어느 곳에서든 null이 발생하면 애플리케이션이 NullPointerException으로 종료됨.

긍정적인 케이스

안전 호출을 Elvis 연산자와 함께 사용하여 기본값을 반환:

val country = user?.address?.city?.country ?: "Unknown"

장점:

  • 오류 방지, 예측 가능한 행동, 가독성.

단점:

  • 추가 로그 없이 체인에서 null이 발생한 지점을 진단하기 어려울 수 있음.