Skip to main content

๐Ÿ“… ์บ˜๋ฆฐ๋” ๋งŒ๋“ค๊ธฐ

ยท 5 min read
์ดํ˜„์ง„

MOZI์—๋Š” Upcoming์ด๋ผ๋Š” ํƒญ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ด ํƒญ์—์„œ๋Š” ๋‹ค๊ฐ€์˜ค๋Š” ํ•  ์ผ์„ ๋ณผ ์ˆ˜ ์žˆ๊ณ  ํ•  ์ผ์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3_Upcoming

์ด ๊ธ€์€ ์œ„ ํ™”๋ฉด๊ณผ ๊ฐ™์ด ๋‹ฌ๋ ฅ์„ ๋งŒ๋“ค์–ด๋ณด๋ฉด์„œ ๊ฒช์€ ๊ฒฝํ—˜์„ ๊ธฐ๋กํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

์บ˜๋ฆฐ๋”๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ํ•˜๋‹ˆ ๋ชฉ๋ฏผ์ฃผ ๋ฉ˜ํ† ๋‹˜์ด ์˜์ƒ์„ ํ•œ๊ฐœ ์ถ”์ฒœํ•ด์ฃผ์…”์„œ ๋ดค์Šต๋‹ˆ๋‹ค. ์˜์ƒ์„ ๋ณด๋‹ˆ ๋‚ ์งœ๋ฅผ Date ๊ฐ์ฒด๋กœ ์ง์ ‘ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ํ—ท๊ฐˆ๋ฆด๋งŒํ•œ ๋ถ€๋ถ„์ด ๋งŽ์•˜์Šต๋‹ˆ๋‹ค.

JavaScript์—์„œ ๋‚ ์งœ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ๊นŒ๋‹ค๋กญ๊ธฐ ๋•Œ๋ฌธ์— moment, dayjs, date-fns์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณค ํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค.(Date ๊ฐ์ฒด๋ฅผ ๋งŽ์ด ๋‹ค๋ฃจ์–ด๋ณด์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— Date ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃจ์–ด ๋ณด๊ณ  ์‹ถ์—ˆ์Œ + React ์—†์ด vanilla๋กœ ์บ˜๋ฆฐ๋” ๊ฐœ๋ฐœ)

์ €๋Š” mozi-calendar๋ผ๋Š” ๋ ˆํฌ๋ฅผ ๋งŒ๋“ค๊ณ  Date ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์บ˜๋ฆฐ๋”๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์—ฐ์Šตํ•ด๋ณด๊ธฐ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” ์ผ๋‹จ ์ฝ”๋“œ๋ฅผ ์ณ๋ณด๊ณ  ์ดํ•ด๊ฐ€ ์•ˆ๊ฐ€๋ฉด ๊ฒ€์ƒ‰ํ•ด์„œ ๋ฌธ์„œ๋ฅผ ๋ณด๊ณ  ์ดํ•ดํ•˜๋Š” ๋ฐฉ์‹์„ ์ข‹์•„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋จผ์ € Date ๊ฐ์ฒด๋ฅผ ๋งˆ์Œ๋Œ€๋กœ ๋‹ค๋ฃจ์–ด๋ดค์Šต๋‹ˆ๋‹ค.

const date = new Date() // Tue Oct 04 2022 02:26:17 GMT+0900 (ํ•œ๊ตญ ํ‘œ์ค€์‹œ)

๋จผ์ € new Date()๋ฅผ ์ฝ˜์†”์— ์ฐ์–ด๋ณด๋‹ˆ ์œ„์™€ ๊ฐ™์ด ๋‚˜์™”์Šต๋‹ˆ๋‹ค. ๋ญ”๊ฐ€ ์˜ค๋Š˜ ๋‚ ์งœ์™€ ์‹œ๊ฐ„์ด ๋‚˜์˜ค๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ผ๋‹จ ๋‹ฌ๋ ฅ์— ์˜ค๋Š˜์˜ ๋…„๋„, ์›”, ์ผ์„ ํ‘œ์‹œํ•ด์•ผํ•˜๋ฏ€๋กœ date์—์„œ๋ถ€ํ„ฐ ๊ฐ€์ ธ์™€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

