ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๋ฐ˜์‘ํ˜•

๐Ÿ“Œ Webpack๊ณผ TypeScript๋กœ ๋งŒ๋“œ๋Š” ์›น์•ฑ ์บ˜๋ฆฐ๋” ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ ์‹œ๋ฆฌ์ฆˆ

โœ… 8ํŽธ: ์ผ์ • ์‚ญ์ œ ๋ฐ ์ˆ˜์ • ๊ธฐ๋Šฅ ์ถ”๊ฐ€ํ•˜๊ธฐ – ์ธํ„ฐ๋ž™์…˜ ๊ฐ•ํ™”


์ง€๋‚œ ๊ธ€์—์„œ๋Š” LocalStorage ์—ฐ๋™์„ ํ†ตํ•ด ์ผ์ • ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์œ ์ง€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.
์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ์ผ์ •์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ ์ผ์ •์€ ์ถ”๊ฐ€๋งŒ ๊ฐ€๋Šฅํ–ˆ์ง€๋งŒ,
์‹ค์ œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์บ˜๋ฆฐ๋”๊ฐ€ ๋˜๋ ค๋ฉด ์‚ญ์ œ ๋ฐ ์ˆ˜์ • ๊ธฐ๋Šฅ๋„ ํ•„์ˆ˜์ ์œผ๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.


๐ŸŽฏ ๋ชฉํ‘œ

  • ์ผ์ • ๋ชฉ๋ก์—์„œ ํŠน์ • ์ผ์ •์„ ์‚ญ์ œ
  • ์ผ์ • ํด๋ฆญ ์‹œ ์ˆ˜์ • ๊ฐ€๋Šฅ
  • LocalStorage ์—…๋ฐ์ดํŠธ๋กœ ์ƒˆ๋กœ๊ณ ์นจ ํ›„์—๋„ ๋ฐ˜์˜

๐Ÿ“ฆ 1. ์ผ์ • ์ˆ˜์ • ๋ฐ ์‚ญ์ œ ๋กœ์ง ๋งŒ๋“ค๊ธฐ

โœ… handleEditEvent() ํ•จ์ˆ˜ ์ถ”๊ฐ€

// src/components/EventUtils.ts
import { CalendarEvent, CalendarState } from "../types";
import { saveEvents } from "../utils/EventStorage";

export function handleEditEvent(eventId: string, state: CalendarState): void {
  const event = state.events.find((e) => e.id === eventId);
  if (!event) return;

  const newTitle = prompt("์ƒˆ ์ผ์ • ์ œ๋ชฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”:", event.title);
  if (!newTitle) return;

  event.title = newTitle;
  saveEvents(state.events); // ๐Ÿง  ์ˆ˜์ •๋œ ๋ฐ์ดํ„ฐ ์ €์žฅ
}

โœ… handleDeleteEvent() ํ•จ์ˆ˜ ์ถ”๊ฐ€

๋ฐ˜์‘ํ˜•
export function handleDeleteEvent(eventId: string, state: CalendarState): void {
  const confirmed = confirm("์ด ์ผ์ •์„ ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?");
  if (!confirmed) return;

  state.events = state.events.filter((e) => e.id !== eventId);
  saveEvents(state.events); // ๐Ÿง  ์‚ญ์ œ ํ›„ ์ €์žฅ
}

๐Ÿ–ผ๏ธ 2. ์ผ์ • UI์— ์ˆ˜์ •/์‚ญ์ œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€

โœ… ์บ˜๋ฆฐ๋” ์…€ ์•ˆ์— ์ˆ˜์ • ๋ฐ ์‚ญ์ œ ์ด๋ฒคํŠธ ์ถ”๊ฐ€

// src/components/Calendar.ts
import { handleEditEvent, handleDeleteEvent } from "./EventUtils";

const eventHTML = eventsForDate
  .map(
    (e) => `
      <div class="event" data-id="${e.id}">
        ${e.title}
        <button class="edit-btn" data-id="${e.id}">โœ๏ธ</button>
        <button class="delete-btn" data-id="${e.id}">๐Ÿ—‘๏ธ</button>
      </div>
    `
  )
  .join("");

โœ… 3. ์ˆ˜์ • ๋ฐ ์‚ญ์ œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์—ฐ๊ฒฐ

// src/components/Calendar.ts
export function attachCalendarEvents(
  target: HTMLElement,
  state: CalendarState,
  rerender: () => void
) {
  // ๊ธฐ์กด ๋‚ ์งœ ํด๋ฆญ ํ•ธ๋“ค๋Ÿฌ ์œ ์ง€
  const cells = target.querySelectorAll(".calendar-cell:not(.header)");
  cells.forEach((cell) => {
    cell.addEventListener("click", () => {
      const dateStr = cell.getAttribute("data-date");
      if (dateStr) {
        const date = new Date(dateStr);
        state.selectedDate = date;
        rerender();
      }
    });
  });

  // ์ˆ˜์ • ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
  target.querySelectorAll(".edit-btn").forEach((btn) => {
    btn.addEventListener("click", (e) => {
      const eventId = (e.target as HTMLElement).getAttribute("data-id");
      if (eventId) {
        handleEditEvent(eventId, state);
        rerender();
      }
    });
  });

  // ์‚ญ์ œ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
  target.querySelectorAll(".delete-btn").forEach((btn) => {
    btn.addEventListener("click", (e) => {
      const eventId = (e.target as HTMLElement).getAttribute("data-id");
      if (eventId) {
        handleDeleteEvent(eventId, state);
        rerender();
      }
    });
  });
}

