ํฐ์คํ ๋ฆฌ ๋ทฐ
study/ts
๐ Webpack๊ณผ TypeScript๋ก ๋ง๋๋ ์น์ฑ ์บ๋ฆฐ๋ ํ๋ฌ๊ทธ์ธ ๊ฐ๋ฐ ์๋ฆฌ์ฆ - ์ผ์ ๋ฐ์ดํฐ ๊ด๋ฆฌํ๊ธฐ – ์ด๋ฒคํธ ์ถ๊ฐ ๋ฐ ์ ์ฅ ๊ตฌ์กฐ ์ค๊ณ
octo54 2025. 3. 25. 11:17๋ฐ์ํ
๐ Webpack๊ณผ TypeScript๋ก ๋ง๋๋ ์น์ฑ ์บ๋ฆฐ๋ ํ๋ฌ๊ทธ์ธ ๊ฐ๋ฐ ์๋ฆฌ์ฆ - ์ผ์ ๋ฐ์ดํฐ ๊ด๋ฆฌํ๊ธฐ – ์ด๋ฒคํธ ์ถ๊ฐ ๋ฐ ์ ์ฅ ๊ตฌ์กฐ ์ค๊ณ
์ด๋ฒ ํธ์์๋ ์บ๋ฆฐ๋ ํ๋ฌ๊ทธ์ธ์ ๊ผญ ํ์ํ ๊ธฐ๋ฅ์ธ
“์ผ์ (Event)”์ ๋ฑ๋กํ๊ณ , ์ ์ฅํ๋ฉฐ, ๋ ๋๋งํ๋ ๋ฐ์ดํฐ ํ๋ฆ์ ์ค๊ณํฉ๋๋ค.
์ด์ ๋ฌ๋ ฅ์ ๋๊ธฐ๊ณ , ๋ ์ง๋ฅผ ์ ํํ ์ ์๊ฒ ๋์์ผ๋,
๊ฐ ๋ ์ง์ ์ผ์ ์ ์ถ๊ฐํ๊ณ ํ์ธํ ์ ์์ด์ผ๊ฒ ์ฃ ?
๐ฏ ๋ชฉํ
- ์ผ์ (Event) ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ ์ ๋ฐ ์ ์ฅ ๋ฐฉ์ ์ค๊ณ
- ๋ ์ง๋ฅผ ํด๋ฆญํ์ฌ ์ผ์ ์ ์ถ๊ฐํ๋ ๊ธฐ๋ฅ ๊ตฌํ
- ๊ฐ ๋ ์ง๋ณ๋ก ๋ฑ๋ก๋ ์ผ์ ์ด ์บ๋ฆฐ๋์ ํ์๋๋๋ก ์ฒ๋ฆฌ
๐ง ๋ฐ์ดํฐ ์ค๊ณ
โ CalendarEvent ํ์ ๋ค์ ํ์ธ
// src/types.ts
export interface CalendarEvent {
id: string;
title: string;
date: string; // YYYY-MM-DD (ISO ํ์)
}
โ ์ํ์ ์ด๋ฒคํธ ์ ์ฅ์ ์ถ๊ฐ
๋ฐ์ํ
export interface CalendarState {
year: number;
month: number;
selectedDate?: Date;
events: CalendarEvent[]; // ๐ก ์ถ๊ฐ๋จ
}
๐ฆ 1. ๊ฐ๋จํ ์ผ์ ์ถ๊ฐ UI ๊ตฌ์ฑ
โ prompt()๋ฅผ ํ์ฉํ ์ ๋ ฅ ๋ฐฉ์ (๊ฐ๋จ MVP์ฉ)
// src/components/Calendar.ts
function handleAddEvent(date: Date, state: CalendarState): void {
const title = prompt(`${date.toDateString()} ์ผ์ ์ ๋ชฉ์ ์
๋ ฅํ์ธ์:`);
if (!title) return;
const newEvent: CalendarEvent = {
id: crypto.randomUUID(),
title,
date: date.toISOString().split("T")[0],
};
state.events.push(newEvent);
}
๐งฉ 2. ๋ ์ง ํด๋ฆญ ์ ์ผ์ ์ถ๊ฐ ๊ธฐ๋ฅ ์ฐ๊ฒฐ
โ ๋ ์ง ์ ํด๋ฆญ ์ด๋ฒคํธ์์ ์ถ๊ฐ ์คํ
// src/components/Calendar.ts
import { handleAddEvent } from "./EventUtils";
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;
handleAddEvent(date, state); // ์ผ์ ์ถ๊ฐ
rerender();
}
});
});
// ... ์๋ต๋ ์ ์ ํ ์ฝ๋ ์ ์ง
}
๐ผ๏ธ 3. ๋ ์ง ์ ์ ์ผ์ ํ์
โ renderCalendar ๋ด๋ถ์ ์ผ์ ๋ ๋๋ง ์ถ๊ฐ
// ๊ฐ ๋ ์ง ์
์์์ ์ผ์ ๋ ๋๋ง
const eventsForDate = state.events.filter(
(e) => e.date === date?.toISOString().split("T")[0]
);
const eventHTML = eventsForDate
.map((e) => `<div class="event">${e.title}</div>`)
.join("");
return `<div class="calendar-cell${inMonth ? "" : " out"}${isSelected ? " selected" : ""}" data-date="${dateStr}">
${day}
${eventHTML}
</div>`;
๐จ 4. CSS ์คํ์ผ ์ถ๊ฐ
.event {
font-size: 0.75rem;
background-color: #f2f2f2;
margin-top: 4px;
padding: 2px 4px;
border-radius: 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
๐ 5. index.ts ์ ๋ฐ์ดํธ
โ ์ด๊ธฐ ์ํ ์ ์์ events ํฌํจ
const state: CalendarState = {
year: new Date().getFullYear(),
month: new Date().getMonth(),
events: [],
};
โ ๊ฒฐ๊ณผ ํ์ธ
npm run dev
- ๋ ์ง ํด๋ฆญ → prompt ์ฐฝ์ ์ผ์ ์ ๋ ฅ
- ์ ๋ ฅ ์๋ฃ ์ ํด๋น ๋ ์ง์ ์ผ์ ์ด ํ์๋จ
- ์ผ์ ๋ฐ์ดํฐ๋ ํ์ฌ ์ํ(state.events)์ ์ ์ฅ๋จ (ํ์ด์ง ์๋ก๊ณ ์นจ ์ ์ฌ๋ผ์ง)
๐ ํ์ฅ ์์ด๋์ด
๊ธฐ๋ฅ ์ค๋ช
โ ๋ก์ปฌ์คํ ๋ฆฌ์ง์ ์ ์ฅ | ์๋ก๊ณ ์นจ ํ์๋ ์ผ์ ์ ์ง |
โ ์ผ์ ์์ /์ญ์ | ์ผ์ ํญ๋ชฉ ํด๋ฆญ ์ ์์ /์ญ์ ๊ธฐ๋ฅ ์ ๊ณต |
โ ์ผ์ ์นดํ ๊ณ ๋ฆฌ | "์ ๋ฌด", "๊ฐ์ธ" ๋ฑ์ ๋ถ๋ฅ ์ถ๊ฐ |
โ ๋ชจ๋ฌ ์ ๋ ฅ์ฐฝ | prompt ๋์ UI ๊ธฐ๋ฐ ์ ๋ ฅ ํผ ์ ๊ณต |
๐ ์ฐธ๊ณ ์๋ฃ
๋ค์ ํธ ์๊ณ :
๐ 7ํธ – ์ผ์ ์ ์ฅ์ ๊ฐ์ ํ๊ธฐ: LocalStorage ๋๋ JSON ํ์ผ ์ฐ๋
ํ์ด์ง ์๋ก๊ณ ์นจ์๋ ์ผ์ ์ด ์ ์ง๋๋๋ก ๋ฐ์ดํฐ ์์ํ(Storage) ๊ธฐ๋ฅ์ ์ถ๊ฐํฉ๋๋ค! ๐ง
ํ๋ฌ๊ทธ์ธ์ ์์ฑ๋๊ฐ ํ ๋จ๊ณ ๋์์ง๋๋ค!
'study > ts' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
โป ์ด ํฌ์คํ
์ ์ฟ ํก ํํธ๋์ค ํ๋์ ์ผํ์ผ๋ก, ์ด์ ๋ฐ๋ฅธ ์ผ์ ์ก์ ์์๋ฃ๋ฅผ ์ ๊ณต๋ฐ์ต๋๋ค.
๊ณต์ง์ฌํญ
์ต๊ทผ์ ์ฌ๋ผ์จ ๊ธ
์ต๊ทผ์ ๋ฌ๋ฆฐ ๋๊ธ
- Total
- Today
- Yesterday
๋งํฌ
TAG
- gatsbyjs
- CI/CD
- ํ๋ก ํธ์๋
- SEO์ต์ ํ
- rag
- Next.js
- ๋ฐฑ์๋๊ฐ๋ฐ
- llm
- ๊ฐ๋ฐ๋ธ๋ก๊ทธ
- AI์ฑ๋ด
- nextJS
- fastapi
- ํ๋ก ํธ์๋๋ฉด์
- Docker
- NestJS
- App Router
- Python
- ์น๊ฐ๋ฐ
- PostgreSQL
- nodejs
- seo ์ต์ ํ 10๊ฐ
- SEO ์ต์ ํ
- Ktor
- flax
- REACT
- ๋ฅ๋ฌ๋
- ํ์ด์ฌ์๊ณ ๋ฆฌ์ฆ
- Prisma
- JAX
- kotlin
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
๊ธ ๋ณด๊ดํจ
๋ฐ์ํ