|

코틀린 fun interface는 언제 좋을까: 함수 타입만 쓰면 안 되는 순간

코틀린 fun interface는 언제 좋을까: 함수 타입만 쓰면 안 되는 순간
함수 타입은 가볍고, fun interface는 이름 있는 계약을 남긴다

코틀린 fun interface는 함수 타입과 비슷해 보이지만 쓰임새가 다릅니다. 함수 하나만 받으면 되는 상황이라면 람다나 함수 타입이 더 간단합니다. 하지만 그 함수가 도메인 안에서 이름 있는 역할을 가져야 한다면 fun interface가 더 읽기 좋을 수 있습니다.

이 글에서는 SAM, 람다, 함수 타입, Java interop 관점에서 fun interface가 언제 좋은지 정리합니다. 전략을 함수로 바꾸는 감각은 Strategy 패턴과 함수형 대안 비교 글과도 이어집니다.

코틀린 fun interface 사용 기준을 정리한 요약 카드
함수 타입은 가볍고, fun interface는 이름 있는 계약을 남긴다

코틀린 fun interface는 무엇인가

fun interface는 추상 메서드를 정확히 하나만 가진 인터페이스입니다. Kotlin 공식 문서의 Functional interfaces 설명처럼, 이런 인터페이스는 SAM 변환을 통해 람다로 구현할 수 있습니다.

fun interface PricePolicy {
    fun discount(price: Int): Int
}

val noDiscount = PricePolicy { price -> price }
val tenPercentOff = PricePolicy { price -> (price * 0.9).toInt() }

겉으로 보면 함수 타입 (Int) -> Int와 비슷합니다. 하지만 PricePolicy라는 이름이 붙는 순간, 이 함수는 단순 계산 함수가 아니라 가격 정책이라는 계약으로 읽힙니다.


함수 타입만으로 충분한 경우

일회성 콜백, 정렬 기준, 간단한 변환 함수처럼 맥락이 짧고 지역적인 경우에는 함수 타입이 더 낫습니다. 이름 있는 타입을 만들면 오히려 코드가 무거워질 수 있습니다.

fun <T> List<T>.countBy(predicate: (T) -> Boolean): Int {
    return count(predicate)
}

여기서 predicate는 특정 도메인 계약이라기보다 일반적인 조건 함수입니다. 이런 경우는 함수 타입이 자연스럽습니다.


fun interface가 더 좋은 순간

1. 이름이 설계 의도를 설명할 때

같은 (Order) -> Boolean이라도 어떤 함수는 주문 승인 조건이고, 어떤 함수는 환불 가능 조건일 수 있습니다. 함수 타입만 보면 인자와 반환값은 보이지만 역할 이름은 사라집니다.

fun interface RefundRule {
    fun canRefund(order: Order): Boolean
}

class RefundService(
    private val rule: RefundRule,
) {
    fun refund(order: Order) {
        require(rule.canRefund(order))
        order.refund()
    }
}

2. Java와 함께 써야 할 때

Kotlin fun interface는 Java의 single abstract method 인터페이스 감각과 잘 맞습니다. Java API와 맞물리는 콜백이나 listener를 Kotlin답게 감쌀 때 유용합니다.

3. 계약이 앞으로 확장될 가능성이 있을 때

fun interface는 추상 메서드는 하나만 둘 수 있지만, 기본 구현 메서드나 문서화된 계약을 함께 둘 수 있습니다. 단순 함수 타입보다 설계 의도를 남기기 쉽습니다.


fun interface를 남용하면 생기는 문제

  • 모든 람다에 이름을 붙이면 타입이 너무 많아진다
  • 일회성 콜백까지 interface로 만들면 읽는 비용이 늘어난다
  • 함수 타입이면 충분한 곳에 계약 타입을 만들면 설계가 과해진다

그래서 기준은 단순합니다. 이 함수가 도메인에서 반복해서 등장하는 역할인가, 이름을 붙였을 때 코드가 더 잘 읽히는가를 보면 됩니다.


선택 기준

  1. 지역적이고 짧은 콜백이면 함수 타입을 쓴다
  2. 도메인 역할 이름이 중요하면 fun interface를 검토한다
  3. Java interop이나 SAM 변환이 중요하면 fun interface가 좋다
  4. 테스트 대역이나 정책 객체처럼 교체 가능한 계약이면 fun interface가 읽기 쉽다

핵심은 문법이 아니라 이름 있는 계약이 필요한지입니다. 함수 타입은 가볍고, fun interface는 의도를 남깁니다.


마무리

코틀린 fun interface는 함수 타입의 대체재가 아니라, 함수 하나짜리 계약에 이름을 붙이는 도구입니다. 단순 콜백은 함수 타입으로 충분하지만, 정책, 규칙, 전략처럼 의미 있는 역할이 반복된다면 fun interface가 더 좋은 선택이 될 수 있습니다.

함께보면 좋은 글