๐Ÿฐ [flowbit] #7. Workspace UI - ํ๋ฆ„์„ ๋ณด์ด๊ฒŒ ๋งŒ๋“  ๋‚ 

bean8080๐Ÿซ›ยท2026๋…„ 5์›” 2์ผ

flowbit ๐Ÿฐโ˜˜๏ธ

๋ชฉ๋ก ๋ณด๊ธฐ
8/15

โ˜˜๏ธ 1. ์˜ค๋Š˜ ๋ชฉํ‘œ

์–ด์ œ๊นŒ์ง€๋Š”

์ด๋ฒคํŠธ๋ฅผ ๊ธฐ๋กํ•˜๊ณ 
๊ทธ ์ด๋ฒคํŠธ๋ฅผ ํ•ด์„ํ•ด์„œ
ํ”„๋กœ์ ํŠธ ์ƒํƒœ๋ฅผ ๋„์ถœํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค

์ฆ‰,

๋ฐ์ดํ„ฐ๋Š” ์™„์„ฑ๋œ ์ƒํƒœ

โ†’ ๋ฐฑ์—”๋“œ ๊ธฐ์ค€์—์„œ๋Š” ์ด๋ฏธ ๋ชจ๋“  ์ •๋ณด๊ฐ€ ๊ณ„์‚ฐ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์˜€๋‹ค

๊ทผ๋ฐ ๋ฌธ์ œ๋Š” ํ•˜๋‚˜์˜€๋‹ค.

โ†’ ์ด๊ฒŒ ๋ˆˆ์— ์•ˆ ๋ณด์ธ๋‹ค

๊ทธ๋ž˜์„œ ์˜ค๋Š˜ ๋ชฉํ‘œ๋Š” ๋ช…ํ™•ํ–ˆ๋‹ค.

โ†’ ํ๋ฆ„์„ ๋ณด์ด๊ฒŒ ๋งŒ๋“ค์ž


โ˜˜๏ธ 2. ํ”„๋ก ํŠธ์—”๋“œ ๊ตฌ์ถ• (React + Vite)

์˜ค๋Š˜์€ ์ฒ˜์Œ์œผ๋กœ ํ”„๋ก ํŠธ๋ฅผ ๋ถ™์˜€๋‹ค.

Vite + React + TypeScript ํ™˜๊ฒฝ ์„ธํŒ…
axios ๊ธฐ๋ฐ˜ API ํ†ต์‹  ๋ชจ๋“ˆ ๋ถ„๋ฆฌ
taskApi, projectApi ๊ตฌ์กฐ ์„ค๊ณ„

ํ”„๋ก ํŠธ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

Vite ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ or src ํด๋” ์บก์ณ

์ด์ œ๋ถ€ํ„ฐ๋Š”

API๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ
์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋‹จ๊ณ„


โ˜˜๏ธ 3. Task ๋ฆฌ์ŠคํŠธ โ†’ Workspace ๊ตฌ์กฐ

์ดˆ๊ธฐ UI๋Š” ๋‹จ์ˆœํ–ˆ๋‹ค.

Task 1
Task 2
Task 3

๊ทผ๋ฐ ์ด๊ฑด Flowbit ๋ฐฉํ–ฅ์ด ์•„๋‹ˆ์—ˆ๋‹ค.

Flowbit์€

์ž‘์—… ํ๋ฆ„์„ ๋ณด๋Š” ์‹œ์Šคํ…œ

๊ทธ๋ž˜์„œ ๊ตฌ์กฐ๋ฅผ ๋ฐ”๊ฟจ๋‹ค.

Project
 โ”œโ”€ Task
 โ”œโ”€ Task
 โ””โ”€ Task

Project ์ค‘์‹ฌ์œผ๋กœ ์ž‘์—…์„ ๋ฌถ์–ด
ํ๋ฆ„ ๋‹จ์œ„๋กœ ๋ณผ ์ˆ˜ ์žˆ๋Š” Workspace ๊ตฌ์กฐ๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ค


โ˜˜๏ธ 4. CRUD ๊ธฐ๋Šฅ ์ „์ฒด ์—ฐ๊ฒฐ

ํ”„๋ก ํŠธ์—์„œ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ง์ ‘ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค

ํ”„๋กœ์ ํŠธ

  • ์ƒ์„ฑ
  • ์ˆ˜์ •
  • ์‚ญ์ œ

์ž‘์—…(Task)

  • ์ƒ์„ฑ
  • ์ƒํƒœ ๋ณ€๊ฒฝ (์‹œ์ž‘ / ์™„๋ฃŒ / ๋ณด๋ฅ˜)
  • ์‚ญ์ œ
  • ์ˆ˜์ • (์ œ๋ชฉ + ์„ค๋ช…)

