Backend/Kotlin

[Kotlin] 코틀린에서 유틸함수 만들기

findmypiece 2021. 11. 24. 23:50
728x90

자바에서는 유틸성 함수를 만들 때 특정 클래스에 static 메소드를 정의해놓고 사용하곤 한다. 반복적으로 자주 사용되는 함수이기 때문에 별도의 객체 생성 단계 없이 메모리 상주시켜 사용하기 위함이다.

 

코틀린에서는 유틸성 함수를 만드는데 세 가지 방법을 제공하는데 object, companion object, top-level-function 를 활용한다. 우선 세 가지 방식 모두 자바로 디컴파일 해보면 static 자원이다.

 

top-level-function 은 자바에서 흔하게 사용하던 유틸 메소드와 같이 class 에 static 메소드로 정의된다. object, companion object 는 객체 자체가 static 변수에 할당되는데 모두 어플리케이션 실행시 클래스 로더에 의해 초기화 된다. 차이가 있다면 object 는 static 블럭에서 객체가 생성 되고 companion object 는 static 변수 선언 구문에 아예 객체 생성구문이 포함되어 있다.

 

즉, 모두 힙이 아닌 스태틱 메모리 영역에 생성되기 때문에 특별한 경우가 아니라면 gc되지 않고 어플리케이션과 생명주기를 함께 한다. 이에 어떤 방식을 사용하든 유틸 메소드를 만들기엔 적합한 방식이다. 

 

일단 코틀린에서 유틸 함수를 선언하는데 권장되는 방법은 top-level-function 인데 특정 모듈이나 컨텍스트에 종속적인 함수를 동일한 top레벨에 덩그러니 두는 게 애매할 때가 있다. 

 

이 때는 object 또는 companion object 를 선택해서 함수를 나눠서 관리하는게 낫다. 그렇다면 둘 중 어떤 걸 선택해야 할까?

 

이 둘의 차이는 object 는 해당 클래스의 객체 자체가 static 자원이 된다는 것이고 companion object 는 내부 클래스로 정의되어 있는 Companion 클래스만 static 자원이 된다는 것이다.

 

이에 object 와 달리 companion object 는 static, non static 함수가 공존할 수 있다. 바깥쪽 클래스에서 non static 자원을 정의할 수 있고 내부 클래스 특성상 바깥쪽 클래스에서 내부 클래스에 해당하는 companion object 의 자원에 자유롭게 접근할 수 있다.

 

때문에 연관된 유틸을 클래스 단위로 묶어서 생성하고 싶다면 object, companion object 를 고려하되 non static 자원도 함께 포함시켜야 한다면 companion object 를 사용하면 된다. 반대로 말하면 특별한 경우가 아니라면 object 를 사용하면 된다.

 

다만 엄밀히 따지고 보면 top-level-function는 함수가 static 이 되는 것이고 object / companion object 는 객체 static 변수에 할당되는 것이다. top-level-function 우리가 흔히 사용하던 유틸정의 방식이기 때문에 그와 동급으로 활용하면 되지만 object / companion object 를 활용할 때는 주의가 필요하다.

 

한 예로 @JsonCreator 를 생각해볼 수 있다. 이는 jackson 환경에서 클래스의 역직렬화 메소드를 지정할 때 사용되는 어노테이션으로 지정하는 메소드는 반드시 static 이어야 한다.

 

이에 companion object 를 선언해서 내부의 메소드에 @JsonCreator 를 선언해봐야 역직렬화할 때 해당 메소드는 사용되지 않는다. 위에서 말했듯이 companion object 는 내부 static 변수에 Companion 클래스의 객체가 할당될 뿐이기 때문이다. 

 

메소드 자체를 static 으로 만들기 위해서는 @JsonCreator 과 함께 @JvmStatic 를 정의하면 된다. 이 경우 바깥쪽 클래스의 static 메소드로 정의되어 우리가 의도한데로 동작할 수 있게 된다.

 

https://stackoverflow.com/questions/54862918/kotlin-top-levels-functions-vs-object-function
https://medium.com/@lunay0ung/kotlin-object-declaration-그리고-companion-object-feat-static-d5c97c21168
https://jaejong.tistory.com/105
https://stackoverflow.com/questions/59679479/do-companion-objects-remain-in-memory-for-apps-lifecycle
https://codechacha.com/ko/decompile-kotlin-to-java/
https://stackoverflow.com/questions/54052761/does-object-in-kotlin-get-garbage-collected
728x90

'Backend > Kotlin' 카테고리의 다른 글

[Kotlin] 제네릭(내가 필요한 것만 정리..)  (0) 2021.12.06
[Kotlin] inline  (0) 2021.12.06
[Kotlin] val, const val  (0) 2021.11.22
[Kotlin] companion object  (0) 2021.11.22
[Kotlin] 초기화 없이 속성을 선언하는 방법 lateinit  (0) 2021.11.05