From 5c6b0ce1efbc9a2b2217a72361822bf5d4e4173d Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Mon, 10 Aug 2026 02:03:30 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=EB=82=B4=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EB=AA=A9=EB=A1=9D=20useMemo=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20O(N)=20=EC=9E=AC=EB=A0=8C=EB=8D=94?= =?UTF-8?q?=EB=A7=81=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 3 ++ frontend/src/components/TasksLayout.tsx | 42 ++++++++++++++----------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index d0b0a9997..ade2b5813 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -19,3 +19,6 @@ **Learning:** When using a dictionary purely to track the presence of keys (e.g. `has_sent_message[key] = True`), checking for presence with `.get(key, False)` carries unnecessary semantic and memory overhead. Sets in Python provide a cleaner `key in set_name` syntax for boolean presence checks and slightly reduced memory footprint, while maintaining O(1) time complexity. **Action:** When tracking unique occurrences or boolean presence of items where the value itself doesn't carry additional information, use a `set` and its `.add()` and `in` operators instead of a `dict` mapping to `True` or `False`. +## 2025-02-12 - Memoizing My Tasks view inside JSX +**Learning:** Inline mapping of arrays inside JSX in large React components causes O(N) recalculation on every render. Although the `kanbanBoard` in `TasksLayout` was properly memoized, the `myTasksBoard` list was still mapped inline in the React return block, causing main thread blocking when other layout state (like search) was updated. +**Action:** Always verify that *all* conditional array map rendering blocks are properly wrapped in a `useMemo` hook with all necessary external variables and setters in the dependency array (e.g. `[filteredTicketTasks, setSelectedTaskId, setViewMode]`) to prevent state changes in unrelated components from causing a bottleneck. diff --git a/frontend/src/components/TasksLayout.tsx b/frontend/src/components/TasksLayout.tsx index 034aa6911..d163b518d 100644 --- a/frontend/src/components/TasksLayout.tsx +++ b/frontend/src/components/TasksLayout.tsx @@ -306,6 +306,28 @@ export function TasksLayout() { [ticketTasks], ); + // ⚑ Bolt: Wrap My Tasks list in useMemo to prevent O(N) re-renders + // 🎯 Why: Mapping over potentially large lists of tasks blocks the main thread during unrelated state updates. + const myTasksBoard = useMemo(() => ( +
+

λ‚΄ μž‘μ—…

+ {filteredTicketTasks.length > 0 ? filteredTicketTasks.map(task => ( + + )) : ( +

μ„œλͺ… μ„Έμ…˜μ— μ—°κ²°λœ λ‚΄ μž‘μ—…μ΄ μ—†μŠ΅λ‹ˆλ‹€.

+ )} +
+ ), [filteredTicketTasks, setSelectedTaskId, setViewMode]); + // ⚑ Bolt: Wrap Kanban columns in useMemo to prevent O(N) re-renders // 🎯 Why: Mapping over potentially large lists of tasks by status blocks the main thread during unrelated state updates. const kanbanBoard = useMemo(() => ( @@ -681,25 +703,7 @@ export function TasksLayout() { {viewMode === '칸반' && kanbanBoard} - {viewMode === 'λ‚΄ μž‘μ—…' && ( -
-

λ‚΄ μž‘μ—…

- {filteredTicketTasks.length > 0 ? filteredTicketTasks.map(task => ( - - )) : ( -

μ„œλͺ… μ„Έμ…˜μ— μ—°κ²°λœ λ‚΄ μž‘μ—…μ΄ μ—†μŠ΅λ‹ˆλ‹€.

- )} -
- )} + {viewMode === 'λ‚΄ μž‘μ—…' && myTasksBoard} {viewMode === 'μœ„μž„ν•œ μž‘μ—…' && (