date.getFullYear() // 2022
date.getMonth() // 9
date.getDate() // 4

์ด๋ ‡๊ฒŒ ๋…„, ์›”, ์ผ์„ ๊ฐ€์ ธ์™€๋ดค์Šต๋‹ˆ๋‹ค. ์žฌ๋ฐŒ๋Š” ์ ์€ ๋…„ํ•˜๊ณ  ์ผ์€ ๊ดœ์ฐฎ์€๋ฐ ์›”์€ ์ธ๋ฑ์Šค๊ฐ€ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 0์€ 1์›”, 1์€ 2์›” ... ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ 9๋Š” 10์›”์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์ด 2022๋…„ 10์›” 4์ผ์ด๋ฏ€๋กœ ๋งž์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์ด์ œ ์กฐ๊ธˆ ๋‚˜์•„๊ฐ€์„œ ์ด๋ฒˆ ๋‹ฌ์˜ ์ฒซ์งธ ๋‚ ๊ณผ ๋งˆ์ง€๋ง‰ ๋‚ ์„ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

new Date(year, month, 1) // ๋‹ฌ์˜ ์ฒซ๋‚ : Sat Oct 01 2022 00:00:00 GMT+0900 (ํ•œ๊ตญ ํ‘œ์ค€์‹œ)
new Date(year, month + 1, 0) // ๋‹ฌ์˜ ๋งˆ์ง€๋ง‰ ๋‚ : Mon Oct 31 2022 00:00:00 GMT+0900 (ํ•œ๊ตญ ํ‘œ์ค€์‹œ)

์ง€๊ธˆ๊นŒ์ง€์˜ ๋‚ด์šฉ์œผ๋กœ ๋‹ฌ๋ ฅ์˜ ์œ—๋ถ€๋ถ„์ธ Navigator๋ถ€๋ถ„์— ํ˜„์žฌ ๋…„๋„์™€ ์›”์„ ํ‘œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

image

const getNavigatorHTML = (today: Date) => {
return html`
<button class="move-month-button">
โ† ${MONTHS[today.getMonth() == 0 ? 11 : today.getMonth() - 1]} ${today.getMonth() <=
0
? today.getFullYear() - 1
: today.getFullYear()}
</button>
<h1 class="month-display">
${MONTHS[today.getMonth()]}<br />${today.getFullYear()}
</h1>
<button class="move-month-button">
${MONTHS[today.getMonth() == 11 ? 0 : today.getMonth() + 1]} ${today.getMonth() >=
11
? today.getFullYear() + 1
: today.getFullYear()} โ†’
</button>
`
}

์ด๋ ‡๊ฒŒ ๋„ค๋น„๊ฒŒ์ด์…˜์„ ๋งŒ๋“ค์–ด์ค€ ํ›„์— ์ „๋‹ฌ๊ณผ ๋‹ค์Œ๋‹ฌ๋กœ ์ด๋™ํ•  ๋•Œ ๋„ค๋น„๊ฒŒ์ด์…˜๊ณผ ์บ˜๋ฆฐ๋” ๋ถ€๋ถ„์„ ๋‹ค์‹œ ๋ Œ๋”๋ง ํ•˜๋ฉด ๋‹ฌ๋ ฅ์ด ์™„์„ฑ๋ฉ๋‹ˆ๋‹ค.

const previousMonthButtonDidPress = () => {
displayDate.setMonth(displayDate.getMonth() - 1)

renderNavigator(document.getElementById("navigator"), displayDate)
renderCalendar(document.getElementById("calendar"), displayDate)
}

์ด์ œ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ถ€๋ถ„์„ ์™„์„ฑํ–ˆ์œผ๋‹ˆ ์บ˜๋ฆฐ๋”๋ถ€๋ถ„์œผ๋กœ ๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์บ˜๋ฆฐ๋”์˜ ์ตœ์ƒ๋‹จ์—๋Š” ์ผ~์›” ๋‚ ์งœ๊ฐ€ ํ‘œ์‹œ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

