{event.title}
+{event.source}
+{event.mode}
+From 2f01821fd971600afa91573600ab2110b0749df0 Mon Sep 17 00:00:00 2001
From: seonghobae <8172694+seonghobae@users.noreply.github.com>
Date: Thu, 6 Aug 2026 01:20:53 +0000
Subject: [PATCH] =?UTF-8?q?feat:=20=EC=BA=98=EB=A6=B0=EB=8D=94=20=EC=BB=B4?=
=?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?=
=?UTF-8?q?=EB=A0=8C=EB=8D=94=EB=A7=81=EC=97=90=20useMemo=20=EB=8F=84?=
=?UTF-8?q?=EC=9E=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.jules/bolt.md | 4 +++
.../calendar/CalendarCandidateView.tsx | 33 ++++++++++++-------
.../components/calendar/CalendarWeekView.tsx | 33 ++++++++++++-------
3 files changed, 46 insertions(+), 24 deletions(-)
diff --git a/.jules/bolt.md b/.jules/bolt.md
index d5fcbd53e..ee4e66261 100644
--- a/.jules/bolt.md
+++ b/.jules/bolt.md
@@ -15,3 +15,7 @@
**Learning:** `dict.setdefault(key, []).append(value)` evaluates the empty-list default on every iteration, including when the key already exists. In grouping loops, `defaultdict(list)` avoids those transient unused list allocations while preserving insertion order.
**Action:** Use `defaultdict(list)` when missing keys are intentionally initialized with lists. Keep `setdefault` when its eager-default behavior or an ordinary `dict` is part of the required contract, and benchmark before claiming a material end-to-end improvement.
+## 2025-02-12 - Wrap array rendering loops with useMemo
+
+**Learning:** Mapping over arrays of properties inside a React functional component's render execution directly causes O(N) evaluations when unrelated state (like input queries or tab switches) updates the component.
+**Action:** Always wrap `.map()` calls that output elements in a `useMemo` block with exact prop array dependencies in large lists, especially if they are passed as props to avoid blocking the main thread on every re-render.
diff --git a/frontend/src/components/calendar/CalendarCandidateView.tsx b/frontend/src/components/calendar/CalendarCandidateView.tsx
index 35c681e06..7923a2277 100644
--- a/frontend/src/components/calendar/CalendarCandidateView.tsx
+++ b/frontend/src/components/calendar/CalendarCandidateView.tsx
@@ -1,3 +1,4 @@
+import { useMemo } from 'react';
import type { CalendarCandidateEvent } from './types';
type Props = {
@@ -5,22 +6,30 @@ type Props = {
};
export function CalendarCandidateView({ visibleCandidateEvents }: Props) {
+
+ // ⚡ Bolt: Wrap candidate events map in useMemo to prevent O(N) re-renders
+ // 🎯 Why: Mapping over event lists during unrelated parent renders (e.g. state changes) blocks the main thread.
+ const candidateEventsList = useMemo(() => (
+ <>
+ {visibleCandidateEvents.map((event) => (
+ {event.source} {event.mode}{event.title}
+
+ 표시 중인 캘린더 후보가 없습니다. +
+ )} + > + ), [visibleCandidateEvents]); return ({event.source}
-{event.mode}
-- 표시 중인 캘린더 후보가 없습니다. -
- )} + {candidateEventsList}{event.day}
+{event.source}
++ 표시 중인 캘린더 일정이 없습니다. +
+ )} + > + ), [visibleWeekEvents]); return ({event.day}
-{event.source}
-- 표시 중인 캘린더 일정이 없습니다. -
- )} + {weekEventsList}