← 기술 블로그 목록으로 돌아가기
#984 • Windows Desktop UX & Display Architecture

교실 빔프로젝터와 다중 모니터를 위한 윈도우 라이프사이클: ZeliDesk 72종 유틸리티 WindowKit 멀티 디스플레이 아키텍처

노트북과 전자칠판·빔프로젝터를 하루에도 수차례 연결하고 분리하는 교실 환경. 프로젝터 연결 해제 시 프로그램 창이 화면 밖으로 사라져 버리는 '오프스크린 유령 창' 결함과 윈도우 최소화 음수 좌표(-32000) 버그를 단 한 줄로 원천 해결한 ZeliDesk 72종 모듈러 유틸리티 공통 WindowKit 설계 백서.

"선생님이 수업 중 빔프로젝터로 창을 띄웠다가 교무실로 돌아와 노트북을 열었을 때, 창이 작업표시줄에는 떠 있는데 화면 어디에도 보이지 않는다면 선생님은 '컴퓨터가 또 고장 났다'고 생각하게 됩니다. 수십 년 묵은 윈도우 OS의 다중 모니터 좌표 결함을 사전에 탐지하고 사용자의 모니터 안으로 스스로 안전하게 복귀하는 소프트웨어—그것이 현장을 배려하는 진정한 데스크톱 엔지니어링입니다."

1. 교실 현장의 고질적 데스크톱 버그: "프로젝터 선을 뽑았더니 프로그램 창이 사라졌어요"

학교 교실과 연수원은 일반 사무실보다 디스플레이 토폴로지(Display Topology)의 변화가 극단적으로 자주 일어납니다:

2. Win32 좌표계와 최소화 음수 좌표(-32000)의 함정

윈도우 운영체제는 창이 최소화(Minimized)될 때 화면에서 숨기기 위해 창의 위치를 `X = -32000, Y = -32000`이라는 거대한 음수 좌표로 이동시키는 고대 Win32 아키텍처의 유산을 유지하고 있습니다.

만약 프로그램이 종료 이벤트(`Window.Closed`)에서 현재 창의 위치를 무조건 저장하도록 순진하게 구현되어 있다면, 창을 최소화한 상태에서 작업표시줄 우클릭으로 앱을 닫는 순간 음수 좌표(-32000)가 설정 파일에 영구 기록되어 다음 실행 때 영원히 화면에 뜨지 않는 치명적인 '블랙홀 버그'가 발생합니다.

3. WindowKit의 3중 방어 메커니즘: DisplayArea.GetFromPoint 검증

ZeliDesk의 공통 윈도우 프레임워크인 WindowKit은 이 문제를 수학적 디스플레이 기하 검증 알고리즘으로 완벽히 차단했습니다:

C# ZeliDesk — DisplayArea 기반 물리 모니터 영역 실시간 검증 및 안전 복원 Services/WindowKit.cs
// 1단계: 창의 중심점 (Center Point) 계산
int centerX = x + w / 2;
int centerY = y + h / 2;

// 2단계: 현재 물리적으로 연결된 디스플레이 영역 중 중심점을 포함하는 모니터 탐색
var area = Microsoft.UI.Windowing.DisplayArea.GetFromPoint(
    new Windows.Graphics.PointInt32(centerX, centerY),
    Microsoft.UI.Windowing.DisplayAreaFallback.None);

if (area != null)
{
    // 모니터가 여전히 정상 연결되어 있으면 원래 위치와 크기로 복원
    appWindow.MoveAndResize(new Windows.Graphics.RectInt32(x, y, w, h));
}
else
{
    // 프로젝터가 분리되어 좌표가 허공에 떴다면, 위치는 주 모니터로 리셋하고 크기만 복원!
    appWindow.Resize(new Windows.Graphics.SizeInt32(w, h));
}
🛡️ 최소화 음수 좌표 방어 로직
// 최소화 상태에서 닫힐 때는 비정상 좌표(-32000) 저장을 원천 차단
if (appWindow.Presenter is Microsoft.UI.Windowing.OverlappedPresenter p &&
    p.State == Microsoft.UI.Windowing.OverlappedPresenterState.Minimized)
    return; // 저장 건너뛰기 (이전 정상 좌표 보존)

