Agent Office v2 — Pixel Office UX 대규모 업데이트 설계
참고 프로젝트: pixel-agents (VS Code 확장, React 19 + Canvas 2D)
대상: web-ui/src/pages/agent-office/ (프론트엔드) + web-backend/agent-office/ (백엔드)
1. 목표
기존 대시보드 칼럼 중심 UI를 전체 화면 픽셀 오피스 중심으로 전환하여, "가상 오피스를 사용한다"는 몰입감을 제공한다.
핵심 변경
- 캔버스가 메인 화면을 차지하고, 에이전트 클릭 시 사이드 패널로 상세 정보 표시
- BFS 경로 탐색 + 풀 배회 시스템으로 에이전트에 생동감 부여
- 3가지 오피스 테마 프리셋 (Modern / Retro / Minimal)
- 캐릭터 프로시저럴 고도화 + 스프라이트 로더 설계 (점진적 전환)
변경하지 않는 것
- 백엔드 FSM 5상태 (
idle, working, waiting, reporting, break)
- WebSocket 프로토콜 메시지 타입 (init, agent_state, task_complete, agent_move, notification, command_result)
- REST API 엔드포인트
- 텔레그램 봇 연동
2. 화면 구성
2.1 데스크톱 레이아웃
- 상단 바: 타이틀, WebSocket 연결 상태(●), 테마 드롭다운, 줌 컨트롤 (1x~4x)
- 캔버스:
flex: 1로 남은 공간 전체 차지, imageSmoothingEnabled = false
- 사이드 패널: 320px 고정폭, 에이전트 클릭 시 슬라이드 인, X 버튼 또는 빈 공간 클릭으로 닫힘
- 패널 닫힘 시: 캔버스가 전체 너비로 확장
2.2 모바일 레이아웃 (< 768px)
- 캔버스: 전체 화면, 터치 핀치 줌/패닝
- 사이드 패널 → 바텀 시트 (에이전트 탭 시 올라옴, 아래로 드래그 시 닫힘)
- 상단 바: 햄버거 메뉴로 테마/줌 접기
3. 사이드 패널 구조
3.1 헤더
- 에이전트 아이콘 (emoji 기반, 32x32 색상 배경)
- display_name + 현재 상태 + state_detail
3.2 탭 구성
| 탭 |
내용 |
| Commands (기본) |
Quick Action 버튼 (에이전트별 고유), Custom Command 입력, Approval UI (waiting 상태 시) |
| Tasks |
최근 작업 이력 (상태 배지, 타임스탬프, 결과 펼치기) |
| Tokens |
일간/주간 토큰 사용량 차트, 캐시 히트율 |
| Logs |
에이전트 로그 스트림 (level별 색상, 자동 스크롤) |
3.3 에이전트별 Quick Actions
| 에이전트 |
버튼 |
| Stock |
Fetch News, Add Alert, Test Telegram |
| Music |
Compose, Check Credits |
| Blog |
Research, Add Keyword, List Keywords |
| Realestate |
Fetch Matches, Dashboard |
| Lotto |
Curate Now, Status |
4. 캔버스 엔진
4.1 타일맵
- 그리드: 32 × 20 타일 (기존 20×14에서 확장)
- 타일 크기: 32px × 32px (기본), 줌에 따라 스케일
- 타일 타입: VOID(0), FLOOR(1), WALL(2), FURNITURE(3)
- 렌더링 순서: 바닥 → 벽 → 가구 → 에이전트 (Y좌표 Z-sorting) → 오버레이
4.2 오피스 레이아웃 (고정)
- 각 에이전트 구역에 테마별 소품 (Stock: 모니터 3대, Music: 악기, Blog: 서류 등)
- 중앙: 회의 테이블 (4x2 타일)
- 하단: 휴게실 구역 (커피 머신 + 소파)
- waypoint 정의:
desk_stock, desk_music, desk_blog, desk_realestate, desk_lotto, meeting, break_room, coffee
4.3 줌 & 패닝
- 줌 레벨: 1x, 2x, 3x, 4x (정수 배율만, 픽셀 선명도 유지)
- 데스크톱: 마우스 휠 줌, 드래그 패닝
- 모바일: 핀치 줌, 터치 패닝
- 기본값: 캔버스 크기에 맞춰 자동 fit
4.4 게임 루프
- 60fps requestAnimationFrame
imageSmoothingEnabled = false (픽셀 선명도)
- devicePixelRatio 반영
5. 에이전트 캐릭터 시스템
5.1 프로시저럴 렌더링 (Phase 1)
- 해상도: 16 × 32px (기존 8×16에서 2배 확대)
- 에이전트별 고유 색상 (기존 유지)
- 애니메이션 프레임:
| 상태 |
프레임 수 |
속도 |
설명 |
| idle |
2 |
0.8s/frame |
미세 움직임 (숨쉬기) |
| walk |
4 |
0.15s/frame |
걷기 사이클 [0,1,2,1] |
| type |
2 |
0.3s/frame |
타이핑 (팔 움직임) |
| wait |
2 |
0.5s/frame |
좌우 흔들림 (wobble) |
| break |
2 |
1.0s/frame |
커피 마시기 / 졸기 |
- 4방향 스프라이트: DOWN, UP, RIGHT, LEFT (LEFT = RIGHT 좌우반전)
5.2 스프라이트 로더 (Phase 2 준비)
- 스프라이트시트 규격: 각 프레임 16×32px, 가로로 프레임 나열
- 행: 방향 (DOWN/UP/RIGHT), 열: 상태별 프레임
- PNG 없으면 프로시저럴 폴백 → 에셋 제작 전에도 완전 동작
6. 이동 시스템
6.1 BFS 경로 탐색
- 가구 footprint →
blocked[] 배열로 타일 마킹
- 의자/책상 뒤 타일은 walkable (backgroundTiles 개념)
- 경로 없으면 제자리 유지
6.2 이동 파라미터
| 파라미터 |
값 |
설명 |
| WALK_SPEED |
48 px/sec |
pixel-agents 참고 |
| moveProgress |
0~1 |
현재 타일 → 다음 타일 선형 보간 |
| direction |
DOWN/UP/RIGHT/LEFT |
이동 방향 → 스프라이트 방향 결정 |
6.3 배회 로직 (idle 상태)
6.4 상태 전환 시 이동 시퀀스
| 전환 |
동작 |
* → working |
배회 중단, 자기 책상으로 BFS 이동 → 도착 후 type 애니메이션 |
* → waiting |
자기 책상에서 wobble 애니메이션 + 말풍선 |
* → reporting |
자기 책상에서 빠른 type 애니메이션 |
idle (배회 중) |
랜덤 floor 타일로 이동, wanderCount 소진 시 복귀 |
* → break |
휴게실(break_room/coffee) waypoint로 BFS 이동 → break 애니메이션 |
break → idle |
자기 책상으로 BFS 이동 → idle 루프 시작 |
7. 오버레이 시스템
캔버스 위에 HTML이 아닌 Canvas 2D로 직접 렌더링.
7.1 항상 표시
- 이름 라벨: 에이전트 아래, 에이전트 색상 텍스트, 12px
- 상태 배지: 이름 아래, 배경색 + 텍스트 ("working", "idle", "break")
7.2 조건부 표시
- 말풍선:
waiting 상태에서만, 에이전트 위에 "승인 대기!" 텍스트
- 둥근 사각형 배경 (#fbbf24), 아래 삼각형 꼬리
- 2초 페이드인, 상태 변경 시 즉시 사라짐
- 알림 배지: 미확인 notification 있을 때, 에이전트 우상단에 빨간 원 + 숫자
7.3 렌더링 순서
8. 테마 시스템
8.1 테마 데이터 구조
const THEMES = {
modern: {
name: 'Modern',
wall: { color: '#1a1a2e', border: '#333', accent: '#8b5cf6' },
floor: { color1: '#2a2a3e', color2: '#323248' },
furniture: { desk: '#3a3a5a', chair: '#4c1d95', monitor: '#5555aa', shelf: '#2a2a4e' },
decor: { plant: '#22c55e', pot: '#4a3a2a', lamp: '#fbbf24', ledStrip: '#8b5cf6' },
lighting: { ambient: 'rgba(139,92,246,0.05)', glow: 'rgba(139,92,246,0.15)' }
},
retro: {
name: 'Retro',
wall: { color: '#2a1a0a', border: '#6a4a2a', accent: '#cc8844' },
floor: { color1: '#4a3a1a', color2: '#3a2a10' },
furniture: { desk: '#6a4a1a', chair: '#8a5a2a', monitor: '#555555', shelf: '#5a3a1a' },
decor: { plant: '#44aa44', pot: '#6a4a2a', lamp: '#ffcc66', brick: '#8a5a2a' },
lighting: { ambient: 'rgba(255,200,100,0.05)', glow: 'rgba(255,200,100,0.2)' }
},
minimal: {
name: 'Minimal',
wall: { color: '#fafafa', border: '#ddd', accent: '#3b82f6' },
floor: { color1: '#e8e8e8', color2: '#f0f0f0' },
furniture: { desk: '#ffffff', chair: '#e0e0e0', monitor: '#333333', shelf: '#f5f5f5' },
decor: { plant: '#86efac', pot: '#ffffff', lamp: '#fbbf24', window: '#e0f0ff' },
lighting: { ambient: 'rgba(59,130,246,0.03)', glow: 'rgba(255,255,255,0.1)' }
}
};
8.2 테마 적용 방식
TileMap.render(theme) — 바닥/벽 색상을 theme에서 읽어 렌더링
FurnitureRenderer.draw(type, theme) — 가구별 프로시저럴 렌더링에 theme 팔레트 적용
- 테마 전환 시 전체 캔버스 리렌더 (레이아웃 변경 없음)
- 사용자 선택은
localStorage에 저장, 기본값: modern
8.3 테마별 고유 데코
| 테마 |
고유 요소 |
| Modern |
LED 스트립 (벽 하단), 네온 글로우, 미니멀 화분 |
| Retro |
벽돌 텍스처, CRT 모니터, 책장(컬러풀 책), 탁상 램프 |
| Minimal |
창문(자연광), 다육이, 깔끔한 화이트 선반 |
9. 히트 테스팅 & 인터랙션
9.1 클릭 처리
9.2 호버 (데스크톱만)
- 에이전트 위 호버 시 커서
pointer로 변경
- 툴팁 불필요 (이름+배지가 항상 표시되므로)
10. WebSocket 연동
기존 프로토콜 100% 유지. 프론트엔드에서 메시지 수신 시 캔버스 상태만 추가 업데이트.
| 메시지 타입 |
캔버스 반응 |
agent_state |
해당 에이전트 FSM 상태 전환 → 애니메이션/위치 변경 트리거 |
agent_move |
target에 따라 BFS 경로 계산 → 이동 시작 |
task_complete |
에이전트 상태를 idle로 전환 |
notification |
에이전트 위 알림 배지 카운트 증가 |
init |
모든 에이전트 초기 위치/상태 설정 |
agent_state 수신 시 이동 로직
11. 파일 구조 (프론트엔드)
삭제 대상
components/AgentColumn.jsx → CommandTab + TaskTab으로 분리
components/CommandColumn.jsx → SidePanel 내 CommandTab으로 통합
components/ChatPanel.jsx → 미사용, 삭제
components/DocumentPanel.jsx → LogTab으로 대체
canvas/SpriteSheet.js → ProceduralSprite.js로 리팩토링
12. 백엔드 변경사항
없음. 기존 WebSocket 프로토콜과 REST API를 그대로 사용한다.
단, agent_move 메시지가 break 전환 시에도 정확히 발송되는지 확인 필요:
base.py의 check_idle_break() → transition('break') → WebSocket broadcast에 agent_move 포함 여부 확인
- 필요 시
transition() 메서드에서 break 상태 전환 시 agent_move 메시지 추가
13. 구현 순서 (Phase 개요)
| Phase |
내용 |
의존성 |
| 1. 캔버스 엔진 |
게임 루프, 타일맵, 줌/팬, 테마 시스템 |
없음 |
| 2. 에이전트 시스템 |
프로시저럴 캐릭터, BFS 경로 탐색, 상태별 애니메이션, 배회 로직 |
Phase 1 |
| 3. 오버레이 |
이름 라벨, 상태 배지, 말풍선, 알림 배지 |
Phase 2 |
| 4. 사이드 패널 |
4탭 구성, Quick Actions, Approval UI |
Phase 1 |
| 5. 페이지 통합 |
AgentOffice.jsx 재작성, WebSocket 연동, 히트 테스팅 |
Phase 1-4 |
| 6. 모바일 대응 |
바텀 시트, 핀치 줌, 터치 이벤트, 반응형 |
Phase 5 |
| 7. 스프라이트 로더 |
SpriteLoader 구현, 폴백 연결 |
Phase 2 |
14. 성공 기준