07. 게임 UI
상위 문서:
게임기획코어.md상태: 3열 배치 · 연출 2레이어 · 위젯 배치·스트립 방향 확정 · 슬롯 연출 = 방치형 루프(2026-09-27) / 목업 1종(v2) 바뀌면 갱신:게임기획코어·벌목·우편·채굴·캐릭터·퀘스트
이 게임이 다른 방치형과 구분되는 유일한 차별점이다. "바탕화면 위에서 상시 동작"은 컨셉 문구가 아니라 가장 강한 제약이다.
1. 확정 사항
- Windows 바탕화면 위 투명 창으로 상시 동작한다.
- 기본은 방치형 — 조작이 필요 없다.
- 위젯 클릭 → 큰 창으로 퀘스트·특성·아이템·거래를 조작한다.
- 아트: Pixel + Stylized (AI). UI/UX도 동일 방향.
2026-08-01 추가 확정 — 2026-07-30 방향 제안 합의분.
| 항목 | 확정 내용 | 근거 |
|---|---|---|
| 상주 범위 | 바탕화면에 상주하는 것은 위젯뿐이다. 3열은 필요할 때 여는 큰 창 | 제안 2.3 (기존 Q8의 답) |
| 3열 배치 | 왼쪽 인벤토리(캐릭터·장비·자원·특성 — 얻은 것이 바로 들어오는 곳 · 옛 이름 창고) / 가운데 작업슬롯 전용 / 오른쪽 거래(뽑기·경매장·창고) | 제안 2장 · 2026-09-30 개편 |
| 연출 2레이어 | 상시 위젯은 텍스트 + 게이지 + 가벼운 연출(픽셀 머리 흔들기 · 아이템 떠오름 — 2026-09-27). 배경·캐릭터 전신·공격 모션은 큰 창에서만 돌린다 → 2.5 | 제안 8.2 |
| 상점의 정체 | 골드 상점. 현금 상품은 두지 않는다 (BM은 여전히 미정) | 제안 4.4 · 거래 3.2 |
| 창 자체 | 16:9 비율 고정 · 배경 투명 · 화면을 덮지 않는다. 크기는 배율 프리셋 1x~2x |
2장 |
| 위젯 위치 | 창 안 6칸 프리셋 — 왼쪽·가운데·오른쪽 × 위·아래. 자유 드래그 없음 |
2.1 |
| 기준 해상도 | 1920 × 1080(= 배율 2x)로 UI를 만든다 |
2장 |
1-1. 목업 (v2 · 2026-07-30)
브라우저로 열면 동작한다. 카운트다운은 실제 계산식
(CurrentWorkSpeed · JudgeCostUnits · ProgressUnits)을 그대로 쓰므로,
클라 구현 시 계산 부분을 옮겨 쓸 수 있다.
| 파일 | 내용 | 연결 일감 |
|---|---|---|
| 게임UI목업(2026-07-30 업데이트).html | v2 통합 목업 — 인벤토리(4탭) · 작업슬롯 · 거래(2탭) 3창 + 상단바 + 하단 버튼 + 상시 위젯 | T-006 · T-007 · T-002 · T-015 |
v1 두 목업(
게임UI목업.html·작업슬롯UI목업.html)은 폐기됐다. 방향 제안이 합의되면서 배치가 바뀌었고, 작업슬롯 전용 목업의 내용(상시 스트립 3안)이 v2 상단 토글로 흡수돼 하나로 합쳐졌다. 제안 시점의 사본은proposals/2026-07-30/에 기록으로 남아 있다.
📋 목업 우상단 "기획 메모" 버튼을 누르면 v1→v2 변경 내역 · 계산식 · 목업이 가정한 미확정 항목이 표로 정리돼 있다. 이 문서에 옮겨 적지 않는다 — 메모가 목업의 단일 진실이다.
⚠️ 거래소·상점은 기획이 없다. 목업의 수수료·한도·품목·가격은 전부 가정이다. 골드 상점이라는 방향만 잡혔고 수치는 전부 미정이다. → 거래 3.2
⚠️ v2에도 산업 레벨이 반영돼 있지 않다. 배치가
(산업, 캐릭터)두 칸으로 그려져 있는데, 실제로는 레벨이 한 칸 더 붙는다. 패킷 레벨 필드는 붙었다(T-017 완료 —C_WorkStationAssignRequest.IndustryLevel). 해금은 해금으로 통일됐다(2026-09-14) — 잠긴 것은 전부 보이고 조건도 보인다. 계정 레벨 요구치(T-016)가 정해지면 목업을 갱신한다. → 산업 레벨
2. 화면 구조
창 자체 — 16:9 배율 창 (2026-08-01 확정)
게임은 바탕화면을 덮지 않는다. 데스크톱 위에 뜨는 16:9 비율 고정 · 배경 투명 창이고, 크기는 배율 프리셋으로 고른다. 아래 UI 이야기는 전부 이 창 안의 이야기다.
| 축 | 값 | 담당 |
|---|---|---|
| 창의 데스크톱 위치 | 9분할 앵커 | WindowManager.ScreenAnchor |
| 창 크기 | 1x 960×540 · 1.25x 1200×675 · 1.5x 1440×810 · 2x 1920×1080 |
WindowManager.WindowScale |
| 위젯의 창 안 위치 | 6칸 (2.1) | UI 레이아웃 |
- 절대 픽셀이다. 모니터 해상도에 비례시키지 않는다 — 어느 기기에서든 UI 픽셀 크기가 같아야 디자인 검증과 버그 재현이 된다.
- 배율이 모니터보다 크면 16:9를 유지한 채 작업 영역 안으로 줄인다.
- 기준 해상도
1920 × 1080(=2x)로 UI를 만들고, 그보다 작은 배율은CanvasScaler가 비례 축소한다. 1x보다 작은 배율은 두지 않는다(0.5x·0.75x는 너무 작아 제거, 2026-09-30).
⚠️ 세 축을 섞지 않는다. "창을 화면 어디에 두는가"(9분할)와 "위젯을 창 안 어디에 두는가"(6칸)는 다른 축이다.
캔버스 구성
캔버스는 3개다. 위젯은 별도 캔버스가 아니라 작업슬롯 캔버스 안의 패널이다 — 상시 표시되는 것이 위젯뿐이어도, 위젯은 작업슬롯 열의 위/아래 슬롯에 들어간다.
| 캔버스 | 담는 것 | 표시 |
|---|---|---|
작업슬롯 (Workstation) |
작업슬롯 전용. 위아래 슬롯에 상태 패널(섬주인 레벨·골드·시스템 아이콘)과 위젯이 들어간다. 본체 안쪽 아래에 버튼 5개 | 위젯은 항상, 본체는 ↑ 로 열 때 |
인벤토리 (Inventory) |
캐릭터 · 장비 · 자원 · 특성 4탭 (2026-09-30 창고/Storage에서 개명) |
작업슬롯에서 열 때 |
거래 (Market) |
뽑기 · 경매장 · 창고 3탭 (2026-09-30 — 창고는 자원·장비·캐릭터 무엇이든 두고두고 보관하는 곳. 인벤토리와 별개 · 아직 (기능 없음)) |
작업슬롯에서 열 때 |
배치의 골격은 세로 3구역(왼쪽·가운데·오른쪽) 분할이다.

