한 줄 정의
타입을 생략할 수 있다고 해서 생략하라는 뜻은 아니므로, 문맥상 타입이 자명하지 않거나 공개 API라면 타입을 명시해야 합니다.
쉽게 말하면
택배 상자에 “보내는 물건: 상자 안에 있음”이라고만 적으면 받는 사람은 매번 열어 봐야 알 수 있습니다.
val num = 10 처럼 상자가 투명하면 라벨이 없어도 되지만, val data = getSomeData() 처럼 불투명한 상자라면 라벨(타입)을 붙이는 쪽이 모두의 시간을 아껴 줍니다.
왜 중요한가?
타입이 코드에서 안 보이면 읽는 사람은 함수 정의로 점프해야 하고, 그 함수도 추론에 기대고 있으면 계속 파고들어야 합니다.
GitHub PR 리뷰처럼 구현부로 이동할 수 없는 환경에서는 아예 확인할 방법이 없습니다.
더 큰 문제는 안전성입니다. 추론된 타입은 구현이 바뀌면 조용히 함께 바뀌므로, 공개 API라면 그 변경이 컴파일 에러 없이 외부 사용자에게 그대로 전파됩니다.
핵심 내용
가독성: 자명하지 않으면 명시
| 상황 | 예시 | 판단 |
|---|---|---|
| 리터럴·생성자로 타입이 드러남 | val ids = listOf(12, 112, 554, 997) | 생략 |
| 함수 반환값이라 타입이 안 보임 | val data = getSomeData() | val data: UserData = getSomeData() 로 명시 |
타입은 개발자와 컴파일러 모두에게 중요한 정보이고, 명시하는 비용은 거의 없습니다.
안전성: 추론은 항상 가장 구체적인 타입을 고른다
open class Animal
class Bear : Animal()
class Camel : Animal()
fun main() {
var animal = Bear()
animal = Camel() // 에러: 타입 불일치
}animal 의 추론 타입은 Animal 이 아니라 Bear 입니다. 이 성질 때문에 공개 API의 반환 타입이 의도치 않게 좁아질 수 있습니다.
interface CarFactory {
fun produce(): Car
}
val DEFAULT_CAR: Car = Fiat126P()누군가 DEFAULT_CAR 가 Car 이니 fun produce() = DEFAULT_CAR 로 줄이고, 이어서 다른 사람이 val DEFAULT_CAR = Fiat126P() 로 타입을 지웠습니다.
두 변경 모두 그 자체로는 무해해 보이지만, 합쳐지면 produce() 의 반환 타입이 Fiat126P 로 좁아져 모든 공장이 Fiat126P 만 생산할 수 있게 됩니다.
내부 코드라면 금방 발견되지만 외부에 노출된 API라면 사용자 쪽에서 먼저 깨지고 나서야 알게 됩니다.
공개 API의 범위
외부 모듈이 쓰는 요소뿐 아니라, 다른 개발자가 유지보수하는 코드에서 쓰이는 내부 요소도 포함합니다. 라이브러리라면 모든 public·protected 클래스, 함수, 객체 선언이 해당합니다.
명시적 API 모드 (Kotlin 1.4+)
공개 API에 타입과 가시성 한정자(visibility modifier)를 명시하도록 컴파일러가 강제하는 기능입니다.
kotlin {
// 엄격 모드: 누락 시 컴파일 에러
explicitApi()
// 경고 모드: 누락 시 경고만
explicitApiWarning()
}위의 CarFactory 같은 실수를 사람 대신 빌드가 막아 줍니다.
내 생각
- 공개 함수의 반환 타입은 항상 명시합니다. 표현식 본문(
= ...)으로 줄이는 리팩터링이 반환 타입을 조용히 바꾸는 가장 흔한 경로라, 리뷰 규칙으로 두면 비용 대비 효과가 큽니다. - 멀티모듈 프로젝트의 공유 모듈에는
explicitApiWarning()부터 켜 볼 만합니다.common·domain모듈은 사실상 다른 팀이 쓰는 공개 API라, 경고로 시작해 정리 후 엄격 모드로 올리는 편이 부담이 적습니다. - 로컬 변수는 IDE inlay hint에 기대지 않는 기준으로 판단합니다. 에디터에선 타입이 보여도 PR diff에선 안 보이므로, “리뷰어가 diff만 보고 알 수 있는가”를 기준으로 삼습니다.
관련 개념
- 아이템 03 가능한 한 빨리 플랫폼 타입을 제거하라 — 플랫폼 타입을 명시적 타입으로 바꾸는 것도 같은 이유(가독성·안전성)에서 출발합니다