useCustom hook์„ ๋งŒ๋“ค์–ด ์„œ๋น„์Šค ํ—ค๋”์˜ ๋’ค๋กœ๊ฐ€๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
ยท
What I Learn
์‚ฌ์šฉ์ž๊ฐ€ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์ตœ๋Œ€ ๋ผ์šฐํ„ฐ๋Š” /messagebox/[userId]/[type]/[messageId]/[options] ์ธ๋ฐ, ๋งˆ์ง€๋ง‰ ๊ฒฝ๋กœ [options]๋Š” ๋ณ‘๋ ฌ ๋ผ์šฐํŒ…์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ๊ฒฝ๋กœ ๊ฐ€๋กœ์ฑ„๊ธฐ๋ฅผ ํ†ตํ•ด ํŽ˜์ด์ง€ ์ƒ์œ„์— ๋„์šฐ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•œ ํŽ˜์ด์ง€์™€ ์ชฝ์ง€์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” reaction ํŽ˜์ด์ง€๊ฐ€ ์žˆ์–ด์„œ ๊ฒฝ๋กœ์— ๋งž์ถฐ ๊ธฐ๋Šฅ์„ ๊ตฌ๋ถ„ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์— ๋‹จ์ˆœํžˆ router.back()์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ ค ํ•˜๋‹ˆ ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ ๊ณ ๋ คํ–ˆ์„ ๋•Œ ์˜๋„ํ•œ ๋ฐ”๋กœ ๋’ค๋กœ๊ฐ€๊ธฐ๊ฐ€ ๋˜์ง€ ์•Š๋˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์„œ, ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋ณต์žกํ•œ ๋‚ด๋น„๊ฒŒ์ด์…˜ ๋กœ์ง์„ ๊ด€๋ฆฌํ•˜๊ณ  ํŠน์ • ๊ฒฝ๋กœ์—์„œ ๋’ค๋กœ๊ฐ€๊ธฐ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ์ปค์Šคํ…€ ํ›…์„ ๊ฐœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” router.back() ์ด์—ˆ์„ ๋•Œ ํ˜„์ƒ์ž…๋‹ˆ๋‹คhttps://youtu...
husky์™€ GitHub Actions์„ ์‚ฌ์šฉํ•œ CICD
ยท
What I Learn
์ด์ „์— ํˆฌ๋‘ํƒœ์Šคํฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋˜ ํŒ€ ์ €์žฅ์†Œ๋ฅผ forkํ•ด์™€์„œ ๊ฐœ์ธ ๋ ˆํฌ์—์„œ AWS Amplify๋กœ ๋ฐฐํฌํ–ˆ๋Š”๋ฐ, ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์–‘์ชฝ์— ๋‹ค push ํ•ด์ค˜์•ผ ํ–ˆ๋˜ ๋ฒˆ๊ฑฐ๋กœ์›€์„ ๋А๊ผˆ๋˜ ๊ฒฝํ—˜์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.Amplify๋กœ ์ง„ํ–‰ํ–ˆ์„ ๋•Œ ๋“ค์—ˆ๋˜ ๊ฒŒ Next.js๋กœ ๋ฐฐํฌ๋ฅผ ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด vercel์ด ๊ฐ™์€ ํšŒ์‚ฌ๋ผ์„œ ์—ฐ๋™์ด ์‰ฝ๊ณ  CICD๋ฅผ ์ž˜ ๊ตฌ์ถ•ํ•ด๋‘ฌ์„œ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๋ง์„ ๋“ค์€ ์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.์›น์„œ๋ฒ„ ๊ตฌ์ถ•์— ์–ด๋ ค์›€์„ ๋А๋ผ๊ณ  ์žˆ๋˜ ๋•Œ Vercel๋กœ ์–ด๋ ต์ง€ ์•Š๊ฒŒ ํ•˜๋ฉด ์•ˆ๋˜๋‚˜? ์‹ถ์–ด์„œ ํ•ด๋ณด์•˜๋Š”๋ฐ, ์ž‘์—…์„ ๋๋‚ด๊ณ  ์ฐพ์•„๋ณด๋‹ˆ๊นŒ Vercel์„ ์›น์„œ๋ฒ„๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ๊ฐ€๋Šฅํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ Vercel์˜ ์„œ๋ฒ„๋ฆฌ์Šค ํ•œ๊ณ„์™€ ์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•˜์ง€ ๋ชปํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜๊ณ , ์ดํ›„ AWS EC2์™€ Nginx๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์›น์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค..
Intersection Observer API๋ฅผ ์‚ฌ์šฉํ•ด ๋ทฐํฌํŠธ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ
ยท
What I Learn
์ด์ „์— offset ๊ธฐ๋ฐ˜ ๋ฌดํ•œ์Šคํฌ๋กค์„ ๊ตฌํ˜„ํ–ˆ์„ ๋•Œ๋Š” ์Šคํฌ๋กค ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ทฐํฌํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€๋กœ๋“œํ•˜๋„๋ก ํ–ˆ์—ˆ๋Š”๋ฐ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ์„œ๋ฅผ ์ญ‰ ์ฝ์–ด๋ณด๋‹ค๊ฐ€ ํŽ˜์ด์ง€ ๋‚ด์— ๊ฐ ์š”์†Œ๊ฐ€ ๊ฐ๊ฐ์˜ ๋ชฉ์ (๊ด‘๊ณ , ๋ ˆ์ด์ง€ ๋กœ๋”ฉ, ๋ฌดํ•œ ์Šคํฌ๋กค ๋“ฑ)์˜ ์ด์œ ๋กœ scroll ์ด๋ฒคํŠธ๋ฅผ ๋ฆฌ์Šค๋‹ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด์— ์ƒ์‘ํ•˜๋Š” ์ฝœ๋ฐฑ์ด ๋ฌด์ˆ˜ํžˆ ์‹คํ–‰๋  ์ˆ˜๋„ ์žˆ๊ณ  ์ด๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์— ํฐ ๋ถ€ํ•˜๋ฅผ ์ค„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค๋ฅธ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๋‹ค๊ฐ€ ํƒ€๊ฒŸ ์š”์†Œ์™€ ๋ทฐํฌํŠธ์˜ ๊ต์ฐจ์ ์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ด€์ฐฐํ•ด์„œ ์š”์†Œ๊ฐ€ ๋ทฐํฌํŠธ์— ํฌํ•จ๋˜๋Š”์ง€ ์•„๋‹Œ์ง€ ๊ตฌ๋ณ„ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” Intersection Observer API๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์Šคํฌ๋กค ์ด๋ฒคํŠธ์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ throttling/debouncing์ด ๋ถˆํ•„์š”ํ•˜๋‹ค๋Š” ์ , ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ..
Next.js ๋ณ‘๋ ฌ ๋ผ์šฐํŒ… & ๊ฒฝ๋กœ ๊ฐ€๋กœ์ฑ„๊ธฐ๋ฅผ ํ†ตํ•œ ๋ชจ๋‹ฌ ํŽ˜์ด์ง€ ๊ตฌํ˜„ 2
ยท
What I Learn
์ด์ „์— ๊ณต๋ถ€ํ–ˆ๋˜ Next.js์˜ ๊ธฐ๋Šฅ์ธ parallel routes, intercepting routes๋ฅผ ์ด์šฉํ•œ ๋ชจ๋‹ฌ ํŽ˜์ด์ง€ ๊ตฌํ˜„ ํ•˜๊ธฐ.์ค‘๊ฐ„์— ํ”„๋กœ์ ํŠธ๊ฐ€ ํ์ง€๋ถ€์ง€๋˜์–ด์„œ ๊ทธ ์ด์ƒ์˜ ์ง„ํ–‰์€ ํ•˜์ง€ ๋ชปํ–ˆ๋Š”๋ฐ, ์ด๋•Œ ๊ณต๋ถ€ํ–ˆ๋˜ ๊ฒƒ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ค์Œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด์•˜๋‹ค.  ๊ฐ ํŒŒ์ผ๋ณ„ ๊ธฐ๋Šฅ์€ ์œ„์— ์ฒจ๋ถ€ํ•œ ๊ธ€์—์„œ ๋ชจ๋‘ ์„ค๋ช…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ ์šฉํ•œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ๋งŒ ์ž‘์„ฑํ•ด๋‘”๋‹ค. ํŽ˜์ด์ง€์˜ UI๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•˜๋‹ค. ์ด๋Ÿฐ ๋ชจ๋‹ฌ์ด ์‹ ๊ณ ํ•˜๊ธฐ/์ˆจ๊ธฐ๊ธฐ/์ˆจ๊น€ํ•ด์ œ ๋กœ 3๊ฐ€์ง€๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค ๋ณ‘๋ ฌ ๋ผ์šฐํŒ…์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ๊ฒฝ๋กœ ๊ฐ€๋กœ์ฑ„๊ธฐ๋ฅผ ํ†ตํ•ด ๋ชจ๋‹ฌ์„ ์ƒ์œ„์— ๋„์šฐ๋Š” ์ด ๋ฐฉ๋ฒ•์€ ์ด๋™ํ•œ ํŽ˜์ด์ง€ ๋‚ด๋ถ€์—์„œ ๋ชจ๋‹ฌ์„ ์ƒ์„ฑํ•ด์„œ ๋ Œ๋”ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๊ฒฝ๋กœ๋ฅผ ๊ฐ€๋กœ์ฑ„์„œ ๋ชจ๋‹ฌ ์ž์ฒด๋ฅผ ๋„์šฐ๋Š” ๊ฒƒ์ด๋‹ˆ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ์ข‹์•„์ง€๊ฒŒ ๋  ์ˆ˜ ์žˆ๋‹ค ๊ตฌํ˜„ํด๋” ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™..
e.stopPropagation(), ์ด๋ฒคํŠธ ์ „ํŒŒ ๋ฐฉ์ง€
ยท
What I Learn
PR ๋ฆฌ๋ทฐ๋กœ ๋ฐ›์•˜๋˜ ํ”ผ๋“œ๋ฐฑ ์ค‘ ์ด ์งˆ๋ฌธ์„ ๋ฐ›๊ณ  ์ž‘์„ฑํ•ด๋ณด๋Š” ๊ธ€์ด๋‹ค. ๋จผ์ € ๋‚˜๋Š” ๊ฒฝ๋กœ๋ฅผ ๊ฐ€๋กœ์ฑ„์„œ ๋ชจ๋‹ฌ ์ž์ฒด๋ฅผ ๋„์šฐ๋Š” intercepting routes & parallel routes๋กœ ๋ชจ๋‹ฌ์„ ๋„์› ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ์งˆ๋ฌธ์ด ๋‹ฌ๋ฆฐ ํŒŒ์ผ์€ ๋‹ค์Œ (.)hide/ page.tsx ์ด์—ˆ๋‹ค. 'use client'import { Button } from '@/shared/components/Button'import { useRouter } from 'next/navigation'import { useCallback } from 'react'export default function Page({ params: { userId, messageId },}: { params: { userId: string; messageId..
format date as 'YYYY.MM.DD AMhh:mm'
ยท
What I Learn
ํฌ๋งทํŒ…ํ•ด์•ผํ•˜๋Š” ์–‘์‹์€ ์œ„์™€ ๊ฐ™์•˜๊ณ , js์˜ DateTimeFormat์„ ์‚ฌ์šฉํ•ด KST๋กœ ๋ฐ”๊พธ๋ฉด์„œ ์˜ต์…˜์„ DateTimeFormatOptions๋กœ ์ฃผ์—ˆ๋‹ค. /** * ์ฃผ์–ด์ง„ ๋‚ ์งœ์™€ ์ผ์ž๋ฅผ "YYYY.MM.DD. ์˜ค์ „(ํ˜น์€ ์˜คํ›„)HH:MM" ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. */const dateFormat = (e: Date) => { const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: '2-digit', day: '2-digit', hour: 'numeric', minute: '2-digit', hour12: true, } const formatter = new Intl.DateTimeFormat('ko-K..
Tooltip ๊ตฌํ˜„
ยท
What I Learn
Tooltip์€ ์ปค์„œ๋ฅผ ํŠน์ • ๊ตฌ์„ฑ ์š”์†Œ์— hover ๋˜๋ฉด ํ•ด๋‹น ์˜์—ญ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•˜๋Š” GUI ์š”์†Œ์ด๋‹ค. ํ™”๋ฉด์— ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์ด๋‚˜ ํŠน์ • ์š”์†Œ์— ๋Œ€ํ•œ ์•ˆ๋‚ด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํ™”๋ฉด์„ Dimmed ์ฒ˜๋ฆฌํ•˜๊ณ  ๋„์›€๋ง์ด๋‚˜ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค. ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์— ์˜ํ•œ ํŒ์—… ์ข…๋ฅ˜๋Š” ๋‹ค์Œ ๊ธ€์— ์žˆ๋‹ค. -> Toast ์ ์šฉ๊ธฐ ๋‚˜์˜จ ๋””์ž์ธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํˆดํŒ UI๊ฐ€ ์žˆ์—ˆ๊ณ , ์ด๋ ‡๊ฒŒ ํˆดํŒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค. import React from 'react'interface TooltipProps { children: React.ReactNode}export default function Tooltip({ children }: TooltipProps) { return ( ..
Lottie๋กœ ์ชฝ์ง€ ์ธ๋„ค์ผ์— ์ ์šฉํ•˜๊ธฐ
ยท
What I Learn
์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๊ฐ€ ์žˆ๋Š” ์ชฝ์ง€ ์ธ๋„ค์ผ์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ• ์ง€์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๋‹ค๊ฐ€, ๋‹ค๋ฅธ ํŒ€์›๋ถ„์ด ์˜๊ฒฌ๋‚ด์–ด์ฃผ์‹  ๋กœํ‹ฐ!!Lottie๋Š” ์—์–ด๋น„์—”๋น„์—์„œ ๊ฐœ๋ฐœํ•œ ์˜คํ”ˆ์†Œ์Šค ๋ชจ๋ฐ”์ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ๋ฒกํ„ฐ ๊ธฐ๋ฐ˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด๋‹ค. ๋น„ํŠธ๋งต๊ณผ ๋‹ฌ๋ฆฌ ๋ฒกํ„ฐ๋Š” ์„ ๋ถ„๊ณผ ๋ฉด์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด์ƒ๋„ ์ €ํ•˜๊ฐ€ ์—†๊ณ  ์šฉ๋Ÿ‰๋„ ์ž‘๋‹ค.  png, jpeg, gif๋Š” ๋น„ํŠธ๋งต ๊ธฐ๋ฐ˜์ธ๋ฐ ์ด์™€ ๊ฐ™์€ ํ™•์žฅ์ž ํŒŒ์ผ์„ ํฌํ† ์ƒต์œผ๋กœ ํฌ๊ฒŒํฌ๊ฒŒ ํ™•๋Œ€ํ•ด๋ณด๋ฉด ์ •์‚ฌ๊ฐํ˜• ํ”ฝ์…€๋กœ ์ด๋ฏธ์ง€๊ฐ€ ์ด๋ฃจ์–ด์กŒ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. gif๋Š” ์ด๋Ÿฐ ํ”ฝ์…€ ์ด๋ฏธ์ง€๊ฐ€ ์—ฐ์†์ ์œผ๋กœ ๋ฐฐ์น˜๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์šฉ๋Ÿ‰๋„ ๋ฌด๊ฑฐ์›Œ์ง€๊ณ , ํ™”์งˆ์ด ๊นจ์งˆ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.ํฌํ† ์ƒต์ด๋ž‘ ์ผ๋Ÿฌ์ŠคํŠธ ์ข€ ๋งŒ์ ธ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ์Œ..   ํŒŒ์ผ ์ž์ฒด๋Š” ๋””์ž์ด๋„ˆ๋‹˜์ด ๋งŒ๋“ค์–ด์„œ .lottie๋กœ ์ฃผ์‹œ๊ฑฐ๋‚˜, json์œผ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ์ฃผ์…จ๋‹ค..lottie๋กœ..