13. Singleton 주입
1. Singleton 주입 개요
더보기
✔️ 사용 목적
- Logger 같은 전역 서비스(Singleton)를 ViewModel에 안전하게 주입하여 사용합니다.
- MVVM에서 Logger.Instance를 직접 참조하지 않고, 인터페이스 기반으로 느슨한 결합을 유지합니다.
✔️ 소스코드
WPF_Singleton.zip
0.23MB
2. 예제1 - Window 1개
더보기





📁 Services 구현
WPF_Singleton04_01MVVM/
├── Services/
│ ├── ILoggerService.cs
│ └── Logger.cs ← Singleton 구현
//├── ViewModels/
//│ └── MainViewModel.cs
//├── Views/
//│ └── MainWindow.xaml
//│ └── MainWindow.xaml.cs
//└── App.xaml.cs
✔️ ILoggerService 인터페이스 구현

public interface ILoggerService
{
void Log(string message);
string GetLogs();
}
✔️ Logger 클래스 구현

public sealed class Logger : ILoggerService
{
private static Logger? _instance = null;
private static readonly object _lock = new();
private readonly StringBuilder _logs = new();
private Logger()
{
Console.WriteLine("Logger Singleton 인스턴스 생성됨");
}
public static Logger Instance
{
get
{
lock (_lock)
{
return _instance ??= new Logger();
}
}
}
public void Log(string message)
{
_logs.AppendLine($"{DateTime.Now:HH:mm:ss} - {message}");
}
public string GetLogs()
{
return _logs.ToString();
}
}
📁 ViewModels 구현
WPF_Singleton04_01MVVM/
//├── Services/
//│ ├── ILoggerService.cs
//│ └── Logger.cs ← Singleton 구현
├── ViewModels/
│ └── MainViewModel.cs
//├── Views/
//│ └── MainWindow.xaml
//│ └── MainWindow.xaml.cs
//└── App.xaml.cs
✔️ MainViewModel 구현

public partial class MainViewModel : ObservableObject
{
private readonly ILoggerService _logger;
[ObservableProperty]
private string logText;
public MainViewModel(ILoggerService logger)
{
_logger = logger;
_logger.Log("MainViewModel 생성됨");
LogText = _logger.GetLogs();
}
[RelayCommand]
private void WriteLog()
{
_logger.Log("버튼 클릭 로그 기록");
LogText = _logger.GetLogs();
}
}
📁 View 구현
WPF_Singleton04_01MVVM/
//├── Services/
//│ ├── ILoggerService.cs
//│ └── Logger.cs ← Singleton 구현
//├── ViewModels/
//│ └── MainViewModel.cs
├── Views/
│ └── MainWindow.xaml
│ └── MainWindow.xaml.cs
//└── App.xaml.cs
✔️ MainWindow XAML 구현

Title="Logger Singleton" Height="250" Width="400">
<StackPanel Margin="10">
<Button Content="로그 남기기" Command="{Binding WriteLogCommand}" Margin="0 10"/>
<TextBox Text="{Binding LogText}" Height="150" AcceptsReturn="True" VerticalScrollBarVisibility="Auto"/>
</StackPanel>
✔️ MainWindow 코드 비하인드 구현

// Logger.Instance 를 서비스 인터페이스로 주입
DataContext = new MainViewModel(Logger.Instance);
3. 예제2 - Window 2개
더보기