๐ŸŽจ 4. ์Šคํƒ€์ผ ์—…๋ฐ์ดํŠธ (์„ ํƒ ์‚ฌํ•ญ)

.event {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 8px;
  background: #f8f8f8;
  margin-top: 4px;
  border-radius: 4px;
}

.edit-btn,
.delete-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 0.8rem;
  margin-left: 6px;
}

๐Ÿš€ 5. ํ…Œ์ŠคํŠธ

npm run dev

๐Ÿ› ๏ธ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค

โœ… ์ผ์ • ํด๋ฆญ ํ›„ ์ˆ˜์ • ๊ฐ€๋Šฅ:

  1. ์ผ์ • ์ž…๋ ฅ ํ›„, โœ๏ธ ๋ฒ„ํŠผ์„ ํด๋ฆญ
  2. ์ƒˆ๋กœ์šด ์ œ๋ชฉ์„ ์ž…๋ ฅ
  3. ์ผ์ •์ด ์—…๋ฐ์ดํŠธ๋จ

โœ… ์ผ์ • ์‚ญ์ œ ๊ฐ€๋Šฅ:

  1. ์ผ์ • ์ž…๋ ฅ ํ›„, ๐Ÿ—‘๏ธ ๋ฒ„ํŠผ์„ ํด๋ฆญ
  2. ํ™•์ธ ์ฐฝ์—์„œ "ํ™•์ธ" ์„ ํƒ
  3. ์ผ์ •์ด ์‚ญ์ œ๋จ

โœ… ์ƒˆ๋กœ๊ณ ์นจ ํ›„ ๋ฐ์ดํ„ฐ ์œ ์ง€:

  • ์ˆ˜์ • ๋ฐ ์‚ญ์ œ ํ›„์—๋„ LocalStorage์— ๋ฐ˜์˜๋จ์„ ํ™•์ธ

๐Ÿ“š ์ฐธ๊ณ ์ž๋ฃŒ

 


๋‹ค์Œ ํŽธ ์˜ˆ๊ณ :
๐Ÿ“˜ 9ํŽธ – ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง: ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ตฌ์กฐํ™” ๋ฐ ์œ ์ง€๋ณด์ˆ˜ ์ตœ์ ํ™”
์ง€๊ธˆ๊นŒ์ง€ ๋งŒ๋“  ๊ธฐ๋Šฅ๋“ค์„ ๋” ๊น”๋”ํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ ๊ตฌ์กฐ๋กœ ๊ฐœ์„ ํ•ด๋ด…๋‹ˆ๋‹ค! ๐Ÿš€
๋” ์ข‹์€ ์บ˜๋ฆฐ๋” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ•œ ๋‹จ๊ณ„ ์—…๊ทธ๋ ˆ์ด๋“œ! ๐ŸŽฏ

'study > ts' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

๐Ÿ“Œ Webpack๊ณผ TypeScript๋กœ ๋งŒ๋“œ๋Š” ์›น์•ฑ ์บ˜๋ฆฐ๋” ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ ์‹œ๋ฆฌ์ฆˆ  (0) 2025.03.28
๐Ÿ“Œ Webpack๊ณผ TypeScript๋กœ ๋งŒ๋“œ๋Š” ์›น์•ฑ ์บ˜๋ฆฐ๋” ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ ์‹œ๋ฆฌ์ฆˆ - ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง โ€“ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ตฌ์กฐํ™” ๋ฐ ์œ ์ง€๋ณด์ˆ˜ ์ตœ์ ํ™”  (0) 2025.03.27
๐Ÿ“Œ Webpack๊ณผ TypeScript๋กœ ๋งŒ๋“œ๋Š” ์›น์•ฑ ์บ˜๋ฆฐ๋” ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ ์‹œ๋ฆฌ์ฆˆ - ์ผ์ • ๋ฐ์ดํ„ฐ ์˜๊ตฌ ์ €์žฅ โ€“ LocalStorage ์—ฐ๋™์œผ๋กœ ์ƒˆ๋กœ๊ณ ์นจ์—๋„ ์œ ์ง€ํ•˜๊ธฐ  (0) 2025.03.26
๐Ÿ“Œ Webpack๊ณผ TypeScript๋กœ ๋งŒ๋“œ๋Š” ์›น์•ฑ ์บ˜๋ฆฐ๋” ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ ์‹œ๋ฆฌ์ฆˆ - ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ โ€“ ๋‚ ์งœ ์„ ํƒ๊ณผ ์›” ์ด๋™ ๊ธฐ๋Šฅ ๊ตฌํ˜„  (0) 2025.03.25
๐Ÿ“Œ Webpack๊ณผ TypeScript๋กœ ๋งŒ๋“œ๋Š” ์›น์•ฑ ์บ˜๋ฆฐ๋” ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ ์‹œ๋ฆฌ์ฆˆ - ์ผ์ • ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌํ•˜๊ธฐ โ€“ ์ด๋ฒคํŠธ ์ถ”๊ฐ€ ๋ฐ ์ €์žฅ ๊ตฌ์กฐ ์„ค๊ณ„  (0) 2025.03.25
โ€ป ์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค.
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
ยซ   2025/05   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
๊ธ€ ๋ณด๊ด€ํ•จ
๋ฐ˜์‘ํ˜•