Kotlin

[Kotlin] 싱글톤 패턴(Singleton Pattern), @JvmStatic, Object Class

KyungMin08 2024. 12. 5. 10:45
728x90

개요

Kotlin에서는 자바의 static 키워드와 new 키워드가 없다고 들었다. 그런데 어떻게 static과 같은 기능을 구현할까? 라는 궁금증에 포스팅해본다.


싱글톤 패턴이란?

싱글톤 패턴은 어떤 클래스의 인스턴스가 오직 하나임을 보장하며 애플리케이션 시작부터 종료까지 고정된 메모리 영역을 가진다. 이로 인해 메모리를 효율적으로 사용할 수 있다. 하위 레이어들이 인스턴스를 참조하여 사용하는 방식이고 하나의 인스턴스만 필요할 때 사용한다.

 

자, 그럼 이런 싱글톤 패턴은 왜 사용할까? 정해진 메모리 영역을 사용하기 때문에 해당 객체에 접근할 때 메모리 낭비를 방지할 수 있다. 여러 메모리 영역에 똑같은 인스턴스가 생기는 것을 방지할 수 있으며 전역 인스턴스이기 때문에 공유(static)가 쉽다. 즉, 메모리 낭비 방지와 메모리 영역을 공유해 사용하기 때문에 많은 인스턴스를 생성할 이유가 없어진다.

만약 사용자가 1초에 20번 똑같은 요청을 보내면 요청을 처리하기 위해서 똑같은 객체를 20번 생성하게되고 이렇게 되면 메모리 낭비를 초래하게 된다. 싱글톤 패턴을 사용하면 인스턴스를 공유할 수 있기 때문에 메모리 낭비가 없어지는 장점이 있다.

 

순수 Java로만 싱글톤 패턴을 구현한다면 아래와 같이 만들 수 있다.

private으로 접근을 막고 new 키워드로 인스턴스를 생성한다. 앞으로 이 클래스의 getInstance() 메소드를 사용하면 Singleton 클래스에 private으로 생성된 인스턴스만 사용하게 된다. 왜냐하면 메모리 영역에 고정적으로 생성되었기 때문이다. static 키워드를 활용해서 인스턴스를 전역적으로 공유하면 new 키워드를 사용해 다른 인스턴스를 만들 필요가 없어진다.

 

왜 static final로 선언했냐하면 일단 final은 최종적인, 수정 불가능이라는 의미이고, 거기에 static 키워드를 붙여 메모리에 1번만 생성하여 모든 곳에서 공유될 수 있도록 하기 위해서이다. 즉, 객체 생성 없이 접근이 가능하고 수정이 불가능하다라는 의미로 선언했다.

 

하지만 Kotlin에서는 static 키워드가 없어서 companion object 또는 object class를 사용해서 static과 비슷하게 구현한다. static과 관련해서 Kotlin에서 제공하는 @JvmStatic 어노텐션이 존재한다. 이 어노텐션으로 static과 똑같은 기능을 구현할 수 있다.


object

object class는 자바의 static과 new 키워드를 대신한다. 객체를 선언과 동시에 인스턴스가 생성된다. 간단히 말하자면 싱글톤 패턴이다. object는 아래와 같이 선언한다.

object class 사용 예시 코드

자바의 static 메소드 또는 static 필드와 동일하게 사용할 수 있는 것을 볼 수 있다. ( private으로 선언된 필드와 메소드는 당연히 안되고 )

object class는 외부에서 선언되며 object class에 선언된 프로퍼티나 함수는 클래스명.(함수 / 프로퍼티)로 호출 가능하다.

object는 접근 시점에서 하나의 인스턴스가 생성되므로 생성자가 없는 클래스에서만 사용할 수 있다.

 

이러한 장점들이 있음에도 불구하고 단점이 존재한다. 애플리케이션 시작시 인스턴스가 생성된다는 점이다. 이로 인해 발생할 단점으로는 해당 object 클래스를 사용하지 않아도 메모리상에 올라간다는 단점이 있다. ( 메모리를 낭비하는거니까 좋진 않겠죠? )


companion object

companion object는 자바의 static 키워드를 대신하며 여러 개의 객체를 생성할 수 있지만 클래스의 메모리 주소 값은 동일하다.

클래스 내부에서만 선언되며 companion object 내부에 선언된 프로퍼티나 함수들은 클래스명.객체명.(함수 / 프로퍼티)로 접근이 가능한데 객체명은 생략 가능하다. 참고로 인터페이스(Interface)나 클래스(Class), 추상 클래스(abstract class) 모두 상속 받을 수 있다.

companion object 사용 예시 코드


@JvmStatic

@JvmStatic 어노텐션은 컴파일 했을때 자바의 클래스 내부에 static 메소드나 필드가 있게 만들 수 있다. 결론부터 말하자면 결국엔 자바의 static처럼 사용하기 위함이다. 다만, companion object는 컴파일 했을때 companion이라는 객체 안에 필드나 메소드가 있었는데 @JvmStatic 어노텐션을 사용하면 컴파일 했을때 클래스 내부에 static 필드나 메소드가 만들어진다. @JvmStatic 어노텐션은 companion object와 유사하지만 사실 좀 다르다.

Java 코드로 Decompile된 Kotlin 코드

(눌러서 봐주세요. 더 잘보입니다.)

위 사진에서 @JvmStatic 어노텐션이 선언된 프로퍼티는 StaticClass 내부에 선언되고, @JvmStatic 어노텐션을 선언하지 않은 getSimple() 함수는 StaticClass/Companion 내부에 선언된 것을 볼 수 있다. 또한 클래스 내부 뿐만 아니라 Companion 객체 내부에도 Getter / Setter가 생성된 것을 볼 수 있다.

이 코드를 자바 코드로 디컴파일하면

위와 같이 바뀐다.


총 정리하자면 object는 싱글톤 패턴을 만들때 사용하고 companion object와 @JvmStatic 어노텐션은 자바의 static을 구현할때 사용한다.

 

잘못된 부분이나 부족한 부분이 있을 수 있습니다. 댓글로 남겨주시면 감사하겠습니다. ☺️

728x90