본문 바로가기

Kotlin/안전성, 가독성을 효과적인 향상시키는 사용법

👋Kotlin : 4️⃣Inferred(추론된) 타입으로 리턴하지 말라

728x90

코틀린은 2010년에 처음 개발되었지만 2016년 2월에 첫 번째 안정 버전(stable version)이 공식적으로 배포되었을 정도로 굉장히 오랜 시간 동안 만들어지고 있고, 처음부터 대규모 애플리케이션을 실용적으로 만들기 위한 프로그래밍 언어로 설계되었고 현재는 모바일 애플리케이션, 웹 애플리케이션의 백엔드, 웹 애플리케이션의 프론트엔드 등 다양한 영역에서 활용되고 있습니다.

 

4️⃣ Inferred 타입 제한

코틀린의 타입 추론(type inference)은 코틀린의 특징 중 하나이지만 타입 추론을 사용할 때는 몇 가지 위험한 부분들이 있기 때문에 잘 못 사용해선 안됩니다.

 

이러한 위험을 피하기 위해선 할당 시 inferred 타입은 절대로 슈퍼클래스 또는 인터페이스로 설정되지 않고 할당하려는 값에 맞게 설정됩니다.

아래 예제를 확인해보면 위에서 말했듯이 inferred 타입인 food는 Steak 타입으로 타입 추론이 되었기 때문에 슈퍼클래스인 Food 타입을 할당할 수 없습니다.

open class Food
class Steak: Food()

fun main() {
	var food = Steak()  	// Type : Steak
        food = Food()		// 오류 : 타입의 불일치
}

 

 

만약 원하는 Food 타입 보다 제한된 Steak 타입이 설정되어있으니 타입 불일치가 발생하는 것은 당연합니다. 이를 Food 타입을 명시적으로 지정해주면 간단히 해결됩니다.

open class Food
class Steak: Food()

fun main() {
	var food: Food = Steak()  	// Type : Food
        food = Food()     		// Type : Food
}

 

그리고 inferred 타입을 노출하면, 잠재적으로 오류를 불러올 수 있습니다. inferred 타입의 노출에 위험성에 대한 간단한 예를 들어보겠습니다. 

val DEFAULT_FOOD : Food = DEFAULT()

interface Kitchen {
    fun cook() : Food = DEFAULT_FOOD
}
   .. 생략 ..

 

위 예제를 확인해보면 기본으로 생성되는 식품을 DEFAULT를 반환하도록 했는데, DEFAULT_FOOD는 Food 타입으로 명시되어 있으니 필요없다고 생각되어 아래처럼 수정했다고 생각해봅시다.

val DEFAULT_FOOD : Food = DEFAULT()

interface Kitchen {
    fun cook() = DEFAULT_FOOD	// <-- 수정된 부분
}

open class Food: Kitchen {
    override fun cook() = this
}

class DEFAULT : Food()
class Pasta : Food()

fun main() {
    val defaultFood1 = Pasta().cook()
    val defaultFood2 = DEFAULT().cook()
    println(defaultFood1)
    println(defaultFood2)
}

 

이후에 다른 사람이 코드를 보다가, DEFAULT_FOOD는 타입 추론에 의해 자동으로 타입이 지정될 것이라고 생각하고 아래와 같이 수정하게되면 Kitchen 인터페이스는 DEFAULT 이외의 식품을 만들 수 없고 오류가 발생합니다.

val DEFAULT_FOOD = DEFAULT()	// <-- 수정된 부분

interface Kitchen {
    fun cook() = DEFAULT_FOOD
}

 

인터페이스를 직접 만들었다면 해당 문제를 쉽게 찾아 수정할 수 있겠지만 이러한 문제가 외부 API에서 발생한다면 해결하기도 힘들고 사용하고 있는 개발자 입장에선 답답하겠죠. 따라서 리턴 타입은 외부에서 확인할 수 있게 명시적으로 지정해 주는 것이 좋습니다.

 

inferred 타입을 사용하면 프로젝트의 진전에 제한이 생기거나 예측하지 못한 결과를 낼 수 있으니 타입을 확실하게 지정해야 하는 경우에는 명시적으로 타입을 지정해야 한다는 원칙을 잊지말아야 합니다.