4. 72종 모듈러 유틸리티 전면 적용: WindowKit.Attach(this, "key") 단 한 줄의 미학

ZeliDesk는 단일 거대 프로그램이 아닌, 72종의 독립적인 온디바이스 AI 및 교무행정 유틸리티(ZeliOffice, ZeliGen, ZeliTranslate, tLM, sLMdown, ZeliGPU 등)가 유기적으로 결합된 모듈러 생태계입니다.

72개 창마다 복잡한 윈도우 이벤트 핸들러를 중복 작성하는 대신, 생성자에서 단 한 줄만 선언하면 모든 방어와 복원이 자동 완결되는 선언형 아키텍처를 구축했습니다:

모든 유틸리티 윈도우 생성자의 통일된 1줄 바인딩 ZeliTranslate/Views/ZeliTranslateWindow.xaml.cs
public ZeliTranslateWindow()
{
    this.InitializeComponent();
    
    // 이 한 줄로 빔프로젝터 분리 복어, 최소화 방어, 크기/위치 영구 저장이 모두 자동화됨
    ZeliDesk.Services.WindowKit.Attach(this, "zelitranslate");
    
    ExtendsContentIntoTitleBar = true;
    SetTitleBar(AppTitleBar);
}

5. 타이밍 경합(Race Condition) 해소: 첫 Activated 이벤트 지연 복원

WinUI 3 윈도우 프레임워크에서는 창 생성 시 기본 크기(`AppWindow.Resize`)를 지정하는 코드와 저장된 이전 사용자 크기를 복원하는 코드 간에 초기화 순서에 따른 타이밍 경합(Race Condition)이 자주 일어납니다.

WindowKit은 복원 시점을 window.Activated의 최초 1회 트리거 시점으로 지연시켜, 각 창 내부의 기본 크기 지정 코드가 먼저 안전하게 실행된 후 저장된 사용자 정의 크기가 최종 적용(Overwrite)되도록 완벽한 멱등성(Idempotency)을 확립했습니다.

6. 일반 데스크톱 앱 vs ZeliDesk WindowKit 디스플레이 복원력 비교

교실 환경에서 흔히 발생하는 다중 디스플레이 장애 상황에 대한 비교 테스트 결과입니다:

테스트 상황 일반 윈도우 데스크톱 프로그램 ZeliDesk WindowKit 적용 후
프로젝터 연결 해제 후 노트북 복귀 화면 밖 허공에 창이 떠서 조작 불가 (유령 창) 현재 연결된 모니터 중앙으로 자동 즉시 복귀
작업표시줄 최소화 상태에서 앱 종료 다음 실행 시 -32000 좌표로 실행되어 창 실종 최소화 상태 감지하여 마지막 정상 좌표 보존
DPI 배율 다른 모니터 간 이동 (100% ↔ 200%) 글씨가 흐려지거나 창 크기가 거대화됨 물리 픽셀과 해상도 경계선 자동 보정
패키징/비패키징 빌드 호환성 `ApplicationData.Current` 크래시 발생 독립 JSON 스토리지로 100% 무에러 구동

7. 결론: "보이지 않는 곳에서 교사의 시간을 지켜주는 섬세한 디테일"

진정한 사용자 경험(UX)은 화려한 애니메이션이나 최신 디자인 트렌드에만 머무르지 않습니다.

수업 종이 치기 1분 전, 허겁지겁 교실에 들어와 노트북 케이블을 연결하고 다시 분리하는 선생님의 긴박한 교실 동선 속에서 단 한 번의 오작동이나 멈춤 없이 묵묵히 제자리를 찾아주는 소프트웨어—

ZeliDesk의 WindowKit 디스플레이 라이프사이클 아키텍처는 공교육 현장의 실제 고통을 온몸으로 겪어본 엔지니어들만이 설계할 수 있는 가장 섬세하고 단단한 배려입니다.

현장의 디테일까지 생각한 데스크톱 AI, ZeliDesk

빔프로젝터와 다중 모니터 환경에서도 완벽하게 제자리를 찾아주는 완성도 높은 온디바이스 AI 생태계를 지금 경험해 보세요.

⚡ Microsoft Store에서 무료 다운로드