코틀린 기반으로 쓰여짐


 

기사 시험을 공부하다보면 싱글톤 패턴이라는 것을 만나게 된다.

사실 처음 기사시험을 공부할때나 학과 공부를 할때 이게 그래서 왜 필요한데에 관한 의문을 정말 많이 가졌다.

안드로이드를 공부하다보니, 자원의 효율적인 사용을 고민하게 되었고 그 결과 싱글톤 패턴이 왜 필요한지 어느정도 감을 갖게 되었다.

 

 

1)싱글톤 패턴이란?

  • 어떤 클래스의 인스턴스가 하나임을 보장하는 전역에서 접근 가능한 디자인 패턴
  • 처음부터 끝까지 한 번의 인스턴스를 생성함으로서 메모리의 효율적인 사용을 가능하게 함

 

2)왜 필요한데?

 

사실 왜 필요한지가 잘 납득이 안되어서 처음에는 이해가 잘 안되었다. 클래스의 인스턴스가 하나임을 보장하면 뭘 할 수 있는가에 관한 의문이 들었기 때문이다. 쉽게 얘기하면 데이터 베이스를 수정할 수 있는 인스턴스가 여러가지라면 어떨까? 당연히 문제가 생길것이다. 그러한 연유로 싱글톤 패턴을 사용한다.

 

3)어떻게 사용해?

 

이를 고민하기 전에 좀 더 익숙한 자바 코드로 한번 보자.

 

public class DBHelper {
	private static DBHelper instance;
    
    private DBHelper() {}
    
    public static DBHelper getInstance() { 
    	if(instance ==null) {
        	instance = new DBHelper();
        }
        return instance;
    
    }
    
 }

 

외부에서 인스턴스 못만들게 private으로 만들어 놓고

인스턴스가 있으면 그냥 리턴해주고 없으면 만들어서 리턴해준다. 즉 인스턴스가 무조건 하나 밖에 만들어 질 수 없는 구조이다

이를 코틀린에서는 object라는 키워드로 간단하게 지원해 준다. 

https://developer.android.com/reference/java/lang/Object

 

Object  |  Android Developers

android.net.wifi.hotspot2.omadm

developer.android.com

 

object DBHandler {}
val dbHandler = DBHandler

 

참 간단하다. 이를 통한 싱글톤 패턴의 구현은 문제가 있다.

 

1)파라미터가 없는 인스턴스만 생성이 가능하다.

 

2)메모리 낭비가 심하다.

 

1번은 뭐 이해되는데 2번은 무슨말이냐?

자바 코드의경우 getInstance()가 실행될때 인스턴스가 만들어진다. 그에 비해 아래 코틀린은 프로세스가 시작 될 때 만들어진다.

즉 인스턴스를 쓰지 않고 있을때도 만들어진다는 것이다. 

우리는 두가지 문제를 해결해볼 것이다

 

1)

class DBHandler private constructor(context:Context) {
	companion object {
    	private var instance : DBHanlder? = null
        
        fun getInstance(context:Context) =
        	instace ?: DBHandler(context).also {
            	instance = it
            }
    }

}

 

1번 문제는 간단하게 해결 할 수 있다.

그냥 구현하면 된다. 자바의 코드와 동일한 효과를 낸다.

근데 여기서 우리는 하나의 모르는 키워드를 하나 더 만나게 된다.

companion object 가 뭐지?

 

1-1) companion object vs object

 

앞서 얘기했듯이 object 키워드는 싱글톤 패턴을 만들어 준다.

근데 코틀린에서는 static 키워드를 지원하지 않는다.  그래서 클래스 인스턴스 없이 함수의 내부에 접근하고 싶을때 companion object를 쓴다

 

2)

이 역시 lazy 키워드를 통해 간단하게 해결 가능하다.

class DBHelper private constructor() {
	companion object {
    	val instance:DBHelper by lazy {~~~~~}
    }

}

 

4)또 다른 문제가 생겼어

 

위에서 구현한 싱글톤 패턴의 또 다른 문제가 있다. 쓰레드가 하나일 때만 쓰레드 세이프를 보장한다는 거다.

즉 쓰레드가 동시에 인스턴스를 생성하는 경우에는 여러개의 인스턴스가 만들어 질 수 있다는 것이다.

 

 

class DBHandler private constructor (context:Context) {
	companion object {
    
    @Volatile
    private var instance:DBHandler?= null
    
    fun getInstance(context:Context) =
    instacne?:synchronized(DBHelper::class.java) {
    	instance ?: DBHandler(context).also {
        	instance = it
        }
    
    }
    
    }


}

 

위와 같이 구현이 가능하다. null check를 두번 함으로써 thread-safe를 보장한다.

4-1)근데 Volatile 이 뭔데

휘발성이 있는 뭐 이런뜻인거 다 알긴아는데 저게 무슨 키워든데?

이는 구조를 좀 알아야한다

일반적으로 쓰레드는 메인메모리에 접근할때 내부 성능향상을 위해 cpu캐시에 저장하게 된다.

근데 쓰레드가 두개 이상이라면 쓰레드 간의 접근 시간의 차이로 이미 인스턴스가 만들어졌음에도 cpu에 이를 전달하지 못하여

다른 쓰레드가 또 인스턴스를 만들게 된다. 이를 방지하기 위한 키워드로, 메인 메모리로부터 읽어온 값을 캐시에 저장하지 않고 

메인메모리에 바로 저장한다.

 

근데 이 방법이 찾아보니까 여러가지 말이 많은거 같다

https://herdin.github.io/2020/12/25/about-double-check-locking

 

Epu Baal – developer from pamukkale

developer from pamukkale

herdin.github.io

 

대부분의 경우 holder를 통해 이를 보강하긴 하는데 이는 말이 많은거 같다. 본인이 선택해야 할 문제이다.

 

 


참고

https://jaejong.tistory.com/105

 

[Kotlin] 코틀린 기본 - object / Companion Object(동반 객체)

Kotlin - object 키워드 + Companion Object (동반 객체) Kotlin object 키워드 object는 흔히 JAVA에서 사용하는 무명 내부 클래스(anonymous inner class) 처럼 사용할 수 있습니다 object 키워드는 클래스를..

jaejong.tistory.com

https://herdin.github.io/2020/12/25/about-double-check-locking

 

Epu Baal – developer from pamukkale

developer from pamukkale

herdin.github.io

https://www.charlezz.com/?p=45959 

 

코틀린/자바의 volatile에 대해서 | 찰스의 안드로이드

volatile이란? 자바의 volatile 키워드 또는 코틀린의 @Volatile 애노테이션을 변수 선언시 지정할 수 있다. 사전적 의미로는 '휘발성의'라는 뜻을 가지며, 변수 선언시 volatile을 지정하면 값을 메인 메

www.charlezz.com

https://kotlinworld.com/166

 

[Kotlin] object 를 이용한 싱글톤 패턴 구현

개발을 하다보면 객체에 대한 하나의 인스턴스만 필요할 때, 하나의 인스턴스를 재사용하기 위해 싱글톤 패턴을 구현해야 할 일이 생긴다. *싱글톤 패턴 : 객체의 인스턴스를 1개만 생성하여 계

kotlinworld.com

https://www.inflearn.com/course/알기쉬운-modern-android

 

냉동코더의 알기 쉬운 Modern Android Development 입문 - 인프런 | 강의

이 강의의 목적은 Android Jetpack을 중심으로 한 안드로이드 라이브러리의 동작 원리를 이해하고 앱에 적용하는 법을 알기 쉽게 전달하는 것입니다., - 강의 소개 | 인프런...

www.inflearn.com

 

+ Recent posts