image

for (let d = 0; d < NUMBER_OF_DAYS_IN_WEEK; d++) {
calendarContents.push(
html`
<div class="${NAME_OF_DAYS[d]} calendar-cell">
${LONG_NAME_OF_DAYS[d]}
</div>
`
)
}

์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์ผ~์›”์„ ์บ˜๋ฆฐ๋” ์ปจํ…์ธ  ๋ฐฐ์—ด์— ํ‘ธ์‰ฌํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ ์‹ค์ œ ์บ˜๋ฆฐ๋”๋ฅผ ๋ Œ๋”๋งํ•  ๊ฑด๋ฐ ๋ณด์—ฌ์ง€๋Š” ๋ถ€๋ถ„์€ 3๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์ด์ „๋‹ฌ, ํ˜„์žฌ๋‹ฌ, ๋‹ค์Œ๋‹ฌ ๋”ฐ๋ผ์„œ 3๋ฒˆ์˜ for๋ฌธ์—์„œ calendar ๊ฐ๊ฐ์˜ ๋‹ฌ์„ ์ฐ๋Š” ๋กœ์ง์„ ์ž‘์„ฑํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

for (
let d = 0;
d <
(thisMonthFirstDate.getDay() > 0
? thisMonthFirstDate.getDay()
: NUMBER_OF_DAYS_IN_WEEK);
d++
) {
calendarContents.push(
html`<div
class="
${d % 7 === 0 ? "sun" : ""}
${d % 7 === 6 ? "sat" : ""}
calendar-cell
past-month
"
>
${lastMonthLastDate.getMonth() + 1}/${lastMonthLastDate.getDate() -
thisMonthFirstDate.getDay() +
d +
1 -
(thisMonthFirstDate.getDay() > 0 ? 0 : NUMBER_OF_DAYS_IN_WEEK)}
</div>`
)
}

for (let d = 0; d < thisMonthLastDate.getDate(); d++) {
calendarContents.push(
html`<div
class="
${today.getDate() === d + 1 &&
ACTUAL_TODAY.getFullYear() === today.getFullYear() &&
ACTUAL_TODAY.getDate() === today.getDate() &&
ACTUAL_TODAY.getMonth() === today.getMonth()
? "today"
: ""}
${(thisMonthFirstDate.getDay() + d) % 7 === 0 ? "sun" : ""}
${(thisMonthFirstDate.getDay() + d) % 7 === 6 ? "sat" : ""}
calendar-cell
this-month
"
>
${today.getMonth() + 1}/${d + 1} ${today.getDate() === d + 1 &&
ACTUAL_TODAY.getFullYear() === today.getFullYear() &&
ACTUAL_TODAY.getDate() === today.getDate() &&
ACTUAL_TODAY.getMonth() === today.getMonth()
? " today"
: ""}
</div>`
)
}

let nextMonthDaysToRender = 7 - (calendarContents.length % 7)

for (let d = 0; d < nextMonthDaysToRender; d++) {
calendarContents.push(
html`<div
class="
${(nextMonthFirstDate.getDay() + d) % 7 === 0 ? "sun" : ""}
${(nextMonthFirstDate.getDay() + d) % 7 === 6 ? "sat" : ""}
calendar-cell
next-month
"
>
${nextMonthFirstDate.getMonth() + 1}/${d + 1}
</div>`
)
}

์ด์ œ ์บ˜๋ฆฐ๋”๋ฅผ ๋ Œ๋”๋งํ–ˆ์œผ๋‹ˆ ์Šคํƒ€์ผ๋ง๋งŒ ์ž…ํ˜€์ฃผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์™„์„ฑ๋ฉ๋‹ˆ๋‹ค. Vanilla, TypeScript, React ์ด ์„ธ๊ฐ€์ง€ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ์—ฐ์Šต์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฐฐํฌ ๋งํฌโ€‹