아이템 3. 최대한 플랫폼 타입을 사용하지 말라

자바는 코틀린과 달리 null-safety 메커니즘이 없다. 따라서 자바의 String 타입을 코틀린에서 사용할때 @Nullable 어노테이션이 붙어 있으면 String? 타입으로, @NotNull 어노테이션이 붙어있으면 String 타입으로 변경하면 된다.

하지만 아무런 어노테이션이 없다면 체크가 까다롭다. 그래서 코틀린에서는 다른 언어에서 넘어온 타입을 특수하게 다루는데 이러한 타입을 플랫폼 타입(platform type) 이라고 한다. 플랫폼 타입은 String!처럼 타입 뒤에 !를 붙여서 표기한다.

val repo = UserRepo()
val user1 = repo.user // user1은 User! 타입
val user2: User = repo.user // user2는 User 타입
val user3: User? = repo.user // user3는 User? 타입

위와 같이 선택적으로 사용할 수 있는데, null이 아니라고 생각한 것이 null일 수 있기 때문에 플랫폼 타입을 사용할 땐 주의해야 한다. 자바 코드를 조작할 수 있다면 @Nullable@NotNull 어노테이션을 붙이는 것이 좋다.

또한 플랫폼 타입은 최대한 빠르게 제거하는 것이 좋다.

// 자바
public class JavaClass {
  public String getValue() {
    return null;
  }
}

// 코틀린
fun statedType() {
  val value: String = JavaClass().value // 타입 명시 -> NPE
  print(value.length)
}

fun platformType() {
  val value = JavaClass().value // 타입 명시 x
  print(value.length) // NPE
}

statedType() 에선 값을 가져오는 위치에서 NPE가 발생하지만 platformType() 에선 사용하는 위치에서 NPE가 발생한다. 이 경우 여러번 호출 되면서 문제가 되지 않는 경우도 있기 때문에 오류를 추적하는데 시간이 오래 걸린다.

또한 인터페이스의 경우 구현하는 클래스에서 null 여부를 지정할 수 있기 때문에 문제가 될 수 있다.

interface UserRepo {
  fun getUserName() = JavaClass().value
}

class RepoImpl: UserRepo {
  override fun getUserName(): String? {
    return null
  }
}

이 경우 사용하는 사람이 null이 아닐거라고 받아들일 수 있기 때문에 문제가 될 수 있다. 이처럼 플랫폼 타입이 전파되는 것은 위험하기 때문에 제거하는 것이 좋다.

정리

  • 다른 프로그래밍 언어로 구현되어 null 여부를 알 수 없는 타입을 플랫폼 타입이라고 한다.

  • 플랫폼 타입은 해당 부분 뿐만 아니라 이를 활용하는 부분도 문제가 될 수 있기 때문에 제거하는 것이 좋다.

Last updated