์ž‘์—… ์ƒ์„ฑ / ์ƒํƒœ ๋ณ€๊ฒฝ ๋ฒ„ํŠผ UI

์ด์ œ๋Š”

Postman ์—†์ด UI์—์„œ ์ง์ ‘ ์กฐ์ž‘ ๊ฐ€๋Šฅํ•˜๋‹ค

๊ฐ ์•ก์…˜์€ axios ๊ธฐ๋ฐ˜ API ํ˜ธ์ถœ๋กœ
๋ฐฑ์—”๋“œ์™€ ๋ฐ”๋กœ ์—ฐ๊ฒฐ๋˜๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค


โ˜˜๏ธ 5. ์ƒํƒœ๊ฐ’ UI ๊ฐœ์„ 

๊ธฐ์กด ์ƒํƒœ:

TODO / IN_PROGRESS / BLOCKED / DONE

๋ณ€๊ฒฝ:

๋Œ€๊ธฐ / ์ง„ํ–‰์ค‘ / ๋ณด๋ฅ˜ / ์™„๋ฃŒ

๊ทธ๋ฆฌ๊ณ 

  • ์ƒํƒœ๋ณ„ ์ƒ‰์ƒ ์ ์šฉ
  • ์‚ฌ์šฉ์ž ๊ธฐ์ค€์œผ๋กœ ๊ฐ€๊ณต๋œ ํ‘œํ˜„ ์‚ฌ์šฉ

โ†’ ์‹œ๊ฐ์  ํ”ผ๋“œ๋ฐฑ ๊ฐ•ํ™”


โ˜˜๏ธ 6. UI/UX ๊ฐœ์„ 

๊ฐœ๋ฐœ์šฉ UI์—์„œ ์„œ๋น„์Šค UI๋กœ ์ „ํ™˜ํ–ˆ๋‹ค

  • ๋‹คํฌ ํ…Œ๋งˆ โ†’ ๋ฐ์€ ํ…Œ๋งˆ
  • ์นด๋“œํ˜• UI ์ ์šฉ
  • ๋ฒ„ํŠผ ์Šคํƒ€์ผ ๊ฐœ์„ 
  • ์ž…๋ ฅ ์˜์—ญ๊ณผ ์•ก์…˜ ๋ฒ„ํŠผ ๋ถ„๋ฆฌ

โ†’ ์‚ฌ์šฉ ํ๋ฆ„์„ ๋‹จ์ˆœํ™”


โ˜˜๏ธ 7. soft delete + ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ

๋ฌธ์ œ:

โ†’ ํ”„๋กœ์ ํŠธ ์‚ญ์ œ ์‹œ Task๋Š” ๋‚จ์•„์žˆ์Œ

ํ•ด๊ฒฐ:

task.delete();

์‚ญ์ œ๋œ ํ”„๋กœ์ ํŠธ์˜ Task๋Š” ํ™”๋ฉด์—์„œ ์ œ์™ธ
์กฐํšŒ ์กฐ๊ฑด์—์„œ๋„ ์ œ์™ธ๋˜๋„๋ก ํ†ต์ผ

โ†’ ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ ๋ฌธ์ œ ํ•ด๊ฒฐ


โ˜˜๏ธ 8. ํ”„๋กœ์ ํŠธ ์ƒํƒœ ๊ตฌ์กฐ ๋ฆฌํŒฉํ† ๋ง ๐ŸŒŸ

๊ธฐ์กด:

Project.status = DB ๊ฐ’

๋ณ€๊ฒฝ:

Project.status = Task ์ƒํƒœ ๊ธฐ๋ฐ˜ ๊ณ„์‚ฐ
if (tasks.isEmpty()) return "READY";
if (hasBlocked) return "BLOCKED";
if (hasInProgress) return "IN_PROGRESS";
if (allDone) return "DONE";

โ†’ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ๋„์ถœํ•œ๋‹ค

์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋ฉด ๋™๊ธฐํ™” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ Task ๊ธฐ์ค€์œผ๋กœ ๊ณ„์‚ฐํ•˜๋„๋ก ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ–ˆ๋‹ค


โ˜˜๏ธ 9. ํƒ€์ž„๋ผ์ธ UI ๊ตฌํ˜„ ๐ŸŒŸ

GET /api/projects/{id}/timeline

ํƒ€์ž„๋ผ์ธ ์ดˆ๊ธฐ ๊ฒฐ๊ณผ

์ด๋ฒคํŠธ๊ฐ€ ์‹œ๊ฐ„์ˆœ์œผ๋กœ ๋‚˜์—ด๋  ๋ฟ ์ž‘์—… ๋‹จ์œ„ ํ๋ฆ„์ด ๋ณด์ด์ง€ ์•Š์•˜๋‹ค


