[Kotlin/디자인 패턴] 싱글톤 패턴에 대하여

왕왕조현·2026년 3월 21일

kotlin

목록 보기
2/8
post-thumbnail

안녕하세요!

개발에 대한 이해도를 높이고자 공부하는 개발자 꿈나무 김조현입니다.

오늘은 싱글톤 패턴에 대한 정리글을 써보겠습니다.

왜 공부하는가?

왜 이걸 공부하냐? object가 싱글톤 패턴이며, enum 객체또한 마찬가지로 싱글톤 패턴이며, 클래스 내에서 companion object를 사용해도 그 객체가 싱글톤 패턴을 가진다고 어디선가 듣고 사용해봤다.

하지만 문법도 알고 쓰는 방법도 알지만 왜 쓰는지를 모른다. 결국 근본적으로 싱글톤 패턴이 무엇인지 알아야 이런 문법과 활용을 잘 할 수 있지 않을까? 라는 생각이 들어 싱글톤 패턴에 대해 공부하고자 마음을 잡았다.

싱글톤 패턴은 무엇인가?

싱글톤은 클래스에 인스턴스가 하나만 있도록 하면서 이 인스턴스에 대한 전역 접근 지점을 제공하는 생성 디자인 패턴이다. 즉, 쉽게 말하면 클래스의 객체를 한개만 생성해서 그 객체만을 사용하는 것이다.

싱글톤 패턴의 큰 장점 중 하나는 해당 인스턴스에 대한 전역 접근 지점을 제공하는 것이다. 그치만 전역 접근을 제공하는 것이라면 코틀린의 경우 객체를 전역 변수로 지정하면 되는 것이 아닌가? 라는 의문이 들 수도 있다.

필수 객체들을 전역 변수로 정의했다고 가정했을 때, 이 변수들의 사용이 편해질 수 있지만 모든 코드가 잠재적으로 해당 변수의 내용을 덮어쓸 수 있다는 위험이 존재한다. 싱글톤 패턴은 전역 변수와 마찬가지로 모든 곳에서부터 일부 객체에 접근할 수 있지만, 이 패턴은 다른 코드가 해당 인스턴스를 덮어쓰지 못하도록 보호한다.

싱글톤 패턴의 장점

  • 하나의 인스턴스로 관리하니 클래스의 데이터의 공유가 쉽다.
  • 하나의 인스턴스만을 사용함으로서 메모리 리소스를 줄일 수 있다는 장점이 있다.
  • 처음 로딩 이후 추가적인 세팅이나 로딩을 필요로 하지 않기 때문에 초기화 부분의 생략이 가능하다.

싱글톤 패턴의 단점

  • 싱글톤 패턴은 하나만 생성되어야 하지만 멀티스레드 환경에서 1개만 생성된다는 것을 보장할 수 없다.
  • 자기 자신의 생성자를 private로 두었기 때문에 상속을 받는 것에 어려움을 가지게 된다.
  • 싱글톤으로 만들어지는 클래스의 경우 기본적으로 자기 자신의 인스턴스를 관리하는 역할과 작업을 처리하는 2가지의 역할을 맡게 되므로 객체 지향의 5원칙 중 하나인 단일 책임 원칙을 위반한다.

그럼 언제 사용하는가?

  • 초기에 넣어야 할 데이터가 없을 때
  • 데이터의 변경이 자주 일어나지 않을 때
  • 독립적으로 호출할 수 있는 메소드 및 필드가 있는 클래스

그러면 멀티스레드에서는 싱글톤 패턴을 사용할 수 없는가?

아니다. 사용할 수 있다. 문제점이 있지만 이를 해결하는 다양한 방법이 있지만 다루지는 않겠다. (아직 필요성을 느끼지 못했다)

object 키워드

코틀린에서 싱글톤 패턴을 선언할 수 있도록 예약된 키워드다. 객체 선언의 초기화는 스레드로부터 안전하며 처음 접근할 때 완료된다.

companion object 키워드

클래스의 인스턴스 없이 어떤 클래스 내부에 접근하고 싶다면 클래스 내부에 객체를 선언할 때 companion 식별자를 붙은 object를 선언하는 것이다. companion object는 클래스에서 한 개만 가질 수 있다.

companion object는 프로세스 시작 시 인스턴스가 생성되며 클래스가 사용되지 않아도 메모리상에 인스턴스가 계속 올라가있는 것이다.

공부하면서 생긴 궁금한 점

object나 companion object나 싱글톤 패턴을 구현하는 것이 같고 다른 점은 클래스 내에서 선언하냐의 차이 뿐인데 그렇다면 왜 굳이 클래스 내에서 선언을 해야하는가?

1. 클래스와의 관계를 나타내기 위해서 사용한다.

예를 들면 내가 작성한 이 코드와도 같다. Tag라는 클래스와 isTagError는 서로 관련이 있는 로직이기에 한 클래스에 묶는 것으로 사용할 수 있다.

2. 캡슐화와 관련이 있다.

companion object는 해당 클래스 내부에 정의되기 떄문에, 클래스의 private 생성자나 private 변수에 접근할 수 있다. 반면 obejct는 접근할 수 없다.

  • 제미나이 피셜) 팩토리 패턴이 companion object를 사용하는 예시

Cannot access 'constructor(name: String, age: Int): Person': it is private in 'org.example.Person'.

위 코드를 보면 companion object와 object가 어디에서 다른지 눈으로 확인할 수 있다. 먼저 private 생성자에 대한 객체를 만들고자 하는 person2를 보면 에러가 나타난다. 이는 생성자가 비공개여서 접근할 수 없어 발생하는 오류이며 object또한 마찬가지고 같은 오류가 나타난다.

하지만 companion object는 다르다. 같은 클래스 내에 있는 객체이기 때문에 가시성이 비공개여도 생성자에 접근할 수 있다.

즉, person2, person3은 가시성이 비공개인 생성자를 통핸 객체를 생성할 수 없지만 person4는 생성할 수 있게 되는 것이다.

결론

싱글톤 패턴이란 값을 가지지 않는 하나의 객체를 전역에서 다루고자 할 때 사용되는 디자인 패턴이며, 이 패턴을 사용했을 때는 메모리 상의 부담을 줄일 수 있고, 데이터를 전역에서 불러올 수 있다는 장점이 있다.

코틀린에서는 object와 companion object를 사용해 선언할 수 있으며 kotlin에서 사용하는 enum 클래스의 enum 객체 또한 싱글톤 패턴이 적용된 예시다.

부족한 부분이나 틀린 내용이 있다면 편하게 말씀해주시면 감사하겠습니다!

읽어주셔서 감사합니다!🙂‍↕️

📚 참고자료
https://refactoring.guru/ko/design-patterns/singleton

profile
천천히, 꾸준히, 한 걸음씩

0개의 댓글