Skip to content

Commit

Permalink
๐Ÿ› fix: ์ด๋ฏธ์ง€ ์ตœ์ ํ™” ๋ฐ ๋ชจ๋ฐ”์ผ ๋ ˆ์ด์•„์›ƒ ๋ณ€๊ฒฝ
Browse files Browse the repository at this point in the history
- ์ด๋ฏธ์ง€ ์ตœ์ ํ™” ๊ฐœ์„ (next.config.js)
- ํ”„๋กœ์ ํŠธ ๋””ํ…Œ์ผ ๋ชจ๋ฐ”์ผ ์ค‘์ฒฉ ๊ฐœ์„ 
  • Loading branch information
gr22nist committed Nov 16, 2024
1 parent 2d3bef3 commit 08dca08
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 70 deletions.
30 changes: 16 additions & 14 deletions components/project/AccordionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,24 @@ export function AccordionCard({ title, tags, isOpen, onToggle, children }: Accor
<div className="rounded-lg border bg-card text-card-foreground shadow-sm">
<button
onClick={onToggle}
className="flex w-full items-center justify-between p-4"
className="w-full p-4"
>
<div className="flex items-center gap-3">
<h3 className="text-lg font-medium">{title}</h3>
<div className="flex gap-2">
{tags?.map((tag, index) => (
<div key={index}>{tag}</div>
))}
<div className="flex items-start justify-between gap-4">
<div className="flex flex-col sm:flex-row sm:items-center gap-2">
<h3 className="text-lg font-medium">{title}</h3>
{tags && tags.length > 0 && (
<div className="flex flex-wrap gap-2">
{tags}
</div>
)}
</div>
<ChevronDown
className={cn(
"h-4 w-4 shrink-0 transition-transform duration-200 mt-1.5",
isOpen && "rotate-180"
)}
/>
</div>
<ChevronDown
className={cn(
"h-4 w-4 shrink-0 transition-transform duration-200",
isOpen && "rotate-180"
)}
/>
</button>
<AnimatePresence initial={false}>
{isOpen && (
Expand All @@ -41,7 +43,7 @@ export function AccordionCard({ title, tags, isOpen, onToggle, children }: Accor
transition={{ duration: 0.2 }}
className="overflow-hidden"
>
<div className="p-4">
<div className="p-4 pt-0">
{children}
</div>
</motion.div>
Expand Down
3 changes: 3 additions & 0 deletions components/project/TroubleShooting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ export function TroubleShooting({ items }: TroubleShootingProps) {
onToggle={() => toggleItem(index)}
>
<div className="space-y-4">
<div>
<p className="text-muted-foreground">{item.issue}</p>
</div>
{item.process && item.process.length > 0 && (
<div>
<h4 className="font-medium mb-2">ํ•ด๊ฒฐ ๊ณผ์ •</h4>
Expand Down
255 changes: 200 additions & 55 deletions data/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ export const projects: Project[] = [
id: "portfolio",
title: "DEVIN DOWN",
description: [
"Next.js์™€ TypeScript๋กœ ๋งŒ๋“  ๊ฐœ์ธ ํฌํŠธํด๋ฆฌ์˜ค ์›น์‚ฌ์ดํŠธ",
"ํŽธ์•ˆํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜๊ณผ ์„ฑ๋Šฅ ์ง€ํ‘œ์— ์ค‘์ ์„ ๋‘” ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋กœ์ ํŠธ"
"Next.js, TypeScript๋กœ ๋งŒ๋“  ํฌํŠธํด๋ฆฌ์˜ค",
"ํŽธ์•ˆํ•œ UX์™€ ์„ฑ๋Šฅ ์ตœ์ ํ™” ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋กœ์ ํŠธ"
],
status: {
main: "์šด์˜ ์ค‘",
Expand Down Expand Up @@ -156,71 +156,159 @@ export const projects: Project[] = [
main: "์šด์˜ ์ค‘",
additional: ["๋ฒ„์ „ 1.0"]
},
period: "2024.01 ~ 2024.02",
period: "2024.07 ~ 2024.08",
content: {
overview: "SQL ์ž…๋ฌธ์ž๊ฐ€ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์›น ์—๋””ํ„ฐ ๊ธฐ๋ฐ˜ SQLite ํ•™์Šต ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.\nํ•œ๊ธ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ•™์Šต ์ง„์ž… ์žฅ๋ฒฝ์„ ๋‚ฎ์ถ”๊ณ , ์žฌ๋ฏธ์žˆ๋Š” ํ•™์Šต์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.",
role: {
main: "ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ (4์ธ ํŒ€ ํ”„๋กœ์ ํŠธ)",
tasks: [
"SQLite ํ•™์Šต์„ ์œ„ํ•œ ์ง๊ด€์ ์ธ UI/UX ๊ตฌํ˜„",
"์ƒ˜ํ”Œ ํ•œ๊ธ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ œ๊ณต",
"์›น ์—๋””ํ„ฐ ๊ธฐ๋ฐ˜ SQLite ํ•™์Šต ๊ธฐ๋Šฅ ๊ตฌํ˜„"
"์›น ์—๋””ํ„ฐ ๊ธฐ๋ฐ˜ SQLite ํ•™์Šต ๊ธฐ๋Šฅ ๊ตฌํ˜„",
"ํ›„์† ์ž‘์—…์œผ๋กœ ์ž๋ฃŒ ๋ฐ ๋ฐ˜์‘ํ˜• ๋ ˆ์ด์•„์›ƒ, ์ƒ˜ํ”Œ DB ์ถ”๊ฐ€"
],
participation: 50
},
challenges: [
{
title: "SQL ํ•™์Šต ์ง„์ž… ์žฅ๋ฒฝ ๋‚ฎ์ถ”๊ธฐ",
tags: ["UX", "๊ต์œก"],
issue: "์ž…๋ฌธ ํ•™์Šต์ž์˜ ์ˆ˜์ค€์„ ๊ณ ๋ คํ•œ ํŽธ์˜์„ฑ ํ•„์š”",
solution: "๋ฌธ์„œ์™€ ์—๋””ํ„ฐ๋ฅผ ๊ฐ™์€ ํŽ˜์ด์ง€์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„",
result: "๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜๊ณ  ์—ฐ์Šต ๋ฌธ์ œ ์นดํ”ผ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋น ๋ฅธ ํ•™์Šต ์œ ๋„"
issue: "SQL ์ดˆ๋ณด์ž๋“ค์ด ๊ฒช๋Š” ์„ค์น˜์™€ ํ™˜๊ฒฝ์„ค์ •์˜ ์–ด๋ ค์›€",
solution: [
"์›น ๊ธฐ๋ฐ˜ SQLite ์—๋””ํ„ฐ๋กœ ์„ค์น˜ ๊ณผ์ • ์ œ๊ฑฐ",
"K-๋ฌธํ™” ํ…Œ๋งˆ์˜ ํ•œ๊ธ€ ๋ฐ์ดํ„ฐ๋กœ ์นœ์ˆ™์„ฑ ํ™•๋ณด",
"๋ฌธ์„œ์™€ ์—๋””ํ„ฐ๋ฅผ ๊ฐ™์€ ํ™”๋ฉด์— ๋ฐฐ์น˜ํ•˜์—ฌ ํ•™์Šต ํšจ์œจ ํ–ฅ์ƒ"
],
result: "์„ค์น˜ ์—†์ด ๋ฐ”๋กœ ์‹œ์ž‘ํ•˜๋Š” SQL ํ•™์Šต ๊ฒฝํ—˜ ์ œ๊ณต"
},
{
title: "ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ ˆ์ด์•„์›ƒ ๊ตฌํ˜„",
tags: ["UI/UX", "๋ฐ˜์‘ํ˜•"],
issue: "๋””๋ฐ”์ด์Šค๋ณ„๋กœ ๋‹ค๋ฅธ ํ•™์Šต ๊ฒฝํ—˜ ์ตœ์ ํ™” ํ•„์š”",
solution: [
"๋ชจ๋ฐ”์ผ์—์„œ๋Š” ๋ฌธ์„œ์™€ ์—๋””ํ„ฐ๋ฅผ ์„ธ๋กœ๋กœ ๋ฐฐ์น˜",
"๋ฐ์Šคํฌํ†ฑ์—์„œ๋Š” ์ขŒ์šฐ ๋ถ„ํ•  ๋ ˆ์ด์•„์›ƒ ์ ์šฉ",
"Next.js Image์™€ Font ์ตœ์ ํ™”๋กœ CLS ๊ฐœ์„ "
],
result: "๋””๋ฐ”์ด์Šค ํŠน์„ฑ์— ๋งž๋Š” ์ตœ์ ํ™”๋œ ํ•™์Šต ๊ฒฝํ—˜ ์ œ๊ณต"
},
{
title: "์„ฑ๋Šฅ๊ณผ ๋ณด์•ˆ ์ตœ์ ํ™”",
tags: ["์„ฑ๋Šฅ", "๋ณด์•ˆ"],
issue: "์—๋””ํ„ฐ ๋ฒˆ๋“ค ํฌ๊ธฐ์™€ XSS ์ทจ์•ฝ์  ์œ„ํ—˜",
solution: [
"CodeMirror ๋™์  ์ž„ํฌํŠธ๋กœ ์ดˆ๊ธฐ ๋กœ๋”ฉ ์ตœ์ ํ™”",
"DOMPurify๋กœ ๋งˆํฌ๋‹ค์šด ์ฝ˜ํ…์ธ  ์†Œ๋…",
"Next.js CSP๋กœ ๋ฆฌ์†Œ์Šค ๋ณด์•ˆ ๊ฐ•ํ™”"
],
result: "Lighthouse ์„ฑ๋Šฅ ์ ์ˆ˜ 98์  ๋ฐ ์•ˆ์ „ํ•œ ์ฝ˜ํ…์ธ  ์ œ๊ณต"
}
],
troubleShooting: [
{
title: "๋‹คํฌ๋ชจ๋“œ ์ „ํ™˜ ์‹œ ๊นœ๋นก์ž„ ๋ฌธ์ œ ํ•ด๊ฒฐ",
tags: ["UX", "Next.js"],
issue: "ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ ์‹œ ๋‹คํฌ๋ชจ๋“œ ํ…Œ๋งˆ๊ฐ€ ๋Šฆ๊ฒŒ ์ ์šฉ๋˜์–ด ๊นœ๋นก์ด๋Š” ํ˜„์ƒ ๋ฐœ์ƒ",
title: "๋ฐ˜์‘ํ˜• ๋ ˆ์ด์•„์›ƒ ์ตœ์ ํ™”",
tags: ["UI/UX", "๋ ˆ์ด์•„์›ƒ"],
issue: "๋ชจ๋ฐ”์ผ๊ณผ ๋ฐ์Šคํฌํ†ฑ์—์„œ ๋ฌธ์„œ์™€ ์—๋””ํ„ฐ์˜ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์กฐ๊ฐ€ ๋‹ฌ๋ผ์•ผ ํ•˜๋Š” ๋ฌธ์ œ",
process: [
"useStore๋กœ ์ „์—ญ ์ƒํƒœ์—์„œ ํ™”๋ฉด ํฌ๊ธฐ ๊ด€๋ฆฌ",
"๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ๋ณ„ ๋ ˆ์ด์•„์›ƒ ๋ถ„์„",
"์ปดํฌ๋„ŒํŠธ ์žฌ์‚ฌ์šฉ์„ฑ ๊ฒ€ํ† "
],
solution: [
"totalOffset ๊ฐ’์„ ํ™œ์šฉํ•œ ๋™์  ๋†’์ด ๊ณ„์‚ฐ",
"isMobile ์ƒํƒœ์— ๋”ฐ๋ฅธ ์กฐ๊ฑด๋ถ€ ๋ ˆ์ด์•„์›ƒ ๋ Œ๋”๋ง",
"CSS Grid์™€ Flexbox ์กฐํ•ฉ์œผ๋กœ ์œ ์—ฐํ•œ ๋ ˆ์ด์•„์›ƒ ๊ตฌํ˜„"
],
result: "๋””๋ฐ”์ด์Šค๋ณ„ ์ตœ์ ํ™”๋œ ํ•™์Šต ๊ฒฝํ—˜ ์ œ๊ณต",
relatedTech: ["Tailwind CSS", "Zustand"]
},
{
title: "SQL ์—๋””ํ„ฐ ์žฌ์‚ฌ์šฉ์„ฑ ๊ฐœ์„ ",
tags: ["์„ฑ๋Šฅ", "์•„ํ‚คํ…์ฒ˜"],
issue: "์‹œ์ž‘ ํŽ˜์ด์ง€์™€ ์—๋””ํ„ฐ ํŽ˜์ด์ง€์—์„œ ๋™์ผํ•œ ์—๋””ํ„ฐ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ ์‹œ ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ ๋กœ๋“œ",
process: [
"์—๋””ํ„ฐ ์ปดํฌ๋„ŒํŠธ ๋ถ„์„",
"๊ณตํ†ต ๊ธฐ๋Šฅ๊ณผ ํŽ˜์ด์ง€๋ณ„ ๊ธฐ๋Šฅ ๋ถ„๋ฆฌ",
"๋™์  ์ž„ํฌํŠธ ์ „๋žต ์ˆ˜๋ฆฝ"
],
solution: [
"isEditorPage prop์œผ๋กœ ๊ธฐ๋Šฅ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ",
"dynamic import๋กœ ์—๋””ํ„ฐ ์ง€์—ฐ ๋กœ๋”ฉ",
"LoadingEditor ์ปดํฌ๋„ŒํŠธ๋กœ ๋กœ๋”ฉ UX ๊ฐœ์„ "
],
result: "ํŽ˜์ด์ง€๋ณ„ ์ตœ์ ํ™”๋œ ์—๋””ํ„ฐ ๋กœ๋”ฉ๊ณผ ์‚ฌ์šฉ์„ฑ ํ–ฅ์ƒ",
relatedTech: ["Next.js", "CodeMirror"]
},
{
title: "๋งˆํฌ๋‹ค์šด ์ฝ˜ํ…์ธ  ๋ณด์•ˆ ๊ฐ•ํ™”",
tags: ["๋ณด์•ˆ", "XSS"],
issue: "์‚ฌ์šฉ์ž ์ƒ์„ฑ ๋งˆํฌ๋‹ค์šด ์ฝ˜ํ…์ธ ์˜ XSS ์ทจ์•ฝ์  ์œ„ํ—˜",
process: [
"next-themes ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ถ„์„",
"suppressHydrationWarning ์˜ต์…˜ ๊ฒ€ํ† ",
"์ดˆ๊ธฐ ๋ Œ๋”๋ง ํ”„๋กœ์„ธ์Šค ์ตœ์ ํ™”"
"๋งˆํฌ๋‹ค์šด ํŒŒ์‹ฑ ํ”„๋กœ์„ธ์Šค ๋ถ„์„",
"DOMPurify ์„ค์ • ๊ฒ€ํ† ",
"ํ—ˆ์šฉํ•  HTML ํƒœ๊ทธ์™€ ์†์„ฑ ์ •์˜"
],
solution: "next-themes์˜ suppressHydrationWarning ์ ์šฉ ๋ฐ ์ดˆ๊ธฐ ๋ Œ๋”๋ง ์ตœ์ ํ™”",
result: "๋ถ€๋“œ๋Ÿฌ์šด ํ…Œ๋งˆ ์ „ํ™˜ ๊ตฌํ˜„ ๋ฐ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๊ฐœ์„ ",
relatedTech: ["next-themes", "Next.js"]
solution: [
"DOMPurify๋กœ HTML ์ฝ˜ํ…์ธ  sanitize",
"ํ—ˆ์šฉ๋œ ํƒœ๊ทธ์™€ ์†์„ฑ๋งŒ ํ•„ํ„ฐ๋งํ•˜์—ฌ ๋ Œ๋”๋ง"
],
result: "์•ˆ์ „ํ•œ ๋งˆํฌ๋‹ค์šด ๋ Œ๋”๋ง๊ณผ XSS ๊ณต๊ฒฉ ๋ฐฉ์ง€",
relatedTech: ["DOMPurify"]
}
],
techStacks: [
{
name: "Next.js",
reason: "๋น ๋ฅธ ํŽ˜์ด์ง€ ๋กœ๋“œ์™€ SEO ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์„ ํƒ"
reason: "๋น ๋ฅธ ํŽ˜์ด์ง€ ๋กœ๋“œ์™€ SEO ์ตœ์ ํ™”",
description: "App Router, Image/Font ์ตœ์ ํ™”, CSP ์„ค์ • ํ™œ์šฉ"
},
{
name: "Flask",
reason: "๊ฒฝ๋Ÿ‰ํ™”๋œ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ๊ตฌ์ถ•๊ณผ SQLite ์—ฐ๋™์„ ์œ„ํ•ด ์„ ํƒ"
}
name: "CodeMirror",
reason: "SQL ์—๋””ํ„ฐ ๊ตฌํ˜„",
description: "๊ตฌ๋ฌธ ๊ฐ•์กฐ, ์ž๋™์™„์„ฑ, ์‹ค์‹œ๊ฐ„ ๋ฌธ๋ฒ• ๊ฒ€์‚ฌ ๊ธฐ๋Šฅ ์ œ๊ณต"
},
{
name: "Tailwind CSS",
reason: "๋ฐ˜์‘ํ˜• UI ๊ฐœ๋ฐœ",
description: "๋‹คํฌ๋ชจ๋“œ์™€ ๋ฐ˜์‘ํ˜• ๋ ˆ์ด์•„์›ƒ ๊ตฌํ˜„์— ํ™œ์šฉ"
},
{
name: "Zustand",
reason: "์ƒํƒœ ๊ด€๋ฆฌ",
description: "๊ฒฝ๋Ÿ‰ํ™”๋œ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋กœ ๋ ˆ์ด์•„์›ƒ ์ƒํƒœ ์ œ์–ด"
},
],
features: [
{
title: "ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ Œ๋”๋ง",
description: "SSR๊ณผ SSG๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ์ตœ์ ์˜ ์„ฑ๋Šฅ ์ œ๊ณต",
tags: ["์„ฑ๋Šฅ", "SEO"]
title: "ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ ˆ์ด์•„์›ƒ",
description: "๋””๋ฐ”์ด์Šค ํฌ๊ธฐ์— ๋”ฐ๋ผ ์ตœ์ ํ™”๋œ ๋ฌธ์„œ-์—๋””ํ„ฐ ๋ ˆ์ด์•„์›ƒ ์ œ๊ณต",
tags: ["UI/UX", "๋ฐ˜์‘ํ˜•"]
},
{
title: "ํ•œ๊ธ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค",
description: [
"K-POP ์•„ํ‹ฐ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค",
"ํ•œ๊ตญ ์˜ํ™” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค",
"๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ ๊ธฐ๋Šฅ"
],
tags: ["๋ฐ์ดํ„ฐ", "K-๋ฌธํ™”"]
},
{
title: "๋ฐ˜์‘ํ˜• ๋””์ž์ธ",
description: "๋ชจ๋“  ๋””๋ฐ”์ด์Šค์—์„œ ์ตœ์ ํ™”๋œ ๋ ˆ์ด์•„์›ƒ ์ œ๊ณต",
tags: ["UI/UX", "์ ‘๊ทผ์„ฑ"]
title: "์ตœ์ ํ™”๋œ ํ•™์Šต ๊ฒฝํ—˜",
description: [
"๋ฌธ์„œ์™€ ์—๋””ํ„ฐ ํ†ตํ•ฉ ์ธํ„ฐํŽ˜์ด์Šค",
"๋””๋ฐ”์ด์Šค๋ณ„ ์ตœ์ ํ™”๋œ ๋ ˆ์ด์•„์›ƒ",
"์—ฐ์Šต ๋ฌธ์ œ ๋ณต์‚ฌ ๋ฐ ์‹คํ–‰ ๊ธฐ๋Šฅ"
],
tags: ["UX", "๊ต์œก"]
},
{
title: "๋‹คํฌ๋ชจ๋“œ",
description: "์‹œ์Šคํ…œ ์„ค์ •๊ณผ ์—ฐ๋™๋˜๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ํ…Œ๋งˆ ์ „ํ™˜",
tags: ["UI/UX", "์ ‘๊ทผ์„ฑ"]
title: "์•ˆ์ „ํ•œ ์ฝ˜ํ…์ธ  ๋ Œ๋”๋ง",
description: "DOMPurify๋ฅผ ํ™œ์šฉํ•œ ๋งˆํฌ๋‹ค์šด ์ฝ˜ํ…์ธ  ๋ณด์•ˆ ์ฒ˜๋ฆฌ",
tags: ["๋ณด์•ˆ", "๋งˆํฌ๋‹ค์šด"]
}
]
},
tech: ["Next.js", "Tailwind CSS", "Zustand", "Python", "Flask", "MariaDB"],
tech: ["Next.js", "Tailwind CSS", "Zustand", "Python", "Flask", "SQLite"],
links: {
github: "https://github.com/gr22nist/sqool",
demo: "https://sqool.kr"
Expand Down Expand Up @@ -272,51 +360,108 @@ export const projects: Project[] = [
],
troubleShooting: [
{
title: "์ƒํƒœ ๊ด€๋ฆฌ ์„ฑ๋Šฅ ์ตœ์ ํ™”",
tags: ["์„ฑ๋Šฅ", "์ƒํƒœ๊ด€๋ฆฌ"],
issue: "๋ณต์žกํ•œ ์ƒํƒœ ๊ด€๋ฆฌ์™€ ๋ฒˆ๋“ค ํฌ๊ธฐ๋กœ ์ธํ•œ ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฌธ์ œ",
title: "ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ฐ์ดํ„ฐ ๋ณด์•ˆ",
tags: ["๋ณด์•ˆ", "์•„ํ‚คํ…์ฒ˜"],
issue: "๋ฏผ๊ฐํ•œ ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ์™€ ๋ฐ์ดํ„ฐ ์œ ์ถœ ๋ฐฉ์ง€",
process: [
"IndexedDB๋ฅผ ํ™œ์šฉํ•œ ๋กœ์ปฌ ์ €์žฅ์†Œ ๊ตฌํ˜„",
"AES-256 ์•”ํ˜ธํ™” ์ ์šฉ",
"๋ฐ์ดํ„ฐ ๋ณตํ˜ธํ™” ๋กœ์ง ์ตœ์ ํ™”"
],
solution: [
"๋ฏผ๊ฐ ์ •๋ณด ์•”ํ˜ธํ™” ์ €์žฅ",
"์„น์…˜๋ณ„ ๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌ ์ €์žฅ",
"์—๋Ÿฌ ๋ณต๊ตฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๊ตฌํ˜„"
],
result: "์„œ๋ฒ„ ์—†์ด ์•ˆ์ „ํ•œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๊ตฌํ˜„"
},
{
title: "๋™์  ์„น์…˜ ๊ด€๋ฆฌ",
tags: ["UX", "์ƒํƒœ๊ด€๋ฆฌ"],
issue: "๋ณต์žกํ•œ ์ด๋ ฅ์„œ ์„น์…˜์˜ ์‹ค์‹œ๊ฐ„ ์ƒํƒœ ๊ด€๋ฆฌ",
process: [
"์„น์…˜ CRUD ๋กœ์ง ๋ถ„์„",
"์ƒํƒœ ์—…๋ฐ์ดํŠธ ์ตœ์ ํ™”",
"๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ ๊ตฌํ˜„"
],
solution: [
"useCallback์œผ๋กœ ํ•ธ๋“ค๋Ÿฌ ์ตœ์ ํ™”",
"uuid๋ฅผ ๋„์ž…ํ•˜์—ฌ ์„น์…˜ ์˜ค๋” ๊ด€๋ฆฌ",
"์‹ค์‹œ๊ฐ„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์—ฐ๋™"
],
result: "์„น์…˜ ์ˆœ์„œ ๊ด€๋ฆฌ ๋ฐ ์‹ค์‹œ๊ฐ„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์—ฐ๋™"
},
{
title: "๋ฐ์ดํ„ฐ ์ด์‹์„ฑ",
tags: ["๊ธฐ๋Šฅ", "UX"],
issue: "๋ธŒ๋ผ์šฐ์ € ๊ฐ„ ๋ฐ์ดํ„ฐ ์ด๋™๊ณผ ๋ฐฑ์—… ํ•„์š”",
process: [
"์„ฑ๋Šฅ ๋ณ‘๋ชฉ ์ง€์  ๋ถ„์„",
"์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋กœ์ง ๊ฒ€ํ† ",
"๋™์  ์ž„ํฌํŠธ ์ ์šฉ ๊ฒ€ํ† "
"๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๋ถ„์„",
"์ž„ํฌํŠธ/์—‘์ŠคํฌํŠธ ๋กœ์ง ์„ค๊ณ„",
"์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ตฌํ˜„"
],
solution: [
"JSON ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ ์ง๋ ฌํ™”",
"์„น์…˜ ์ˆœ์„œ ๋ณด์กด",
"๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ๋กœ์ง ์ถ”๊ฐ€"
],
solution: "๋™์  ์ž„ํฌํŠธ๋ฅผ ํ™œ์šฉํ•˜๊ณ  ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ๋กœ ๋ Œ๋”๋ง ์ตœ์ ํ™”",
result: "ํŽ˜์ด์ง€ ๋กœ๋“œ ์‹œ๊ฐ„ 30% ๊ฐ์†Œ, ์‹ค์‹œ๊ฐ„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์„ฑ๋Šฅ ๊ฐœ์„ ",
relatedTech: ["Zustand", "Dynamic Import"]
result: "์•ˆ์ •์ ์ธ ๋ฐ์ดํ„ฐ ์ด์‹ ๊ธฐ๋Šฅ ๊ตฌํ˜„"
}
],
techStacks: [
{
name: "Next.js",
reason: "ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง๊ณผ ์ •์  ํŽ˜์ด์ง€ ์ƒ์„ฑ์„ ์œ„ํ•ด ์„ ํƒ",
description: "๋น ๋ฅธ ์ดˆ๊ธฐ ๋กœ๋”ฉ๊ณผ SEO ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ Œ๋”๋ง ํ™œ์šฉ"
reason: "ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ์ตœ์ ํ™”",
description: "App Router, Image/Font ์ตœ์ ํ™”, CSP ์„ค์ • ํ™œ์šฉ"
},
{
name: "IndexedDB",
reason: "ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ฐ์ดํ„ฐ ์ €์žฅ๊ณผ ๋ณด์•ˆ์„ ์œ„ํ•ด ์„ ํƒ",
description: "์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์— ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌ"
reason: "ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ฐ์ดํ„ฐ ์ €์žฅ",
description: "Dexie.js๋กœ ์ถ”์ƒํ™”๋œ ์•ˆ์ „ํ•œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ"
},
{
name: "crypto-js",
reason: "๋ฐ์ดํ„ฐ ๋ณด์•ˆ",
description: "AES-256 ์•”ํ˜ธํ™”๋กœ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ ๋ณดํ˜ธ"
},
{
name: "@dnd-kit",
reason: "์„น์…˜ ๊ด€๋ฆฌ",
description: "๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ ๊ธฐ๋ฐ˜ ์„น์…˜ ์ •๋ ฌ ๊ตฌํ˜„"
},
{
name: "Zustand",
reason: "๊ฒฝ๋Ÿ‰ํ™”๋œ ์ƒํƒœ ๊ด€๋ฆฌ์™€ ๋†’์€ ์„ฑ๋Šฅ์„ ์œ„ํ•ด ์„ ํƒ",
description: "์‹ค์‹œ๊ฐ„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์™€ ์ž๋™ ์ €์žฅ์„ ์œ„ํ•œ ์ƒํƒœ ๊ด€๋ฆฌ"
reason: "์ƒํƒœ ๊ด€๋ฆฌ",
description: "๊ฒฝ๋Ÿ‰ํ™”๋œ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋กœ ์„น์…˜ ์ƒํƒœ ์ œ์–ด"
}
],
features: [
{
title: "ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ Œ๋”๋ง",
description: "SSR๊ณผ SSG๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ์ตœ์ ์˜ ์„ฑ๋Šฅ ์ œ๊ณต",
tags: ["์„ฑ๋Šฅ", "SEO"]
title: "Next.js ์ตœ์ ํ™”",
description: [
"App Router์™€ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ํ™œ์šฉ",
"Image/Font ์ž๋™ ์ตœ์ ํ™”",
"CSP ๊ธฐ๋ฐ˜ ๋ฆฌ์†Œ์Šค ๋ณด์•ˆ"
],
tags: ["์„ฑ๋Šฅ", "Next.js"]
},
{
title: "๋ฐ˜์‘ํ˜• ๋””์ž์ธ",
description: "๋ชจ๋“  ๋””๋ฐ”์ด์Šค์—์„œ ์ตœ์ ํ™”๋œ ๋ ˆ์ด์•„์›ƒ ์ œ๊ณต",
tags: ["UI/UX", "์ ‘๊ทผ์„ฑ"]
title: "๋ณด์•ˆ ์ค‘์‹ฌ ์„ค๊ณ„",
description: [
"์„œ๋ฒ„๋ฆฌ์Šค ์•„ํ‚คํ…์ฒ˜๋กœ ๋ฐ์ดํ„ฐ ์œ ์ถœ ๋ฐฉ์ง€",
"AES-256 ์•”ํ˜ธํ™”๋กœ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ ๋ณดํ˜ธ",
"์•ˆ์ „ํ•œ IndexedDB ์ €์žฅ์†Œ ํ™œ์šฉ"
],
tags: ["๋ณด์•ˆ", "์•„ํ‚คํ…์ฒ˜"]
},
{
title: "๋‹คํฌ๋ชจ๋“œ",
description: "์‹œ์Šคํ…œ ์„ค์ •๊ณผ ์—ฐ๋™๋˜๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ํ…Œ๋งˆ ์ „ํ™˜",
tags: ["UI/UX", "์ ‘๊ทผ์„ฑ"]
title: "์„น์…˜ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ",
description: [
"๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ ๊ธฐ๋ฐ˜ ์„น์…˜ ์ •๋ ฌ",
"์ปค์Šคํ…€ ์„น์…˜ ์ƒ์„ฑ ์ง€์›",
"์‹ค์‹œ๊ฐ„ ์ž๋™ ์ €์žฅ"
],
tags: ["UX", "๊ธฐ๋Šฅ"]
}
]
},
Expand Down
Loading

0 comments on commit 08dca08

Please sign in to comment.