13. Extension Functions & Properties

확장 함수와 확장 프로퍼티

치트시트

  • 함수 선언: fun T.extName(...) { ... }

  • 프로퍼티 선언: val T.propName: Type get() = ...

  • this로 수신 객체 접근

  • private/protected 접근 불가

  • 멤버 함수 > 확장 함수 (우선순위)

  • 서버 개발 활용: DTO 변환, JPA Entity Helper, 문자열/컬렉션 유틸, DSL


1) 확장 함수 (Extension Function)

  • 문법: fun 수신객체타입.함수이름(...) { ... }

  • 함수 안에서 this는 확장 대상 객체를 가리킴

fun String.lastChar(): Char = this[this.length - 1]

println("Kotlin".lastChar()) // n
  • 내부적으로는 정적(static) 함수로 컴파일되며, 클래스 멤버를 수정하지 않음

  • 멤버 함수와 이름이 겹치면 멤버 함수가 우선


2) 확장 프로퍼티 (Extension Property)

  • 프로퍼티처럼 보이지만, 실제로는 getter 함수를 확장하는 것

val String.firstChar: Char
    get() = this[0]

println("Kotlin".firstChar) // K
  • backing field 없음 → 값을 저장하는 게 아니라 계산된 결과만 제공.


3) 캡슐화 보장

  • 확장 함수는 private / protected 멤버에는 접근 불가

  • 즉, 캡슐화를 깨뜨리지 않음.


4) 서버 개발 활용 패턴

A. DTO 변환기

fun User.toResponse(): UserResponse =
    UserResponse(id = this.id, name = this.name)

→ Controller 계층에서 user.toResponse()로 바로 변환.

B. String / Collection 유틸

fun String.toSlug() = lowercase().replace(" ", "-")
fun <T> List<T>.toCsv(): String = joinToString(",")

→ 데이터 직렬화/로그 포맷팅에 자주 활용.

C. JPA Entity Helper

fun Order.isCompleted() = this.status == OrderStatus.COMPLETED

→ 서비스 로직에서 가독성↑.

D. DSL 스타일 API

fun Route.healthCheck() {
    get("/health") { call.respond("OK") }
}

→ Ktor 같은 서버 프레임워크에서 라우팅 DSL 확장.


5) 주의사항

  • 정적 바인딩: 다형성(polymorphism)이 적용되지 않음

    • 변수의 정적 타입 기준으로 어떤 확장이 호출될지 결정됨.

  • 남용하면 코드 추적이 어려워짐 → 도메인 로직, 공통 유틸, DSL에 집중해서 사용.

Last updated