๐Ÿฐ [flowbit] #3. ์กฐํšŒ API ๊ณ ๋„ํ™” - ํ๋ฆ„์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค

bean8080๐Ÿซ›ยท2026๋…„ 4์›” 28์ผ

flowbit ๐Ÿฐโ˜˜๏ธ

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

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

์–ด์ œ๋Š” TaskEvent๋ฅผ ๋„์ž…ํ•ด์„œ
์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

์˜ค๋Š˜์€ ๊ทธ ๋‹ค์Œ ๋‹จ๊ณ„๋‹ค.

๊ธฐ๋กํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์ค„ ๊ฒƒ์ธ๊ฐ€

๋‹จ์ˆœํžˆ ์ €์žฅํ•˜๋Š” ๊ฑธ ๋„˜์–ด์„œ
์ด์ œ๋Š” ์กฐํšŒ ๊ตฌ์กฐ๋ฅผ ์ œ๋Œ€๋กœ ๋งŒ๋“œ๋Š” ๋‚ ์ด์—ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด,

์ž‘์—…์€ ๊ณ„์† ์Œ“์ด๋Š”๋ฐ
๋ง‰์ƒ ์–ด๋–ค ํ๋ฆ„์œผ๋กœ ์ง„ํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€๋Š”
ํ•œ๋ˆˆ์— ๋ณด๊ธฐ ์–ด๋ ค์šด ์ƒํƒœ์˜€๋‹ค.

ํ•œ๋ˆˆ์— ๋ณด๊ธฐ ์–ด๋ ค์šด ์ƒํƒœ์˜€๋‹ค.

๊ทธ๋ž˜์„œ

๋‹จ์ˆœ ์กฐํšŒ๊ฐ€ ์•„๋‹ˆ๋ผ
ํ๋ฆ„์„ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹์ด ํ•„์š”ํ–ˆ๋‹ค


โ˜˜๏ธ 2. ์ƒํƒœ๋งŒ ์กฐํšŒํ•˜๋Š” ๊ฑด ๋ถ€์กฑํ–ˆ๋‹ค

๊ธฐ์กด์—๋Š” ์ด๋Ÿฐ ์กฐํšŒ๋งŒ ๊ฐ€๋Šฅํ–ˆ๋‹ค.

GET /tasks

์ด๊ฑด ๋‹จ์ˆœํžˆ ์ „์ฒด ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๋Š” ์ˆ˜์ค€์ด๋‹ค.

๊ทผ๋ฐ ์‹ค์ œ๋กœ ํ•„์š”ํ•œ ๊ฑด ์ด๋Ÿฐ ์กฐํšŒ๋‹ค.

GET /tasks?status=TODO
GET /tasks?status=IN_PROGRESS

โ†’ ์ง€๊ธˆ ํ•ด์•ผ ํ•  ์ž‘์—…๋งŒ ๋ณด๊ณ  ์‹ถ๋‹ค
โ†’ ์ง„ํ–‰ ์ค‘์ธ ์ž‘์—…๋งŒ ๋ณด๊ณ  ์‹ถ๋‹ค

๊ทธ๋ž˜์„œ ์ƒํƒœ ๊ธฐ๋ฐ˜ ์กฐํšŒ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

IN_PROGRESS ์ƒํƒœ ์กฐํšŒ ๊ฒฐ๊ณผ

status ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ด์šฉํ•ด IN_PROGRESS ์ƒํƒœ์˜ ์ž‘์—…๋งŒ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.


โ˜˜๏ธ 3. ํ”„๋กœ์ ํŠธ ๊ธฐ์ค€ ์กฐํšŒ๊นŒ์ง€ ํ™•์žฅ

Task์—๋Š” ์ด๋ฏธ projectId๊ฐ€ ์žˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด๋Ÿฐ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.

GET /tasks?projectId=1
GET /tasks?projectId=1&status=TODO

์ด๊ฑด ๋‹จ์ˆœํ•œ ํ•„ํ„ฐ ์ถ”๊ฐ€๊ฐ€ ์•„๋‹ˆ๋ผ,

ํ”„๋กœ์ ํŠธ ๋‹จ์œ„๋กœ ์ž‘์—… ํ๋ฆ„์„ ์กฐํšŒํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“  ๊ฒƒ์ด๋‹ค.

์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋ฌถ์–ด์„œ
๊ฐ™์€ ํ๋ฆ„ ์•ˆ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฐ˜์ด ๋งŒ๋“ค์–ด์ง„ ์…ˆ์ด๋‹ค

์•„์ง Project ๋„๋ฉ”์ธ์€ ์—†์ง€๋งŒ,
์กฐํšŒ ๊ตฌ์กฐ๋Š” ์ด๋ฏธ ๊ทธ๊ฑธ ๊ธฐ์ค€์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

projectId ์กฐ๊ฑด์œผ๋กœ ์กฐํšŒ๋œ Task ๋ชฉ๋ก

