• Feed
  • Explore
  • Ranking
/
/
    Go

    Singleton Pattern(싱글톤 패턴) 구현하기

    Golang으로 singleton pattern 구현하기
    DevOpsGo
    A
    Antonio
    2025.03.10
    ·
    6 min read

    3845

    1. Singleton pattern(싱글톤 패턴)이란

    싱글톤(Singleton) 패턴은 애플리케이션 전역에서 ‘하나의 인스턴스’만 존재하도록 보장해 주는 디자인 패턴입니다. 객체가 여러 번 생성되는 것을 방지하고, 어디에서든 동일한 인스턴스에 접근할 수 있게 합니다.

    1.1 특징

    장점

    • 유일한 인스턴스 보장: 애플리케이션 전역에서 특정 구조체의 객체가 오직 하나만 존재하도록 보장합니다.

    • 전역적인 접근: 중앙에서 설정/상태 등을 관리하기에 용이하며 어디서든 싱글톤 객체를 불러와 동일한 상태를 공유할 수 있습니다.

    • 비용 절감: 리소스가 많이 드는 객체를 반복 생성할 필요가 없어, 메모리와 CPU 자원을 절약할 수 있습니다.

    단점

    • 전역 상태(Global State) 문제: 전역으로 공유되는 객체는 의존성 주입(Dependency Injection)이 어렵고, 모의(Mock) 테스트가 까다롭습니다.

    • 코드 유연성 저하: 한 번 싱글톤이 생성되면 객체 교체가 쉽지 않아, 구조 확장이나 변경 시 리팩토링 비용이 커질 수 있습니다.

    • 멀티스레드 동시성: sync.Once로 초기화 시점은 안전하게 보장할 수 있지만, 싱글톤 내부에서 관리하는 자료구조가 여러 고루틴에 의해 동시 업데이트될 경우, 별도의 뮤텍스(Mutex)나 동시성 제어가 필요

    1.2 활용 사례

    • 데이터베이스 연결 객체 (DB Connection Pool)

    • 로깅 시스템 (Logger)

    • 설정 파일 관리 (Configuration Manager)

    • 캐싱 시스템 (In-memory Cache)

    • 쓰레드 풀(Thread Pool) 관리

    2. Go에서의 Singleton

    Go는 전통적인 OOP 언어(C++, Java)와 다르게 ‘클래스(class)’ 개념이 없고, 구조체(Struct)와 패키지(package) 단위로 코드를 구성합니다. 그럼에도 불구하고, 전역적으로 유일한 객체를 제공해야 할 때 싱글톤 패턴을 아래와 같이 구현할 수 있습니다.

    2.1 sync.Once

    Go에서 멀티스레드(고루틴) 환경에서도 한 번만 객체를 안전하게 초기화하기 위해 주로 sync.Once를 사용합니다.

    package singleton
    
    import (
        "sync"
    )
    
    // 싱글톤 객체로 사용할 구조체
    type MySingleton struct {
        // 필요한 필드
        // 예: 설정 정보, 내부 캐시, 연결 정보 등
    }
    
    var (
        instance *MySingleton
        once     sync.Once
    )
    
    // GetInstance 함수: 전역에서 동일한 인스턴스를 반환
    func GetInstance() *MySingleton {
        // once.Do() 블록은 프로그램 전체에서 단 한 번만 실행됨
        once.Do(func() {
            instance = &MySingleton{
                // 필드 초기화
            }
        })
        return instance
    }
    
    // MySingleton의 메서드 예시
    func (m *MySingleton) SomeMethod() {
        // 싱글톤 객체가 제공할 기능
    }
    
    • sync.Once의 Do(func())는 여러 고루틴이 동시에 호출해도, 함수 본문을 딱 한 번만 실행하게 보장합니다.

    • instance가 최초 호출 시에만 초기화되므로 Lazy Initialization(지연 초기화)를 달성할 수 있습니다. 이후에는 이미 생성된 instance를 반환하므로, 항상 동일한 객체에 접근하게 됩니다.

      지연 초기화
      객체나 리소스가 실제로 필요해지는 순간(사용 시점)까지는 미리 생성하거나 로딩하지 않고, 최초로 필요한 시점에 동적 생성하는 기법입니다. 이를 통해 불필요한 리소스(메모리, CPU 등) 사용을 줄이고, 애플리케이션 시작 시점의 초기 로드 시간을 단축할 수 있다는 장점이 있습니다.

    • 사용 방법

      package main
      
      import (
          "fmt"
      
          "example.com/mysingleton/singleton"
      )
      
      func main() {
          // 싱글톤 인스턴스 가져오기
          s1 := singleton.GetInstance()
          s2 := singleton.GetInstance()
      
          // 두 포인터가 동일함을 확인 (동일 객체)
          if s1 == s2 {
              fmt.Println("s1 and s2 are the same instance")
          }
      
          // 싱글톤의 메서드 사용
          s1.SomeMethod()
      }
      
      > output: s1 and s2 are the same instance
      






    - 컬렉션 아티클