7.1 KiB
7.1 KiB
Vav2Player - Testable Hybrid Logging Architecture Design
🎯 목표
- 확장 가능한 로깅: 다양한 출력 대상 지원 (Console, Debug, Network, File)
- MVVM 호환: Model-ViewModel-View 패턴과 완벽 통합
- 테스트 가능: Unit Test에서 로깅 동작 검증 가능
- 개발자 친화적: 간단한 API로 어디서든 쉽게 사용
🏗️ 아키텍처 구조
전체 구조도
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ View Layer │ │ ViewModel │ │ Model Layer │
│ (LogMessagePage)│◄───┤(LogPageViewModel)│◄───┤ (LogManager) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ILogOutput Interface │
├─────────────────┬─────────────────┬─────────────────┬───────────┤
│ ConsoleLogOutput│ DebugLogOutput │ FileLogOutput │NetworkLog │
│ (stdout) │ (VS Output) │ (.log file) │(future) │
└─────────────────┴─────────────────┴─────────────────┴───────────┘
컴포넌트 간 관계
[VideoPlayerControl]
│
▼
[LogManagerProvider::GetInstance()] ─┐
│ │ (Production)
▼ ▼
[Real LogManager] ◄──── or ───► [Mock LogManager] (Testing)
│
▼
[ILogOutput Implementations]
🔧 핵심 컴포넌트
1. Model Layer
ILogManager (Interface)
class ILogManager {
public:
virtual void LogInfo(const std::wstring& message, const std::wstring& source) = 0;
virtual void LogVideoLoad(const std::wstring& filename, bool success) = 0;
virtual void AttachLogOutput(std::unique_ptr<ILogOutput> output) = 0;
// ... 기타 로깅 메서드
};
LogManager (실제 구현체)
- Singleton 패턴
- ILogManager 인터페이스 구현
- 다중 ILogOutput 관리
- Thread-safe 로그 데이터 저장
MockLogManager (테스트용)
- ILogManager 인터페이스 구현
- 로그 호출 기록 및 검증 기능
- Unit Test에서 로깅 동작 검증
2. Infrastructure Layer
LogManagerProvider (Global Access)
class LogManagerProvider {
public:
static ILogManager& GetInstance(); // Production: LogManager, Test: MockLogManager
static void SetInstance(std::shared_ptr<ILogManager> mock); // Test에서 Mock 주입
static void ResetToDefault(); // Test 후 정리
};
ILogOutput (출력 인터페이스)
class ILogOutput {
public:
virtual void OutputLog(const LogMessage& message) = 0;
virtual void SetLogLevel(LogLevel level) = 0;
virtual std::wstring GetName() const = 0;
};
구현체들
- ConsoleLogOutput: stdout 콘솔 출력
- DebugLogOutput: Visual Studio 출력 창 (OutputDebugString)
- FileLogOutput: 파일 로깅
- NetworkLogOutput: 네트워크 로깅 (향후 확장)
3. Presentation Layer
LogMessagePageViewModel (향후 구현)
- LogManager와 View 사이의 바인딩
- Observable Collection 관리
- UI 상태 관리 (필터, 자동 스크롤 등)
LogMessagePage (View)
- 순수 XAML 선언형 UI
- ViewModel에 데이터 바인딩
📋 사용 방법
Production 코드에서
class VideoPlayerControl {
void LoadVideo(const std::wstring& filePath) {
// 어디서든 간단하게 로깅
LogManagerProvider::GetInstance().LogInfo(L"Loading video: " + filePath, L"VideoPlayer");
// 비디오 로딩 로직...
bool success = LoadVideoFile(filePath);
LogManagerProvider::GetInstance().LogVideoLoad(filePath, success);
}
};
MainWindow에서 초기화
class MainWindow {
MainWindow() {
// LogManager 초기화 및 출력 설정
auto& logManager = LogManager::GetInstance();
logManager.InitializeDefaultOutputs(); // Console + Debug 출력 자동 추가
// 선택적으로 파일 로깅 추가
logManager.AttachLogOutput(LogOutputFactory::CreateFileOutput(L"app.log"));
}
};
Unit Test에서
TEST_METHOD(VideoPlayerControl_LoadVideo_ShouldLogCorrectly) {
// Arrange - Mock LogManager 주입
auto mockLogManager = std::make_shared<MockLogManager>();
LogManagerProvider::SetInstance(mockLogManager);
VideoPlayerControl player;
// Act
player.LoadVideo(L"test.mp4");
// Assert - 로깅 호출 검증
Assert::AreEqual(2, mockLogManager->GetLogCallCount());
Assert::IsTrue(mockLogManager->WasMethodCalled(L"LogInfo"));
Assert::IsTrue(mockLogManager->WasMethodCalled(L"LogVideoLoad"));
Assert::IsTrue(mockLogManager->WasMessageLogged(L"Loading video"));
// Cleanup
LogManagerProvider::ResetToDefault();
}
✅ 장점
개발 편의성
- 전역 접근:
LogManagerProvider::GetInstance()로 어디서든 사용 - 간단한 API: 복잡한 의존성 전달 불필요
- 타입 안전: 컴파일 타임에 로깅 메서드 검증
확장성
- 플러그인 아키텍처: 새로운 ILogOutput 구현체 추가 용이
- 다중 출력: Console + Debug + File + Network 동시 출력 가능
- 개별 설정: 출력별로 로그 레벨 독립 설정
테스트 가능성
- Mock 지원: MockLogManager로 로깅 동작 완벽 검증
- 격리된 테스트: 테스트 간 로그 상태 격리
- 검증 API: 로그 호출 횟수, 메시지 내용, 파라미터 검증
MVVM 호환성
- Model: LogManager가 데이터와 비즈니스 로직 관리
- ViewModel: UI 바인딩과 프레젠테이션 로직 분리
- View: 순수 선언형 UI
🔄 확장 계획
- LogMessagePageViewModel 구현: ViewModel 패턴 완성
- Network Logging: 원격 로그 수집 서버 연동
- Log Filtering: 동적 로그 필터링 UI
- Performance Logging: 성능 메트릭 전용 로깅
- Structured Logging: JSON 기반 구조화 로깅
🎯 결론
이 하이브리드 아키텍처는:
- Production: 간편한 Singleton 접근
- Testing: 완벽한 Mock 지원
- Architecture: MVVM 패턴 준수
- Extensibility: 플러그인 기반 확장성
을 모두 만족하는 최적의 로깅 솔루션을 제공합니다.