개발자로서 살아남기/Kotlin

현업에서 사용되는 코틀린 정복하기 - companion object 와 @JvmStatic

코드 살인마 2025. 9. 5. 17:03
728x90

개요

이직 한 후, 배울께 천지 삐까리다.

일단 제일 급한 건 코틀린이고, 그 다음은 리액트이다.

4년전쯤 전회사의 신입으로 들어가, 모르는 부분들을 정리하여 포스팅 했던 기억이 있는데, 그때 기억을 되살려, 앞으로 자주 포스팅 할 예정이다.

companion object

  • 클래스 안의 싱글턴인 네임스페이스 자바의 static 메소드와 비슷한 역할을 한다. 인스턴스 생성 없이 사용할 수 있다.
class ClassName {
    companion object {
    const val property: String = "Something..."
    fun funName() {
        // ...
        }
    }
}

위와 같은 코드는 propertyfunNamestatic 하게 사용할 수 있다.

@JvmStatic

  • JAVA에서 진짜 static 처럼 보이게 해주는 브릿지 어노테이션

언제 쓰는가?

Kotlin-only 프로젝트면

  • 그냥 companion object 또는 object/탑레벨 함수로 충분. @JvmStatic 불필요하다.
  • Java 호출자(또는 라이브러리 사용자)가 있다면*
  • Java가 MyClass.myStatic()처럼 정적 호출하길 원하면 @JvmStatic을 붙이세요.
  • 상수는 @JvmField(필드 노출) 또는 const val(컴파일타임 상수)로 내보내세요.

즉 자바와 코틀린이 혼용된 프로젝트에서 static 함수를 사용하기 위해 사용된다.

예시

class User private constructor(
    val id: Long,
    val name: String
) {
    companion object {
        @JvmStatic
        fun fromJson(json: String): User {
            // ... parse & validate
            return User(id = 1L, name = "Alice")
        }
    }
}

Kotlin:

val u = User.fromJson(payload)

Java:

User u = User.fromJson(payload); 
// @JvmStatic 덕분에 진짜 static 호출 
// (없으면 User.Companion.fromJson(payload))

그외 생각해야할 부분

  • 바이트코드 관점
    • @JvmStatic정적 메서드를 추가로 생성(원본 Companion 멤버도 유지). 따라서 메서드가 중복 생성되며, 바이트코드 용량이 아주 약간 늘 수 있음. 꼭 필요한 공개 API에만 붙여야 한다.
  • 초기화 타이밍
    • companion object 초기화는 최초 접근 시점에 한 번. 무거운 초기화는 lazy{} 등으로 분리해야한다.