본문 바로가기
Android/Kotlin

[Android/Kotlin] Kotlin의 ?. 연산자와 ?: 연산자: 실제 예시로 이해하기

by quessr 2024. 11. 29.

 

개발 중 맵의 출발지/도착지를 재설정하는 기능을 구현하면서 Kotlin의 ?. 연산자와 ?: 연산자를 효율적으로 사용할 수 있는 상황이 발생했습니다.
이 글에서는 실제 예시와 함께 두 연산자의 쓰임새를 정리하고, 어떻게 이를 활용해 코드를 간결하고 직관적으로 만들었는지 정리 해 두고자 합니다.

 

문제 상황: 맵의 마커 업데이트

맵에서 사용자가 새로운 출발지나 도착지를 선택하면, 맵에 표시된 마커(레이블)를 업데이트해야 합니다. 이때 고려해야 할 점은 다음과 같습니다:

  1. 마커가 이미 존재하는 경우
    기존 마커의 위치를 업데이트해야 합니다.
  2. 마커가 존재하지 않는 경우
    새로 마커를 추가해야 합니다.

해결 방법: ?. 연산자와 ?: 연산자의 활용

이 문제를 해결하기 위해 아래와 같은 Kotlin 문법을 활용했습니다.

destinationLocationLabel?.moveTo(newLatLng)
    ?: run {
        destinationLocationLabel = map?.labelManager?.layer?.addLabel(
            LabelOptions.from(newLatLng)
                .setStyles(
                    setPinStyle(this, R.drawable.marker_destination)
                )
                .setTexts(LabelTextBuilder().setTexts("도착"))
        )
    }

 

코드 설명

1. ?. 연산자: Null-Safe 호출

destinationLocationLabel?.moveTo(newLatLng)

 

  •  의미: destinationLocationLabel이 null이 아닌 경우에만 moveTo(newLatLng) 메서드를 호출합니다.
  •  사용 이유: 기존에 마커가 존재하면 마커를 옮기기만 하면 되기 때문입니다.

2. ?: 연산자: Elvis 연산자

?: run {
    destinationLocationLabel = map?.labelManager?.layer?.addLabel(...)
}

 

 

 

  •  의미: destinationLocationLabel?.moveTo(newLatLng)의 결과가 null이라면, 즉 마커가 존재하지 않는 경우 새 마커를 추가합니다.
  •  사용 이유: destinationLocationLabel이 null일 때만 새로 마커를 추가해야 하기 때문입니다.

동작 흐름

  1. 마커가 이미 존재하는 경우
    •   destinationLocationLabel?.moveTo(newLatLng)가 실행됩니다.
    •   ?. 연산자 덕분에 moveTo(newLatLng)가 안전하게 호출됩니다.
    •   Elvis 연산자 ?: 이후의 코드는 실행되지 않습니다.
  2. 마커가 존재하지 않는 경우
    •   destinationLocationLabel?.moveTo(newLatLng)의 결과가 null이 됩니다.
    •   Elvis 연산자 ?: 이후의 코드가 실행됩니다.
    •   새 마커를 추가하고, 그 객체를 destinationLocationLabel에 저장합니다.

왜 ?. 연산자와 ?: 연산자가 적합한가?

이 두 연산자를 사용하면 다음과 같은 장점이 있습니다:

  1. 안전한 Null 처리
    •   ?. 연산자를 통해 객체가 null인지 여부를 매번 확인하는 반복적인 코드를 줄일 수 있습니다.
  2. 간결한 코드
    •   ?: 연산자를 사용하면 if-else 문 없이 null 처리와 기본 동작을 한 번에 정의할 수 있습니다.
  3. 가독성 향상
    •   한눈에 "마커가 존재하지 않으면 새로 추가한다"는 로직을 이해할 수 있습니다.

비슷한 코드 없이 작성했다면?

아래는 동일한 기능을 if-else로 작성한 예입니다.

if (destinationLocationLabel != null) {
    destinationLocationLabel.moveTo(newLatLng)
} else {
    destinationLocationLabel = map?.labelManager?.layer?.addLabel(
        LabelOptions.from(newLatLng)
            .setStyles(
                setPinStyle(this, R.drawable.marker_destination)
            )
            .setTexts(LabelTextBuilder().setTexts("도착"))
    )
}

 

 

  •  위 코드는 동작은 동일하지만, if-else로 인해 가독성이 떨어지고 코드가 길어집니다.
  •  Kotlin의 ?. 연산자와 ?: 연산자를 사용하면 이러한 문제를 해결할 수 있습니다.

 

반응형