C#에서 프라이빗 생성자(private constructor)는 외부에서 객체를 직접 생성하지 못하도록 막는 특수한 생성자입니다. 주로 정적(static) 멤버만 포함하는 클래스나, 인스턴스가 하나만 존재해야 하는 싱글톤 패턴을 구현할 때 활용됩니다.
프라이빗 생성자란?
정적 멤버만 가지고 있는 클래스에는 프라이빗 생성자를 사용하는 것이 일반적입니다. 아래 예제처럼 생성자에 private 접근 제한자를 붙이면, 클래스 외부에서 new 키워드로 인스턴스를 만들 수 없습니다.
class Demo {
// 프라이빗 생성자
private Demo() { }
public static int a = 10;
}이렇게 하면 해당 클래스는 오직 정적 멤버를 통해서만 접근할 수 있으며, 불필요한 인스턴스 생성을 원천적으로 차단할 수 있습니다.
싱글톤 클래스와 프라이빗 생성자의 관계
싱글톤(Singleton) 클래스는 애플리케이션 전체에서 단 하나의 인스턴스만 존재하도록 보장하는 디자인 패턴입니다. 일반적인 메서드를 가질 수 있으며, 미리 만들어 둔 단일 인스턴스를 통해 기능을 호출합니다.
여기서 핵심 역할을 하는 것이 바로 프라이빗 생성자입니다. 생성자를 private으로 선언하면 외부 코드가 임의로 새 인스턴스를 만들 수 없으므로, 자연스럽게 다중 인스턴스 생성을 방지할 수 있습니다.
싱글톤 구현 예제
다음은 프라이빗 생성자를 활용한 기본적인 싱글톤 클래스 구조입니다.
public class Singleton {
// 유일한 인스턴스를 저장하는 정적 변수
static Singleton instance = null;
// 프라이빗 생성자: 외부에서 new로 생성 불가
private Singleton() {
}
// 인스턴스에 접근하는 정적 메서드
public static Singleton GetInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}동작 방식 설명
- 정적 변수(instance): 클래스의 유일한 인스턴스를 저장합니다. 처음에는
null로 초기화됩니다. - 프라이빗 생성자: 외부에서
new Singleton()호출 시 컴파일 오류가 발생하여 인스턴스 중복 생성을 막습니다. - GetInstance() 메서드: 인스턴스가 아직 없으면 최초 한 번만 생성하고, 이후에는 항상 동일한 인스턴스를 반환합니다.
사용 시 주의사항
멀티스레드 환경에서는 두 스레드가 동시에 GetInstance()를 호출해 인스턴스가 두 번 생성될 위험이 있습니다. 이 경우 lock 문이나 Lazy<T> 타입을 사용해 스레드 안전성을 확보하는 것이 좋습니다.
public sealed class ThreadSafeSingleton {
private static readonly Lazy<ThreadSafeSingleton> lazy =
new Lazy<ThreadSafeSingleton>(() => new ThreadSafeSingleton());
private ThreadSafeSingleton() { }
public static ThreadSafeSingleton Instance => lazy.Value;
}이처럼 프라이빗 생성자는 단순히 접근을 제한하는 것을 넘어, 인스턴스 생성 정책을 강제하는 강력한 도구입니다. 정적 유틸리티 클래스나 설정 관리, 로깅, 데이터베이스 연결 관리 등 전역적으로 하나의 객체만 필요한 상황에서 싱글톤 패턴과 함께 적극적으로 활용해 보세요.