โ˜˜๏ธ 10. ํ•ด๊ฒฐ: Task ๊ธฐ์ค€ ๊ทธ๋ฃนํ•‘

timeline.reduce((acc, event) => {
  if (!acc[event.taskId]) {
    acc[event.taskId] = {
      taskTitle: event.taskTitle,
      events: [],
    };
  }
  acc[event.taskId].events.push(event);
  return acc;
}, {});

๊ฒฐ๊ณผ:

ํ˜„์žฌ ํƒ€์ž„๋ผ์ธ ํ™”๋ฉด ์บก์ณ

taskId ๊ธฐ์ค€์œผ๋กœ ์ด๋ฒคํŠธ ๊ทธ๋ฃนํ•‘
์ž‘์—… ๋‹จ์œ„ ํ๋ฆ„์œผ๋กœ ์žฌ๊ตฌ์„ฑ

๋‹จ์ˆœ ๋กœ๊ทธ โ†’ ํ๋ฆ„ ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜


โ˜˜๏ธ 11. ํ”„๋กœ์ ํŠธ ์š”์•ฝ UI

GET /api/projects/{id}/analysis

์š”์•ฝ ์นด๋“œ UI

  • ์ „์ฒด ์ž‘์—… ์ˆ˜
  • ์ง„ํ–‰์ค‘ / ์™„๋ฃŒ / ๋ณด๋ฅ˜
  • ๋งˆ์ง€๋ง‰ ํ™œ๋™

โ†’ ํ”„๋กœ์ ํŠธ ์ƒํƒœ๋ฅผ ํ•œ๋ˆˆ์— ํŒŒ์•… ๊ฐ€๋Šฅ


โ˜˜๏ธ 12. ์š”์ฒญ ์ฒ˜๋ฆฌ ์•ˆ์ •ํ™”

  • ์š”์ฒญ ์ค‘ ๋ฒ„ํŠผ ๋น„ํ™œ์„ฑํ™” (์ค‘๋ณต ์š”์ฒญ ๋ฐฉ์ง€)
  • ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ
  • ์ž…๋ ฅ ์•ˆ์ •์„ฑ ํ™•๋ณด

โ˜˜๏ธ 13. ์˜ค๋Š˜ ์ •๋ฆฌ

  • ํ”„๋ก ํŠธ + ๋ฐฑ์—”๋“œ ์—ฐ๊ฒฐ
  • Workspace UI ๊ตฌํ˜„
  • CRUD ๊ธฐ๋Šฅ ์™„์„ฑ
  • ์ƒํƒœ ๊ณ„์‚ฐ ๊ตฌ์กฐ ๋ฆฌํŒฉํ† ๋ง
  • ํƒ€์ž„๋ผ์ธ + ์š”์•ฝ UI ๊ตฌํ˜„

โ˜˜๏ธ 14. ํ˜„์žฌ ์ƒํƒœ

Project โœ”๏ธ
Task โœ”๏ธ
TaskEvent โœ”๏ธ
Timeline โœ”๏ธ
Analysis โœ”๏ธ
Workspace UI โœ”๏ธ

โ†’ ๋™์ž‘ํ•˜๋Š” ์„œ๋น„์Šค ์ƒํƒœ


โ˜˜๏ธ 15. ๋‹ค์Œ ๋ชฉํ‘œ

์ด์ œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์€ ๋ชจ๋‘ ๊ตฌํ˜„๋๋‹ค.

ํ˜„์žฌ ์ƒํƒœ๋Š”

  • ํ๋ฆ„์„ ๊ธฐ๋กํ•˜๊ณ 
  • ํ•ด์„ํ•˜๊ณ 
  • ํ™”๋ฉด์œผ๋กœ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ

๋‹ค์Œ ๋‹จ๊ณ„๋Š”

โ†’ ์‹ค์ œ ์„œ๋น„์Šค๋กœ ๋ฐฐํฌํ•˜๊ธฐ

๋„๋ฉ”์ธ ์—ฐ๊ฒฐ
์„œ๋ฒ„ ๋ฐฐํฌ
ํ”„๋ก ํŠธ / ๋ฐฑ์—”๋“œ ์—ฐ๊ฒฐ

์ด์ œ ๋กœ์ปฌ์„ ๋„˜์–ด
์‹ค์ œ ํ™˜๊ฒฝ์—์„œ ๋™์ž‘ํ•˜๋Š” ๋‹จ๊ณ„๋กœ ๋“ค์–ด๊ฐ„๋‹ค

โ†’ ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ๋„˜์–ด์„œ ์„œ๋น„์Šค ๋‹จ๊ณ„๋กœ ์ „ํ™˜

0๊ฐœ์˜ ๋Œ“๊ธ€