세 창의 정렬 규칙
세 창의 배너 줄(STORAGE · WORKSTATION · MARKET)이 같은 높이에 온다.
본체 높이도 셋 다 같으므로 아래쪽도 맞는다.
세 열은 전부 위 슬롯 / 본체 / 아래 슬롯 3단으로 같게 만든다.
| 열 | 위 슬롯 | 본체 | 아래 슬롯 |
|---|---|---|---|
| 작업슬롯 | 상태 패널 또는 위젯 | 슬롯 격자 | 나머지 하나 |
| 인벤토리 · 거래 | 빈 자리 | 탭 본체 | 빈 자리 |
"상단바"가 아니라 "상태 패널"이다. 위젯이 위 칸으로 가면 이 패널은 아래로 내려가므로, 위치를 이름에 담으면 절반은 거짓이 된다. 담는 것(계정 레벨·골드·시스템 아이콘 = 상태)으로 부른다. v2 목업에는 아직 "상단바"로 적혀 있다.
- 인벤토리·거래에도 같은 높이의 빈 자리를 두어야 본체 높이가 맞는다. 작업슬롯 열만 위아래로 무언가 붙으면 그만큼 본체가 밀려 배너 줄과 아랫변이 어긋난다.
- 하단 버튼 5개는 창 밖이 아니라 본체 안쪽 아래에 들어간다. 창 밖에 붙이면 작업슬롯 열만 길어져 같은 문제가 생긴다.
2.0 여는 순서 — 작업슬롯이 진입점이다
위젯 [↑] ─→ 작업슬롯 본체 ─┬─→ 인벤토리
└─→ 거래
- 위젯의
↑버튼으로 가장 먼저 열리는 것은 작업슬롯 본체다. 인벤토리·거래는 작업슬롯 본체 하단의 버튼으로 연다 — 위젯에서 직접 열지 않는다. - 작업슬롯 캔버스는 위젯의 세로 라인을 따라간다. 위젯이 왼쪽 칸에 있으면 왼쪽 라인에, 오른쪽 칸에 있으면 오른쪽 라인에 맞춰 열린다. ⏸ 구현은 추후 작업이다 — 지금은 방향만 확정.
2.0.1 왜 이 순서인가 — 동선이 한 방향이다
- 인벤토리에 들어온 캐릭터·장비를 작업슬롯으로 끌어다 배치한다.
- 슬롯을 클릭하면 그 슬롯의 설정 오버레이가 열리고, 거기서 캐릭터에 장비를 착용시킨다.
- 오른쪽은 결과물의 출구(거래소) 와 입구(상점) 다. 왼쪽 → 가운데 → 오른쪽으로 흐름이 한 방향이라 헷갈리지 않는다.
원본 근거: 방향 제안 2장.
2.1 위젯 (상주 레이어)
이 게임의 얼굴이자, P1을 지키거나 어기는 지점이다.
| 원칙 | 내용 |
|---|---|
| 작을 것 | 화면 구석 소형. 작업 창을 가리지 않음 |
| 조용할 것 | 급격한 애니메이션·번쩍임 금지 |
| 클릭 통과 | 위젯 바깥은 마우스 입력을 데스크톱으로 통과시킨다 |
| 항상 위 여부 | 선택 가능해야 함 — 강제 최상위는 업무 방해 |
| 상태 한눈에 | 오늘의 산업 / 진행도 / 수확 대기 여부 |
배치 — 6칸 프리셋 (2026-08-01 확정)
위젯은 창을 나눈 6칸 중 하나에 놓는다. 화면(모니터)이 아니라 창 안 기준이다 — 창을 화면 어디에 둘지는 9분할 앵커가 따로 담당한다(2장 첫 표).
| 왼쪽 | 가운데 | 오른쪽 | |
|---|---|---|---|
| 위 | ◻ | ◻ | ◻ |
| 아래 | ◻ | ◻ | ◻ |