projectId๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘์—…์„ ํ•„ํ„ฐ๋งํ•˜์—ฌ,
ํŠน์ • ํ”„๋กœ์ ํŠธ ๋‹จ์œ„๋กœ ์ž‘์—… ๋ชฉ๋ก์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.


โ˜˜๏ธ 4. ์‘๋‹ต ๊ตฌ์กฐ๋ฅผ ๋ฐ”๊ฟจ๋‹ค โญ

๊ธฐ์กด ์‘๋‹ต์€ ์ด๋žฌ๋‹ค.

{
  "id": 1,
  "title": "...",
  "status": "TODO"
}

๊ทผ๋ฐ ์ด๊ฑด ํ˜„์žฌ ์ƒํƒœ๋งŒ ๋ณด์—ฌ์ค€๋‹ค.

๊ทธ๋ž˜์„œ ์‘๋‹ต์„ ์ด๋ ‡๊ฒŒ ํ™•์žฅํ–ˆ๋‹ค.

{
  "id": 1,
  "projectId": 1,
  "status": "IN_PROGRESS",
  "createdAt": "...",
  "startedAt": "...",
  "completedAt": null
}

์ด์ œ๋Š” ๋‹จ์ˆœ ๋ชฉ๋ก์ด ์•„๋‹ˆ๋ผ

์ด ์ž‘์—…์ด ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๊ณ  ์–ธ์ œ ์‹œ์ž‘๋๊ณ 
์ง€๊ธˆ ์–ด๋””๊นŒ์ง€ ์™”๋Š”์ง€๋ฅผ ๊ฐ™์ด ๋ณด์—ฌ์ค€๋‹ค.

โ†’ ์กฐํšŒ API ์ž์ฒด๊ฐ€ ํ๋ฆ„ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ฒŒ ๋๋‹ค.

โ€ป ์ด ๋ถ€๋ถ„์€ ์œ„์— ์ฒจ๋ถ€๋œ Task ์กฐํšŒ ์‘๋‹ต ์ด๋ฏธ์ง€๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


โ˜˜๏ธ 5. ์ด๋ฒคํŠธ ์กฐํšŒ ์•ˆ์ •์„ฑ ๋ณด๊ฐ•

๊ธฐ์กด์—๋Š” ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

GET /tasks/999/events

โ†’ ์กด์žฌํ•˜์ง€ ์•Š๋Š” Task์ธ๋ฐ๋„ ๊ทธ๋ƒฅ ๋นˆ ๋ฐฐ์—ด ๋ฐ˜ํ™˜

์ด๊ฑด ์• ๋งคํ•˜๋‹ค.

Task๊ฐ€ ์—†๋Š” ๊ฑด์ง€
์ด๋ฒคํŠธ๊ฐ€ ์—†๋Š” ๊ฑด์ง€

๊ตฌ๋ถ„์ด ์•ˆ ๋œ๋‹ค.

๊ทธ๋ž˜์„œ ์ด๋ฒคํŠธ ์กฐํšŒ ์ „์—
Task ์กด์žฌ ์—ฌ๋ถ€๋ฅผ ๋จผ์ € ๊ฒ€์ฆํ•˜๋„๋ก ์ˆ˜์ •ํ–ˆ๋‹ค.

โ†’ ์ด์ œ๋Š” ์—†๋Š” Task๋Š” ๋ช…ํ™•ํ•˜๊ฒŒ ์—๋Ÿฌ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค.


โ˜˜๏ธ 6. ํƒ€์ž„๋ผ์ธ API ๐ŸŒŸ

์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๊ฐ€ ์ง„์งœ๋‹ค.

์ด๋ฒคํŠธ๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฒƒ๊ณผ
๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์€ ๋‹ค๋ฅด๋‹ค.

๊ทธ๋ž˜์„œ ๋งŒ๋“  API:

GET /tasks/{id}/timeline

์ด API๋Š” ๋‹จ์ˆœ ์ด๋ฒคํŠธ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ

์ž‘์—…์˜ ์ƒํƒœ ๋ณ€ํ™” ํ๋ฆ„์„ ์‹œ๊ฐ„ ์ˆœ์œผ๋กœ ๋ณด์—ฌ์ค€๋‹ค

์ด ํ๋ฆ„์— ์‹œ๊ฐ„ ์ •๋ณด๋ฅผ ๋”ํ•˜๋ฉด,
์ž‘์—…์ด ์–ผ๋งˆ๋‚˜ ๋น ๋ฅด๊ฒŒ ์ง„ํ–‰๋๋Š”์ง€๊นŒ์ง€ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค

์ฆ‰,

๋‹จ์ˆœํžˆ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋‹ค๊ฐ€ ์•„๋‹ˆ๋ผ
์–ด๋А ๊ตฌ๊ฐ„์—์„œ ์˜ค๋ž˜ ๋จธ๋ฌผ๋ €๋Š”์ง€๊นŒ์ง€ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค


โ˜˜๏ธ 7. ์ด๋ฒคํŠธ ๋กœ๊ทธ์™€ ํƒ€์ž„๋ผ์ธ์€ ๋‹ค๋ฅด๋‹ค

๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์จ๋„ ๋ชฉ์ ์ด ๋‹ค๋ฅด๋‹ค.

/events โ†’ ์›๋ณธ ๋กœ๊ทธ
/timeline โ†’ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ํ๋ฆ„

๊ทธ๋ž˜์„œ DTO๋„ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

TaskEventResponse โ†’ ๋กœ๊ทธ์šฉ
TaskTimelineResponse โ†’ ํƒ€์ž„๋ผ์ธ์šฉ

โ†’ ์ด๊ฑด ๋‹จ์ˆœ ๊ตฌ์กฐ๊ฐ€ ์•„๋‹ˆ๋ผ ์—ญํ•  ๋ถ„๋ฆฌ ์„ค๊ณ„๋‹ค.


โ˜˜๏ธ 8. ์ด๋ฒคํŠธ ๊ฐ„ ์‹œ๊ฐ„๊นŒ์ง€ ๊ณ„์‚ฐ

ํƒ€์ž„๋ผ์ธ์—์„œ ํ•œ ๋‹จ๊ณ„ ๋” ๊ฐ”๋‹ค.

๊ฐ ์ด๋ฒคํŠธ๊ฐ€ ์ด์ „ ์ด๋ฒคํŠธ ์ดํ›„ ์–ผ๋งˆ๋‚˜ ๊ฑธ๋ ธ๋Š”์ง€ ๊ณ„์‚ฐ

์˜ˆ๋ฅผ ๋“ค๋ฉด:

CREATED โ†’ STARTED (10๋ถ„ ํ›„)
STARTED โ†’ BLOCKED (20๋ถ„ ํ›„)

์ด๊ฑธ ์‘๋‹ต์— ํฌํ•จ์‹œ์ผฐ๋‹ค.

{
  "eventType": "STARTED",
  "minutesFromPreviousEvent": 10
}

๋‹จ์ˆœํžˆ ์ด๋ฒคํŠธ ํ๋ฆ„๋งŒ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ,

๊ฐ ์ƒํƒœ ๋ณ€ํ™” ์‚ฌ์ด์˜ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ๊นŒ์ง€ ํ•จ๊ป˜ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

์‹ค์ œ ์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

ํƒ€์ž„๋ผ์ธ ์‘๋‹ต - ์ด๋ฒคํŠธ ๊ฐ„ ๊ฒฝ๊ณผ ์‹œ๊ฐ„(duration) ํฌํ•จ

ํƒ€์ž„๋ผ์ธ ์‘๋‹ต - ์ด๋ฒคํŠธ ๊ฐ„ ๊ฒฝ๊ณผ ์‹œ๊ฐ„(duration) ํฌํ•จ2

์ด๋ฅผ ํ†ตํ•ด

์ž‘์—…์ด ์–ด๋А ๊ตฌ๊ฐ„์—์„œ ์˜ค๋ž˜ ๋จธ๋ฌผ๋ €๋Š”์ง€
์ง„ํ–‰ ์†๋„๊ฐ€ ์–ด๋–ค์ง€๊นŒ์ง€ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค


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

์˜ค๋Š˜ ํ•œ ์ผ์„ ํ•œ ์ค„๋กœ ์ •๋ฆฌํ•˜๋ฉด ์ด๊ฑฐ๋‹ค.

์ด๋ฒคํŠธ๋ฅผ ๋‹จ์ˆœ ์กฐํšŒํ•˜๋Š” ๊ฒƒ์„ ๋„˜์–ด์„œ
์‹œ๊ฐ„ ํ๋ฆ„๊นŒ์ง€ ํฌํ•จํ•œ ์ž‘์—… ํ๋ฆ„์œผ๋กœ ์žฌ๊ตฌ์„ฑํ–ˆ๋‹ค


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

CREATE โœ”๏ธ
READ โœ”๏ธ
STATUS FILTER โœ”๏ธ
PROJECT FILTER โœ”๏ธ
EVENT LOGGING โœ”๏ธ
TIMELINE โœ”๏ธ
DURATION โœ”๏ธ

์ด์ œ ๋‹จ์ˆœ CRUD๊ฐ€ ์•„๋‹ˆ๋ผ

ํ๋ฆ„ ๊ธฐ๋ฐ˜ ์กฐํšŒ ์‹œ์Šคํ…œ์˜ ํ˜•ํƒœ๋ฅผ ๊ฐ–์ถ”๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค


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

๋‹ค์Œ ๋‹จ๊ณ„๋Š” ์ด๊ฑฐ๋‹ค.

Project ๋„๋ฉ”์ธ ์ถ”๊ฐ€
ํƒ€์ž„๋ผ์ธ์„ ํ”„๋กœ์ ํŠธ ๋‹จ์œ„๋กœ ํ™•์žฅ

์ด์ œ Task ํ•˜๋‚˜๊ฐ€ ์•„๋‹ˆ๋ผ
ํ”„๋กœ์ ํŠธ ์ „์ฒด ํ๋ฆ„์œผ๋กœ ํ™•์žฅํ•  ์ฐจ๋ก€๋‹ค.

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