📁 Services 구현
WPF_Singleton04_02MVVM/
├── Services/
│ ├── ILoggerService.cs
│ └── Logger.cs ← Singleton 구현
//├── ViewModels/
//│ └── MainViewModel.cs
//│ └── SubViewModel.cs
//├── Views/
//│ └── MainWindow.xaml
//│ └── MainWindow.xaml.cs
//│ └── SubWindow.xaml
//│ └── SubWindow.xaml.cs
//└── App.xaml.cs
✔️ ILoggerService 인터페이스 구현
public interface ILoggerService
{
void Log(string message);
string GetLogs();
}
✔️ Logger 클래스 구현
// Logger 클래스는 애플리케이션 전역에서 하나만 존재해야 하는 로깅 클래스입니다.
// 여러 창(Window) 또는 ViewModel에서 공통적으로 사용할 수 있도록 Singleton 패턴으로 구성됩니다.
public sealed class Logger : ILoggerService
{
private static Logger? _instance = null;
private static readonly object _lock = new();
private readonly StringBuilder _logs = new();
private Logger()
{
Console.WriteLine("Logger 인스턴스가 생성되었습니다.");
}
public static Logger Instance
{
get
{
lock (_lock)
{
return _instance ??= new Logger();
}
}
}
public void Log(string message)
{
_logs.AppendLine($"{DateTime.Now:HH:mm:ss} - {message}");
}
public string GetLogs()
{
return _logs.ToString();
}
}
📁 ViewModels 구현
WPF_Singleton04_02MVVM/
//├── Services/
//│ ├── ILoggerService.cs
//│ └── Logger.cs ← Singleton 구현
├── ViewModels/
│ └── MainViewModel.cs
│ └── SubViewModel.cs
//├── Views/
//│ └── MainWindow.xaml
//│ └── MainWindow.xaml.cs
//│ └── SubWindow.xaml
//│ └── SubWindow.xaml.cs
//└── App.xaml.cs
✔️ MainViewModel 구현

public partial class MainViewModel : ObservableObject
{
private readonly ILoggerService _logger;
[ObservableProperty]
private string logText;
public MainViewModel(ILoggerService logger)
{
_logger = logger;
_logger.Log("MainWindow 열림");
LogText = _logger.GetLogs();
}
[RelayCommand]
private void WriteLog()
{
_logger.Log("MainWindow에서 로그 기록");
LogText = _logger.GetLogs();
}
[RelayCommand]
private void OpenSubWindow()
{
var sub = new SubWindow();
sub.Show();
}
}
✔️ SubViewModel 구현

public partial class SubViewModel : ObservableObject
{
private readonly ILoggerService _logger;
[ObservableProperty]
private string logText;
public SubViewModel(ILoggerService logger)
{
_logger = logger;
_logger.Log("SubWindow 열림");
LogText = _logger.GetLogs();
}
[RelayCommand]
private void WriteLog()
{
_logger.Log("SubWindow에서 로그 기록");
LogText = _logger.GetLogs();
}
}
📁 View 구현
WPF_Singleton04_02MVVM/
//├── Services/
//│ ├── ILoggerService.cs
//│ └── Logger.cs ← Singleton 구현
//├── ViewModels/
//│ └── MainViewModel.cs
//│ └── SubViewModel.cs
├── Views/
│ └── MainWindow.xaml
│ └── MainWindow.xaml.cs
│ └── SubWindow.xaml
│ └── SubWindow.xaml.cs
//└── App.xaml.cs
✔️ MainWindow.xaml구현

Title="MainWindow" Height="300" Width="400">
<StackPanel Margin="10">
<Button Content="로그 남기기" Command="{Binding WriteLogCommand}" Margin="0 0 0 10"/>
<Button Content="SubWindow 열기" Command="{Binding OpenSubWindowCommand}" Margin="0 0 0 10"/>
<TextBox Text="{Binding LogText}" AcceptsReturn="True" Height="200"/>
</StackPanel>
✔️ MainWindow 코드 비하인드 구현
public MainWindow()
{
InitializeComponent();
// Logger.Instance 를 서비스 인터페이스로 주입
DataContext = new MainViewModel(Logger.Instance);
}
✔️ SubWindow 구현

✔️ SubWindow 코드 비하인드 구현
public SubWindow()
{
InitializeComponent();
// Logger.Instance 를 서비스 인터페이스로 주입
DataContext = new SubViewModel(Logger.Instance);
}