싱글톤 패턴(Singleton Pattern)이란?
싱글톤은 애플리케이션 상 특정 클래스가 최초 한 번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 디자인 패턴을 의미한다. 객체 생성 요청이 여러번 발생하더라도 새롭게 메모리를 할당하여 인스턴스를 만드는 것이 아닌 기존에 생성되어 있던 인스턴스를 참조하는 것이다.
싱글톤 패턴을 사용한다면 불필요한 메모리 사용을 줄일 수 있다는 장점이 있다.
JVM에서의 싱글톤
JAVA에서 인스턴스를 생성할 때에는 new 키워드와 함께 생성자를 사용한다. 그러므로 클래스를 싱글톤으로 만들려면 외부에서 생성자를 호출할 수 없게 private으로 만들어줘야 한다.
// Java
public final class SingleTonTest {
@NotNull
public static final SingleTonTest INSTANCE;
private SingleTonTest() {
}
static {
SingleTonTest var0 = new SingleTonTest();
INSTANCE = var0;
}
}
코틀린에서는 object 키워드로 쉽게 싱글톤을 구현할 수 있다. 이 둘은 완전히 동일한 코드이다.
// Kotlin
object SingleTonTest {
}
하지만 생성자를 public으로 만듦에 따라 싱글톤이 보장되지 않을 수 있는 가능성이 있다.
생성자가 무조건 private이고, 실수하지 않는다고 보장한다면 괜찮은 것 아닌가? 물을 수 있는데.. Reflection으로 접근한다면 말이 달라진다. Reflection을 이용한다면 생성자의 visibility를 변경할 수 있다.
// Kotlin
val constructor = SingleTonTest::class.java.getDeclaredConstructor()
constructor.isAccessible = true
val instance = constructor.newInstance()
private 생성자였지만 Reflection을 이용해 public(accessible = true)으로 바꾸어 객체를 생성한 것이다.
그럼 enum은 어떨까?
enum class와 싱글톤
우선 enum class는 외부에서 인스턴스화 할 수 있는 생성자 자체가 없다. 다만, 내부에서 관리되는 상수를 생성하는 생성자는 존재한다.
// Java
enum EnumTest {
Number("number");
private final String identifier;
public final String getIdentifier() {
return this.identifier;
}
private EnumTest(String identifier) {
this.identifier = identifier;
}
}
// Kotlin
enum class EnumTest(
private val identifier: String
) {
Number("number");
}
그럼 Reflection으로 enum class의 인스턴스를 생성하려 시도한다면 어떻게 될까?
val enum = EnumTest::class.java
val constructors = enum.getDeclaredConstructor()
constructors.isAccessible = true
val instance = constructors.newInstance()
getDeclaredConstructor 단계에서 기본 생성자를 찾을 수 없다며 NoSuchMethodException이 발생하며, 그 외에도 newInstance 시점에 ENUM이라면 IllegalArgumentException을 발생시키는 부분도 존재한다.
결국 enum -> getConstructor -> newInstance로 사용하는 객체 생성 flow가 적용되지 않기 때문에 외부에서 임의로 enum class와 관련된 인스턴스를 생성하는 것은 불가능하며 완벽한 싱글톤이라고 부를 수 있다.
☕️ Networking
기술 직군의 기술적인 교류, 커리어 이야기, 직군 무관 네트워킹 모두 환영합니다!
위클리 아카데미 오픈 채팅방(비밀번호: 9323)
kakaotalk: https://open.kakao.com/o/gyvuT5Yd