- 자유 드래그는 두지 않는다. 프리셋만 있으면 좌표를 저장할 필요가 없고,
창 배율(
1x~2x)이 바뀌어도CanvasScaler가 비례해 자리를 유지한다 → 3장의 "위치·크기 보존" 논점이 여기서 닫힌다. - 멀티 모니터는 "어느 모니터 + 창의 9분할 앵커" 로 표현된다. 위젯 6칸과는 무관하다. 어느 모니터에 띄울지는 3장에 남은 미결 항목이다.
- 이 6칸이 곧 세로 3구역 분할의 기준선이고, 작업슬롯 캔버스가 그 라인을 따라간다(2.0).
구현 방식 — 정렬 그룹 + 형제 순서 (씬 골격 확정분).
| 축 | 조작 대상 |
|---|---|
| 가로 3 | 3열 정렬 그룹 안에서 작업슬롯 열의 형제 순서(0·1·2) |
| 세로 2 | 작업슬롯 열 안에서 위젯 패널이 위 슬롯이냐 아래 슬롯이냐 |
상태 패널은 항상 위젯의 반대편 슬롯으로 간다. 인벤토리·거래 열에도 같은 위/아래 빈 슬롯을 두어 세 열의 배너 줄 높이를 맞춘다.
3열 순서 규칙 — 작업슬롯과 인벤토리는 항상 붙어 있다 (2026-08-01 확정)
규칙은 하나다: 거래는 작업슬롯에서 가장 먼 끝에 둔다. 그러면 인벤토리가 자동으로 사이에 남는다. (작업슬롯이 가운데면 양끝이 같으므로 기본 배치 — 인벤토리 왼쪽 · 거래 오른쪽)
| 위젯 가로 | 열 순서 |
|---|---|
| 왼쪽 | 작업슬롯 · 인벤토리 · 거래 |
| 가운데 | 인벤토리 · 작업슬롯 · 거래 |
| 오른쪽 | 거래 · 인벤토리 · 작업슬롯 |
왜 인벤토리가 붙어야 하는가 — 인벤토리는 작업슬롯에 끌어다 넣는 재료(캐릭터·장비)다. 드래그 거리가 곧 조작 비용이므로 재료는 항상 옆에 있어야 한다. 거래는 결과물의 출구·입구라 한 번 갔다 오면 되는 곳이고, 멀어도 손해가 적다.
2.0.1의 동선은 "재료 → 작업 → 시장" 이라는 순서가 핵심이지 화면 좌우가 핵심이 아니다. 위젯이 오른쪽이면 이 순서가 오른쪽에서 왼쪽으로 읽힐 뿐, 인접 관계는 그대로 유지된다.
위젯이 표시하는 것 (v2 기준)
| 영역 | 내용 |
|---|---|
| 상단 | 골드 · 가동 슬롯 · 시간당 산출 · 누적 수확 |
| 스트립 | 미니 슬롯 — 캐릭터 픽셀 머리 + 수확 표시 + 게이지만. 텍스트 라벨은 넣지 않는다 |
↑ 버튼 |
4시 방향. 작업슬롯 캔버스 본체를 열고/닫는다 |
큰 연출은 여기서 돌리지 않는다. 배경·공격 모션은 큰 창 전용이다(1장 연출 2레이어). 위젯에 허용하는 것은 픽셀 머리 좌우 흔들기 + 판정 때 아이템 떠오름 두 가지뿐이다 (2026-09-27 → 2.5). 상시 실행 앱에서 리소스는 기능이 아니라 생존 조건이다.
2.2 큰 창 (조작 레이어)
| 항목 | 내용 |
|---|---|
| 진입 | 위젯 ↑ → 가운데 → 좌·우 |
| 왼쪽 탭 | 캐릭터 · 장비 · 자원 · 특성 |
| 오른쪽 탭 | 거래소 · 상점 |
| 크기 | 일반 창 수준. 이동·닫기 자유 |
| 종료 | 창을 닫아도 게임 진행은 계속된다. 닫으면 그리기를 멈춘다 |
2.3 알림 정책 (P1 직결)
| 상황 | 알림 | 근거 |
|---|---|---|
| 일반 채취 완료 | 없음 | 상시 발생 → 알리면 방해 |
| 희귀 이상 획득 | 위젯 내 조용한 표시 | 놓쳐도 손해 없음 |
| 인벤토리 가득 | 위젯 표시 | 새 종류 산출이 버려지므로 필요 (T-085 · 진행은 계속) |
| 거래 체결 | 접속 시 요약 | 실시간 알림 불필요 |
| 소리 | 기본 꺼짐 | 업무 중 사용 전제 |
원칙: 어떤 알림도 "지금 클릭하지 않으면 손해"를 만들지 않는다.
2.4 작업슬롯 캔버스 하단 — 특별 이벤트 자리 (2026-07-31)
작업슬롯 캔버스에는 슬롯 말고 다른 것을 넣지 않는다. 그 본체 안쪽 아래에 버튼 한 줄을 둔다.
v2 목업에서 이 줄은 버튼 5개로 구체화됐다 — 인벤토리 · 거래 · 미정 ×3.
비어 있는 3칸에 채취 루프 바깥의 콘텐츠가 들어온다.
| 들어올 후보 | 근거 |
|---|---|
| 보스 | 사냥에서 티켓을 모아 도전. 채취 루프 밖으로 나가는 유일한 통로 → 사냥 4장 |
| 대형 작업물 채취 | 여러 슬롯·시간을 들여 하나를 캐는 형태 (미기획) |
| 기타 특별 이벤트 | 미기획 |
지금 필요한 것은 자리를 비워 두는 것이지 콘텐츠를 만드는 것이 아니다.
- 버튼이 늘어나도 작업슬롯 영역이 밀리거나 줄지 않게 레이아웃을 잡는다
- 비어 있을 때는 잠긴 표시를 보여 주지 않는다. 잠긴 칸을 보여 주면 "지금 못 하는 것"이 상시로 눈에 남는다
- 이 층은 큰 창에서만 열린다. 상시 위젯에는 올라오지 않는다
⚠️ 여기 들어오는 것은 무엇이든 사냥 4.2의 보스 4원칙을 지킨다 — 도전 시점 자유 · 실시간 조작 없음 · 실패해도 티켓만 손실 · 기간 한정 없음.
버튼에 배지·타이머·"오늘까지" 표시를 붙이지 않는다. (예외는 우편함 버튼의 점 하나 — 숫자·기한이 없고, 기다리는 것이 사라지지 않는 보상이다) 붙이는 순간 바탕화면 상주 위젯이 재촉하는 물건이 되고, 2.3의 알림 원칙과 P1(주의를 뺏지 않는다)을 동시에 어긴다.
왜 작업슬롯 열인가 — 인벤토리는 배치에 쓰는 재료(캐릭터·장비), 거래는 결과물의 출구·입구다. "모은 것을 쓰는" 콘텐츠는 슬롯과 같은 열에 있어야 동선이 한 방향으로 유지된다.
구현: 일감 T-015
2.5 작업슬롯 연출 — 방치형 루프 (2026-10-04 갱신 · T-097)
연출 수치(시간·거리·배율)는 공용 설정 하나로 모든 슬롯에 걸리고, 캐릭터마다 다른 값(멈추는 거리 등)만 캐릭터 그림에 덧붙인다 — 클라 Art 규칙.md.
전 산업이 같은 형식이다. 산업마다 바뀌는 것은 대상의 그림뿐이다. 캐릭터는 오른쪽에 서서 왼쪽을 보고, 세상이 캐릭터 쪽으로 흘러온다.
[달리기] 배경이 흐른다(패럴랙스) · 캐릭터는 제자리 달리기 · 대상이 왼쪽에서 다가온다
│ 대상이 사거리에 닿는다 → 대기 자세 한순간(숨)
▼
[공격] 배경이 멈춘다 · 연속 공격(1→2→…타) — 때릴 때마다 대상이 하얗게 번쩍인다
│ 마무리 공격의 타격 = 게이지 도착 = 판정
▼
[처치] 마무리 공격이 동작을 마저 한다(여운) · 쓰러진 대상이 그 자리에서 사라진다
│ 배경·캐릭터는 처치 순간의 상태 그대로 — 처음으로 되돌리지 않는다
▼
[달리기] … 다음 대상 (무한)
| 규칙 | 내용 |
|---|---|
| 처치 1회 = 판정 1회 | 대상 하나를 쓰러뜨리는 것이 곧 판정 한 번이다. 판정 횟수에 걸린 다른 상태값(깊이·고갈)은 없다 |
| 대상 | 슬롯의 산업에 맞춘 대상 — 채굴은 돌, 벌목은 나무 … 레벨은 색으로만 가른다(1레벨 원래 색 · 2레벨 노랑 …). 🎨 지금은 임시 그림 |
| 고정 시간 | 모션 길이는 캐릭터·산업과 무관하게 고정이다 — 다가오기 1초 · 달리기 한 바퀴 0.8초 · 공격 한 번 0.6초. 원본 프레임 수가 달라도 이 시간에 맞춰 재생한다 |
| 속도 | 실효 속도(작업슬롯 3.4)는 모션을 빠르게 하지 않는다. 판정 1회(실효 주기)가 짧아져 때리는 횟수가 줄어든다 — 빠른 캐릭터는 몇 번 만에, 느린 캐릭터는 오래 때린다 |
| 맞춤 지점 | 마지막 타격 = 게이지 도착 = 판정이 한 프레임에 겹친다. 공격은 판정 순간에서 거꾸로 세어 놓는다 — 첫 공격이 잘려 시작할 수는 있어도 마지막 타격은 어긋나지 않는다 |
| 연속 공격 | 그림에 연속 공격(1·2·3타…)이 있으면 대상마다 1타부터 순서대로 친다 — 1·2·3·4·1·2·3·4… 판정 순간에 타격이 닿는 공격이 처치 타다(빨리 죽으면 1타 하나로 끝난다). 대상이 쓰러지면 순서는 1타로 돌아간다. 처치 타가 판정에 정확히 닿도록 공격 한 번의 길이(0.6초)를 슬롯마다 조금 늘이거나 줄인다. 연속 공격이 없는 그림은 공격 하나를 반복한다. 공격 한 번 0.6초는 타마다 같다 |
| 끊김 없이 이어진다 | 처치는 루프의 한 장면일 뿐, 초기화가 아니다. 배경의 흐른 거리는 계속 쌓이고(처치·주기 변경에도 이어진다), 캐릭터는 마무리 공격을 타격 뒤까지 마저 한 다음(여운 0.3초) 그 자리에서 다시 달린다. 쓰러진 대상은 그 자리에서 사라지고(0.3초), 땅이 흐르기 시작하면 땅과 함께 흘러간다 |
| 숨 | 달리기 ↔ 공격이 바뀔 때 대기 자세를 0.1초 끼운다(처치 여운 → 숨 → 달리기 → 숨 → 공격). 바로 맞붙으면 뚝뚝 끊겨 보인다 |
| 짧은 주기 | 실효 주기가 "여운 + 숨 + 다가오기 + 타격까지"보다 짧으면 여운 → 숨 → 다가오기 순으로 줄인다 — 다가오기 = min(1초, 주기 − 타격까지 걸리는 시간). 판정 순간은 건드리지 않는다 |
| 시간의 진실 | 연출은 진행도에서 매 프레임 계산한다(배경의 흐른 거리만 누적한다) — 게이지와 같은 계산표(UI/Shared/WorkStationProgress.cs)를 쓴다 → 작업슬롯 3장 |
| 빈 슬롯 | 캐릭터·대상 없이 멈춘 배경만. 빈 슬롯 전용 배경을 넣을 자리가 있다(없으면 기본 배경) |
| 그림 없는 캐릭터 | 전용 그림이 없으면 1번 캐릭터 그림으로 대신 그린다 |
| 위젯 | 스트립의 미니 슬롯은 캐릭터 픽셀 머리만 두고 좌우로 흔든다. 판정 순간 머리 위에서 작은 아이템이 떠오르며 사라진다 — 큰 창과 같은 타이밍. ❌ 미구현 (일감 T-097) |
| 아이템 떠오름 | 처치 순간 큰 창에서도 아이템이 아래→위로 떠오르며 사라진다. ❌ 미구현 (일감 T-097) |
| 멈춤 | 큰 창을 닫으면 큰 창 연출은 그리기를 멈춘다(2.2). 배치된 슬롯의 루프 자체를 멈추는 일은 없다 |
위상을 어긋나게 둔다. 같은 속도의 슬롯이 여러 개면 모두 같은 순간에 처치·드랍해 동기화돼 보인다 (기획평가 — "위젯이 30초마다 5개 동시 발화"). 배치 시각이 슬롯마다 달라 대체로 흩어지지만, 같은 순간에 배치한 슬롯은 겹칠 수 있다.
그림의 규격·가공 절차는 Assets/Art/Art 규칙.md에 있다.
미결
- 판정 주기의 하한 — 산업 Lv1~5에 하한(예: 1초)을 걸어 "다가오기 1초 + 공격 1번"을 늘 보장할지. 하한이 1초면 타격 전 준비 동작(0.2~0.4초)이 들어갈 틈이 없어 다가오기가 그만큼 줄어든다 — 하한은 1초 + 타격까지로 잡아야 온전하다. 서버 판정식·밸런스가 바뀌는 일이라 클라 단독으로 정하지 않는다 → T-102. 지금은 위 "짧은 주기" 규칙으로 버틴다
- 떠오르는 아이템 그림의 출처 — 로컬 타이머가 먼저 닿으므로, 서버 결과를 기다릴지 산업 대표 아이콘으로 먼저 띄울지
3. 데스크톱 환경 제약
바탕화면 상주 앱 특유의 문제들. 기획 단계에서 답이 있어야 한다.
| 제약 | 논점 | 상태 |
|---|---|---|
| 해상도·DPI 변경 | 위치·크기 보존 | ✅ 해소. 창이 16:9 고정 배율이라 CanvasScaler가 UI를 비례시키고, 위젯은 창 안 6칸 프리셋이라 좌표를 저장하지 않는다 (2장). 고른 배율·9분할 앵커·창 상태 토글은 PlayerPrefs에 저장돼 재실행 시 그대로 복원된다 |
| 멀티 모니터 | 어느 모니터에 뜨는가? | ⏸ 창 위치는 9분할 앵커로 정해졌고 모니터 선택만 남았다 |
| 전체화면 앱 | 게임·영상 실행 중 자동 숨김? | ❌ 미결 |
| 절전·최대 절전 | 복귀 시 경과 시간 정산 → 자원채취 2.2 | ❌ 미결 |
| 시작 프로그램 | 부팅 시 자동 실행 옵션 | ❌ 미결 |
| 트레이 | 위젯 숨김 시 트레이 상주 | ❌ 미결 |
| 리소스 사용량 | 상시 실행이므로 CPU·메모리 최소화가 필수 요건 | ❌ 상한 미결 |
상시 실행 앱에서 리소스 사용량은 기능이 아니라 생존 조건이다. "게임 때문에 노트북이 느려진다"는 즉시 삭제 사유다. 1장의 연출 2레이어가 이 요구에 대한 구조적 답이다 — 창을 닫으면 그리기를 멈춘다.
4. 아트 방향
| 항목 | 내용 |
|---|---|
| 스타일 | Pixel + Stylized (AI 생성) |
| 레퍼런스 | 테스크바 히어로 — 창 프레임·아이콘 격자·위치 선택 UI (참고 사진) |
| 희귀도 색상 | GlobalRarity enum에 이미 정의됨 — UI 전반에서 이 값을 따른다 (구 ItemRarity, 2026-08-02 개명) |
| 톤 | 업무 환경과 충돌하지 않는 채도 |
| 사운드 | 미정. 기본 무음 권장 |
희귀도 색상 (Enum.xlsx 확정값):
| 등급 | 색상 |
|---|---|
| Common | #9D9D9D |
| Uncommon | #1EFF00 |
| Rare | #0070DD |
| Epic | #A335EE |
| Legendary | #FF8000 |
| Mythic | #E6CC80 |
5. 구현 접점
| 영역 | 위치 |
|---|---|
| 씬 · UI 골격 | Assets/Scenes/DesktopWindow_Control.unity — Root Canvas → !Horizental Columns → 세 열(@Storage/@Main/@Market Column). 로그인 화면은 열 밖에 !Login Canvas로, 로딩·알림은 그보다 위 !System Canvas로 따로 선다. 오브젝트 이름은 접두사로 계층(!·@·#), 표기로 MVP 역할((MODEL)·(MAIN VIEW)·(↓ SUB VIEW)) 을 나타낸다 |
| 위젯 6칸 배치 | Assets/Scripts_Client/UI/Layout/WidgetPositionLayout.cs — 좌표를 계산하지 않는다 — 형제 순서 + 3열의 자식 정렬을 바꾸고, 사이드 칸의 높이만 계산한다. 위 칸이면 열 정렬을 UpperCenter, 아래 칸이면 LowerCenter로 뒤집어 위젯이 창 가장자리에 붙는다(정렬 조합은 코드 상수 — 위치에서 따라 나오므로 고를 여지가 없다). 가운데를 뺀 나머지 높이는 위젯 쪽 2 : 상태 쪽 1로 나눠 preferredHeight에 숫자로 써 넣는다 |
| 창 제어 (크기 배율 · 9분할 · 투명 · 클릭스루) | Assets/Scripts_Client/Managers/WindowManager.cs |
| 설정 입력 | Assets/Scripts_Client/UI/Main/SettingPresenter/SettingPresenter.cs — 창 제어(Win32)와 일반 설정(위젯 6칸)을 한 패널에서 받아 각 담당자에게 넘긴다. 거래 열에 얹혀 있던 패널이 #Main Canvas 안으로 옮겨져 작업슬롯과 자리를 나눠 쓴다 |
| 설정 저장 | Assets/Scripts_Client/Settings/WindowSettings.cs — 창 설정 6종 + 위젯 위치를 PlayerPrefs에 보존 |
| 화면 골격 조율 (3열 + 위젯 여닫기) | Assets/Scripts_Client/Managers/UIManager.cs — 2.0의 진입 순서를 ToggleAll/OpenWorkStation/ToggleStorage/ToggleMarket로 구현. 여닫는 대상은 Column이 아니라 그 안의 Canvas — 열 폭이 유지돼야 위젯이 6칸 자리에서 안 움직인다 |
| 메인 화면 전환 (슬롯 목록 ↔ 슬롯 선택 ↔ 설정 ↔ …) | UIManager의 MainScreen enum + ShowMainScreen/ToggleMainScreen. #Main Canvas 안에서 Title과 Menu Presenter 사이의 한 칸을 나눠 쓰는 화면들을 갈아 끼운다. 여는 입구는 둘 — 상태 패널의 버튼, 그리고 슬롯 목록의 칸 클릭. 같은 버튼을 다시 누르면 기본(슬롯 목록)으로 돌아오고, 전체를 접으면 다음에 열 화면도 슬롯 목록으로 리셋된다. 캔버스 머리의 제목도 화면마다 바뀐다(MainCanvasView.SetTitle, 문구는 인스펙터) |
| 각 열·칸의 화면 | 캔버스는 전부 ...CanvasView(여닫기만), 내용은 그 아래 ...Presenter가 그린다 — UI/Storage/StorageCanvasView + StorageTabPresenter·StorageGridPresenter·SellCartPresenter · UI/Main/MainCanvasView + WorkStationListPresenter·WorkStationSelectPresenter·SettingPresenter·MenuPresenter · UI/State/StateCanvasView + StatePresenter · UI/Market/MarketCanvasView + GachaPresenter · UI/Widget/WidgetCanvasView + WidgetPresenter · UI/Login/LoginCanvasView + LoginPresenter |
| 작업슬롯 3단계 (목록 → 캐릭터 고르기 → 세팅) | 목록과 선택은 #Main Canvas의 형제 화면이라 전환을 UIManager가 한다 — WorkStationListPresenter(칸 8개·카운트다운) ↔ WorkStationSelectPresenter(배치·해제). 캐릭터 줄은 CharacterStateRowView. 하단 인벤토리·거래 버튼은 MenuPresenter. 참조는 목록→선택 한 방향뿐이다(슬롯 번호를 넘기려고). 고른 산업의 적성 0이면 줄을 남긴 채 버튼만 잠근다(6장 #11) — 적성은 PlayerDataModel.GetAptitude로 패킷에서 읽는다 |
| 상주 위젯의 표시 (골드 · 가동 슬롯 · 수확 스트립) | Assets/Scripts_Client/UI/Widget/WidgetPresenter/ — 상단 줄은 PlayerDataModel의 CurrencyChanged·WorkStationSlotsChanged를 구독하고, 아래 스트립은 배치된 칸만 왼쪽부터 WidgetMiniSlotView로 만든다(빈 칸 없음 — 위젯은 눌러 배치하는 화면이 아니다). 카운트다운은 큰 창의 목록과 같은 계산표를 쓴다(UI/Shared/WorkStationProgress.cs) — 복사하면 서버 판정식이 두 벌이 된다. ⏸ 지금 도는 것은 게이지뿐이고 캐릭터 그림·수확 표시·시간당 산출·누적 수확은 자리만 잡혀 있다(산출 정의는 6장 미결) |
| 대기·알림·결과 오버레이 | !System Canvas(UI/System/SystemCanvasView) — 최상단 상주 오버레이 셋. LoadingPresenter(서버 응답 대기 표시, 0.15초 안에 끝나면 아예 안 뜬다) + GachaResultPresenter(가챠로 뽑힌 목록을 5열 × n행으로, 닫기 전까지 유지 — 칸마다 수량은 끈다) + NoticePresenter(실패·무응답 사유, 연결 끊김은 확인 후 앱 종료). 판단은 Managers/ServerWaitManager.cs가 하고(요청당 5초 타임아웃), 서버 결과 코드→문구는 UI/Shared/ResultMessages.cs, 등급→표시색은 UI/Shared/RarityPalette.cs. 가챠 결과가 거래 열이 아니라 여기 있는 이유 — 요청을 보낸 뒤 사용자가 거래 열을 닫아도 결과가 떠야 한다 |
| 로그 | Log/ClientLogger.cs — 출력 창구·태그 규약. 무엇을 남길지는 부르는 쪽이 정한다. 서버 수신을 콘솔에 풀어 주던 임시 관찰자는 대체 화면(가챠 결과 팝업 · 위젯 수확 스트립)이 갖춰져 없앴다 |
| 서버 상태 캐시 (인벤토리 · 슬롯 · 캐릭터 · 재화) | Assets/Scripts_Client/Managers/PlayerDataModel.cs — MVP의 Model. 수신 전담이고 요청은 각 Presenter가 직접 보낸다 |
| 클라이언트 코드 | Assets/Scripts_Client/ — UI Toolkit을 쓰지 않는 MVP(Legacy). UI/는 <캔버스>/<Presenter>/ 두 단 구조이고, 접미사는 MVP 역할(...Model·...Presenter·...CanvasView·...View)을 따른다. 하이어라키는 접두사로 계층(!·@·#), 표기로 역할((MODEL)·(MAIN VIEW)·(↓ SUB VIEW))을 나타내고, 오브젝트 이름의 Presenter/Panel이 "화면"과 "그 안의 정렬 상자"를 가른다. 규칙은 UI 규칙 |
| 네트워크 연동 | Assets/Scripts_Server/Network/ |
| 코드 스타일 | .claude/skills/client/clean-code-style |
| 기능 설계 | .claude/skills/client/feature-design |
| 성능 | .claude/skills/client/optimization — 상시 실행이므로 특히 중요 |
| 에디터 작업 | .claude/skills/client/unity-editor-ops |
6. 결정 필요 (Open Questions)
- 위젯의 크기·형태는? — ⏸ 배치는 해소됐다 (창 안 6칸 프리셋 · 2.1). 크기와 형태는 여전히 미정이다.
- 항상 위(Always on top) 기본값은 켜짐인가 꺼짐인가?
- 전체화면 앱 감지 시 자동 숨김을 넣는가?
- 트레이 상주를 지원하는가?
- 사운드를 넣는가? 넣으면 기본 꺼짐인가?
- 목표 리소스 사용량 상한은? (CPU %, 메모리 MB)
상시 스트립의 방향은?✅ 해소 (2026-08-26) — 가로. 위젯이 창 안 6칸 중 한 칸을 가로로 길게(폭 633 × 높이 87) 차지하므로, 같은 자리에 세로 스트립을 세우면 칸 크기가 87px 안에 갇힌다. ⚠️ 폭이 늘어나는 단점은 그대로 안고 간다 — 슬롯 8개면 칸(49) + 간격(4)으로 약 420px를 쓴다. 위젯 폭(633)에는 들어가지만 슬롯이 8을 넘으면 다시 봐야 한다. → v2 목업 상단의 위젯 스트립 토글에서 3안을 비교할 수 있다.3열 패널을 동시에 띄우는가?✅ 해소 (2026-08-01) — 상주하는 것은 위젯뿐이다. 3열은 필요할 때 여는 큰 창이고, 진입점은 작업슬롯 캔버스다 (1장 · 2.0).상점은 골드 상점인가 현금 상점인가?✅ 해소 (2026-08-01) — 골드 상점 (1장). 품목은 미정이다 — 작업슬롯 확장권은 상점 품목이 아니다 (2026-09-16 · 잠긴 칸에서 직접 연다 → 해금 4.1). ⚠️ 가챠는 상점 품목이 아니다 — 골드를 직접 내고 뽑는 별도 화면이다 → 캐릭터 5.1. ⚠️ 슬롯 해금은 잠긴 칸의 조건 표시(골드·선행)가 담당한다 → T-039.- 해금하지 않은 산업 레벨은 보여 준다 — 조건과 함께 ✅ (2026-09-14 → 해금 7장). 2.4의 "비어 있을 때는 잠긴 표시를 보여 주지 않는다"는 기획이 없는 콘텐츠 자리에 대한 규칙이고, 해금 대상(슬롯·산업 레벨·특성)은 전부 보인다. 여기서는 보여 줘도 P1과 충돌하지 않을 수 있다. → 산업 레벨
적성 0 캐릭터를 배치 선택창에 보여 주는가?✅ 해소 (2026-08-10) — 보여 주되 잠근다. 질문이 남아 있던 근거("작업슬롯 3.4는 적성 0도 배치 가능이라는데 목업은 제외한다")가 이미 낡은 서술이었다. 3.4는 2026-08-01에 적성 0 = 배치 불가로 재확정되면서 표에 "배치 UI: 적성 0 캐릭터를 잠금 표시" 를 함께 못 박았다 — 즉 제외(숨김)가 아니다. 목록에는 남기고 버튼만 잠근다. 숨기면 "내 캐릭터가 왜 안 보이지"가 되고, 장비 등으로 적성 0 → 1 승격이 생겼을 때 화면이 조용히 틀린다. → 구현 완료 (WorkStationSelectPresenter· 이슈 #13).작업슬롯 캔버스 하단 버튼 3~5번에 무엇이 들어가는가?✅ 해소 (2026-09-16) — 2.4의 특별 이벤트 자리와 같은 줄이다. 별도 층을 두지 않는다.인벤토리·거래옆 빈 자리에 채취 루프 밖의 콘텐츠(보스 · 대형 작업물)가 들어오고, 줄 높이가 고정이라 버튼이 늘어도 작업슬롯 영역은 밀리지 않는다. 무엇이 들어가는지는 여전히 미기획이다 — 2.4의 후보 표를 따른다.적성 포인트를 어디서 찍는가?✅ 없어짐 (2026-10-06). 레벨 효과가 작업속도 자동 가산으로 바뀌어 찍는 화면 자체가 사라졌다 → 캐릭터 5.4 · 이슈 #35.위젯이 좌·우 끝일 때 3열을 어떻게 두는가?✅ 해소 (2026-08-01). 작업슬롯과 인벤토리는 항상 붙어 있고, 거래를 가장 먼 끝에 둔다 → 2.1 3열 순서 규칙. 동선의 핵심은 좌우 방향이 아니라 "재료 → 작업 → 시장"의 인접 관계이므로 2.0.1과 충돌하지 않는다.