๐Ÿ… ํ† ๋งˆํ† ๋“ค ํ”„๋กœ์ ํŠธ๋ฅผ ๋งบ์œผ๋ฉด์„œ

์นด๋ฏธ์œ ยท2025๋…„ 6์›” 16์ผ
0

ํ”„๋กœ์ ํŠธ ํšŒ๊ณ ๋ก

๋ชฉ๋ก ๋ณด๊ธฐ
2/5
post-thumbnail

โœ๏ธ ๋ธ”๋กœ๊ทธ ์ด์ „ ์•ˆ๋‚ด
์ด ๊ธ€์€ ์ด์ „์— ์šด์˜ํ•˜๋˜ ๋ธ”๋กœ๊ทธ์— ์ž‘์„ฑ๋œ ๊ธ€์ž…๋‹ˆ๋‹ค. ๋ธ”๋กœ๊ทธ๋ฅผ ์ด์ „ํ•˜๋ฉฐ ๋ชจ๋“  ๊ธฐ๋ก์„ ์ด๊ณณ์œผ๋กœ ์˜ฎ๊ฒจ์™”์Šต๋‹ˆ๋‹ค. ๊ธ€์— ํฌํ•จ๋œ ์ •๋ณด๋Š” ์ตœ์ดˆ ์ž‘์„ฑ ์‹œ์ ์„ ๊ธฐ์ค€์œผ๋กœ ํ•˜๊ณ  ์žˆ์œผ๋‹ˆ, ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”. ๋ณธ ๊ฒŒ์‹œ๊ธ€์€ 2024๋…„ 11์›” 3์ผ์— ์ž‘์„ฑ๋์Šต๋‹ˆ๋‹ค.

๋“ค์–ด๊ฐ€๋ฉด์„œ

์ง€๋‚œ 9์›” ์ค‘์ˆœ๋ถ€ํ„ฐ 10์›”๊นŒ์ง€, ํ”„๋กœ์ ํŠธ ์บ ํ”„: Next.js 3๊ธฐ๋ผ๋Š” ๊ต์œก ํ”„๋กœ๊ทธ๋žจ์— ์ฐธ์—ฌํ•˜๊ฒŒ ๋์Šต๋‹ˆ๋‹ค. 2์ฃผ๊ฐ„์˜ ์‚ฌ์ „ ๊ต์œก ๊ธฐ๊ฐ„ ์ดํ›„ 4์ฃผ๋™์•ˆ์˜ ํŒ€ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ๊ณ , ์ด์— ๋Œ€ํ•œ ํšŒ๊ณ ๋ฅผ ํ’€์–ด๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

ํ† ๋งˆํ† ๋“ค์ด๋ž€

ํ† ๋งˆํ† ๋“ค์€ ๋Œ€ํ•™์ƒ๋“ค์ด ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์™ธํ™œ๋™๊ณผ ๊ณต๋ชจ์ „ ์ •๋ณด๋ฅผ ์†์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณตํ•˜๊ณ , ์ทจ์—…๊ณผ ๋Œ€ํ•™์ƒํ™œ์— ๋„์›€์ด ๋˜๋Š” ๋‹ค์–‘ํ•œ ์ •๋ณด๋ฅผ ์•ˆ๋‚ดํ•˜๋Š” ์›น ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋Š” ๊ธฐ์—…๊ณผ์˜ ์—ฐ๊ณ„ ๊ณผ์ •์œผ๋กœ ์ง„ํ–‰๋˜์—ˆ๊ณ , ํ•„์š”ํ•œ ๋””์ž์ธ ํŒŒ์ผ๊ณผ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์†Œ๊ฐœ๋Š” ๋ฏธ๋ฆฌ ๊ธฐ์—…์ธก์œผ๋กœ๋ถ€ํ„ฐ ์ œ๊ณต๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

ํ† ๋งˆํ† ๋“ค์˜ ์ฃผ์š” ๊ธฐ๋Šฅ์€ ํฌ๊ฒŒ ํ™ˆ, ๋งค๊ฑฐ์ง„, ๋Œ€์™ธํ™œ๋™ ๋ฐ ๊ณต๋ชจ์ „ ํŽ˜์ด์ง€์™€ ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.

  • ํ™ˆ: ๋งค๊ฑฐ์ง„๊ณผ ๊ณต๋ชจ์ „ ๋ฐ ๋Œ€์™ธํ™œ๋™ ์ •๋ณด ๋ชจ์•„๋ณด๊ธฐ
  • ๊ณต๋ชจ์ „/๋Œ€์™ธํ™œ๋™: ๊ณต๋ชจ์ „๊ณผ ๋Œ€์™ธํ™œ๋™์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํ•„ํ„ฐ์™€ ์ •๋ ฌ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ํ™•์ธํ•˜๊ธฐ
  • ๋งค๊ฑฐ์ง„: ๋Œ€ํ•™์ƒํ™œ ๋ฐ ๋Œ€์™ธํ™œ๋™์— ๊ด€๋ จ๋œ ๋‹ค์–‘ํ•œ ํŒ ๋ชจ์•„๋ณด๊ธฐ
  • ๊ฒ€์ƒ‰: ๊ณต๋ชจ์ „๊ณผ ๋Œ€์™ธํ™œ๋™ ๋ฐ ๋งค๊ฑฐ์ง„์— ๋Œ€ํ•œ ์ •๋ณด ๊ฒ€์ƒ‰ํ•˜๊ธฐ

์ €๋Š” ์ด ์ค‘์—์„œ ๊ณต๋ชจ์ „ ๋ฐ ๋Œ€์™ธํ™œ๋™ ํŽ˜์ด์ง€์™€, ํ—ค๋”์™€ ํŽ˜์ด์ง€๋„ค์ด์…˜ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋Œ€์™ธํ™œ๋™ ๋ฐ ๊ณต๋ชจ์ „ ํŽ˜์ด์ง€์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํฌ๋กค๋งํ•˜๋Š” ์ž‘์—…๋„ ๋‹ด๋‹นํ–ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์–ด๋–ค ๊ธฐ๋Šฅ๋“ค์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ–ˆ๊ณ , ๋˜ ์–ด๋–ค ๊ณ ๋ฏผ๋“ค์„ ํ–ˆ๋Š”์ง€ ์•Œ์•„๋ณด๊ธฐ์— ์•ž์„œ ํ”„๋กœ์ ํŠธ์˜ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ํ•ด๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœํ™˜๊ฒฝ

๊ฐœ๋ฐœ ํ™˜๊ฒฝ์€ ํฌ๊ฒŒ ํ”„๋ก ํŠธ/๋ฐฑ์—”๋“œ์˜ ๊ธฐ์ˆ  ์Šคํƒ๊ณผ ํด๋” ๊ตฌ์กฐ, ๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ๋กœ ๋‚˜๋ˆ„์–ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๋จผ์ € ๊ธฐ์ˆ  ์Šคํƒ๋ถ€ํ„ฐ ์‚ดํŽด๋ณผ๊นŒ์š”?

ํ”„๋ก ํŠธ์—”๋“œ

ํ”„๋ก ํŠธ์—”๋“œ์—์„œ๋Š” Next.js, TypeScript, TailwindCSS๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

Next.js์˜ SSR์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ๊ณต๋ชจ์ „ ๋ฐ ๋Œ€์™ธํ™œ๋™ ์ •๋ณด์˜ ํŽ˜์ด์ง€๋ฅผ ๋น ๋ฅด๊ฒŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๊ณ , ํŒŒ์ผ ๊ตฌ์กฐ์— ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ…์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœ์ ํŠธ์˜ ํ™•์žฅ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์–ด์„œ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

TypeScript๋Š” ์ด์ œ๋Š” ์‚ฌ์‹ค์ƒ Next.js๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋””ํดํŠธ๊ฐ€ ๋œ ์Šคํƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ, ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•œ ๊ทธ ์ด์œ ๋ฅผ ๊ณ ๋ฅด์ž๋ฉด ๋‹จ์—ฐ ํƒ€์ž… ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ๋Š”๋ฐ, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์˜ ์ •์  ํƒ€์ž… ๊ฒ€์‚ฌ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์–ด๋””์— ์–ด๋–ค ๊ฐ’์ด ๋“ค์–ด๊ฐ€์•ผ ํ•˜๋Š”์ง€ ๋ณด๋‹ค ๋ช…ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

Tailwind CSS๋Š” ์‰ฝ๊ณ  ๋น ๋ฅธ ์ ์šฉ์„ ์œ„ํ•ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์ „์— ์ •์˜๋œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๊ฐ„ํŽธํ•˜๊ฒŒ ์Šคํƒ€์ผ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์—ˆ๊ณ , Next.js์™€์˜ ๊ธฐ๋ณธ ํ†ตํ•ฉ์ด ๊ฐ„ํŽธํ–ˆ์–ด์š”. ์ถ”ํ›„์— ์ด์•ผ๊ธฐ ํ•  ๋‚ด์šฉ์ง€๋งŒ, ์‚ฌ์ „์— ์ •์˜๋œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค๋ผ๋Š” ๊ฒƒ์ด ๋•Œ๋กœ๋Š” ๋งˆ๋ƒฅ ์ข‹์€ ๊ฒƒ๋งŒ์€ ์•„๋‹ˆ๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ ์™ธ์—๋„ ๋‹ค์–‘ํ•œ ์ด์œ ๊ฐ€ ์žˆ๊ฒ ์ง€๋งŒ, ์ถ”๊ฐ€์ ์œผ๋กœ 2์ฃผ๊ฐ„์˜ ์‚ฌ์ „ ์ง๋ฌด ๊ต์œก์—์„œ ์œ„ ์„ธ ๊ฐ€์ง€ ๊ธฐ์ˆ  ์Šคํƒ์„ ํ•™์Šตํ–ˆ๋‹ค๋Š” ์ ๋„ ์žˆ์—ˆ์–ด์š”. ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„๋™์•ˆ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ  ์Šคํƒ์„ ๋ฐฐ์šฐ๊ธฐ๋ณด๋‹ค๋Š” ๋ชจ๋‘๊ฐ€ ์–ด๋А์ •๋„ ์ต์ˆ™ํ•ด์ง„ ๊ธฐ์ˆ  ์Šคํƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋น ๋ฅธ ์ƒ์‚ฐ์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋ฐฑ์—”๋“œ

๋ฐฑ์—”๋“œ์—์„œ๋Š” Supabase, Python ๋“ฑ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

์ €ํฌ ํŒ€์€ ํ”„๋กœ์ ํŠธ์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋”ฐ๋กœ ์ฃผ์–ด์ง€์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ํฌ๋กค๋งํ•œ ๋’ค ๊ฐ€๊ณตํ•ด์•ผ ํ–ˆ๋Š”๋ฐ, ๊ฐ€๊ณต๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” DB์™€ ์ด๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „๋‹ฌํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ์„œ๋ฒ„๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋ธ”๋กœ๊ทธ๋ฅผ ๋งŒ๋“ค๋ฉด์„œ Supabase๋ฅผ ์‚ฌ์šฉํ•ด ๋ณธ ์ ์ด ์žˆ์—ˆ๋Š”๋ฐ, ๋งˆ์นจ ๋‹ค๋ฅธ ํŒ€์›๋„ ์‚ฌ์šฉํ•ด ๋ณธ ์ ์ด ์žˆ๋‹ค๊ณ  ํ•ด์„œ ๋น ๋ฅด๊ฒŒ ์Šต๋“ํ•˜๊ณ  ํ™œ์šฉ ๊ฐ€๋Šฅํ•œ ํ•ด๋‹น ๊ธฐ์ˆ ์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

Python์˜ ๊ฒฝ์šฐ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์ •๋ง ์˜ค๋žœ๋งŒ์— ์‚ฌ์šฉํ•ด ๋ณธ ์–ธ์–ด์˜€์Šต๋‹ˆ๋‹ค. ๊ธฐ์ดˆ์ ์ธ ๋ฌธ๋ฒ•์„ ์ œ์™ธํ•˜๋ฉด ์•„์˜ˆ ๋ชจ๋ฅด๊ณ  ์žˆ๋‹ค๊ณ  ๋งํ•ด๋„ ๊ณผ์–ธ์ด ์•„๋‹ ์ •๋„๋กœ ๋ถ€์กฑํ•œ ์ดํ•ด๋„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ, ํฌ๋กค๋ง ๊ด€๋ จ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋Š” LLM๊ณผ ํŒ€์›์˜ ๋„์›€์„ ๋งŽ์ด ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

ํด๋” ๊ตฌ์กฐ

Next.js๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ •ํ•ด์ง„ ํด๋” ๊ตฌ์กฐ๊ฐ€ ์žˆ์–ด์„œ, ํŠนํžˆ app ํด๋”์˜ ๊ฒฝ์šฐ ํ•ด๋‹น ์ปจ๋ฒค์…˜์„ ์ž˜ ๋”ฐ๋ฅด๊ธฐ๋งŒ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ณด๋‹ค ์ข‹์€ ํด๋” ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด์„œ, ๊ด€๋ จ ์ž๋ฃŒ๋ฅผ ์ฐพ์•„๋ณด๋˜ ์ค‘ containers ํด๋”๋ฅผ ํ™œ์šฉํ•ด UI ๋ฐ ๋ ˆ์ด์•„์›ƒ๊ณผ ๋ผ์šฐํ„ฐ ๊ด€๋ จ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ธ€์„ ์ฝ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Containers Structure

์œ„์™€ ๊ฐ™์ด api๋ฅผ ์ œ์™ธํ•˜๋ฉด app๊ณผ ์™„์ „ํžˆ ๋™์ผํ•œ ํ˜•ํƒœ์˜ ๊ตฌ์กฐ๋ฅผ containers์—์„œ ๊ฐ–์ถ˜ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { fetchActivityContestAbstractWith } from '@/lib/fetchActivityAbstractWith';
import Activity from '@/containers/activity/Activity';

// ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๊ฐ™์€ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ์— ํ•„์š”ํ•œ ๋กœ์ง

export default async function Page({ searchParams }: PageProps) {
	const filters = searchParams.filters?.split(',').filter(Boolean) || [];
	const sort = searchParams.sort || '๊ด€๋ จ๋„์ˆœ';

	const { data: activitiesContests, error } =
		await fetchActivityContestAbstractWith({
			filters,
			sort,
			mainCategory: '๋Œ€์™ธํ™œ๋™',
		});

	if (error) {
		// ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋กœ์ง
	}

	return <Activity activitiesContests={activitiesContests || []} />;
}

๊ทธ ๊ฒฐ๊ณผ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ด๋ ‡๊ฒŒ UI์™€ ํŽ˜์ด์ง€์˜ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•ด, ๋ณด๋‹ค ๊ฐ€๋…์„ฑ ๋†’์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์–ด์š”. ๋‚˜๋จธ์ง€ ๋‹ค๋ฅธ ํด๋”๋Š” ์ผ๋ฐ˜์ ์ธ ํด๋” ๊ตฌ์กฐ์™€ ๊ทธ ์—ญํ• ์ด ๋™์ผํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฌ˜ํ•˜๊ฒŒ ์ด์งˆ์ ์ธ ํด๋”๊ฐ€ ํ•˜๋‚˜ ์žˆ๋Š”๋ฐ, ๋ฐ”๋กœ scripts ํด๋”์ž…๋‹ˆ๋‹ค. ์•ž์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ์–ด์ง€์ง€ ์•Š์•˜๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ, ์ด์ œ ๋ฐ์ดํ„ฐ์™€ ํฌ๋กค๋ง์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ํ•ด ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ

ํ† ๋งˆํ† ๋“ค์—๋Š” ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋Œ€ํ•™์ƒํ™œ ๊ฟ€ํŒ๊ณผ ๊ด€๋ จ๋œ ๋งค๊ฑฐ์ง„ ํŽ˜์ด์ง€์—์„œ ๋ณด์—ฌ์ฃผ๋Š” ์ฝ˜ํ…์ธ ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ์™€, ๊ณต๋ชจ์ „ ๋ฐ ๋Œ€์™ธํ™œ๋™ ํŽ˜์ด์ง€์—์„œ ๋ณด์—ฌ์ฃผ๋Š” ์ฝ˜ํ…์ธ ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ์˜€์–ด์š”. ์ €๋Š” ๋‘˜ ์ค‘ ํ›„์ž๋ฅผ ๊ตฌํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

Tomatoes Data

์œ„์™€ ๊ฐ™์€ ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌํ•ด์•ผ ํ–ˆ๋Š”๋ฐ, ๋‹คํ–‰ํžˆ ๋Œ€ํ•™์ƒ์„ ์œ„ํ•œ ๋Œ€์™ธํ™œ๋™๊ณผ ๊ณต๋ชจ์ „์„ ์†Œ๊ฐœํ•˜๋Š” ๊ธฐ์กด์˜ ์„œ๋น„์Šค๋Š” ๋งŽ์•˜๊ธฐ์— ๊ทธ์ค‘ ํ•œ ๊ณณ์ธ '์บ ํผ์Šคํ”ฝ'์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํฌ๋กค๋งํ•ด ์˜ค๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํฌ๋กค๋งํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌด๋‹จ์œผ๋กœ ์ƒ์—…์ ์ธ ์šฉ๋„๋กœ ํ™œ์šฉํ•˜๋ฉด ๋‹น์—ฐํžˆ ๋ฒ•์ ์ธ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์„ค๋ช…์„ ์ด์–ด๊ฐ€๊ธฐ์— ์•ž์„œ ์ €ํฌ๊ฐ€ ํฌ๋กค๋ง ํ•œ ๋ฐ์ดํ„ฐ๋Š” ๋น„์ƒ์—…์ ์ธ ์šฉ๋„๋กœ, ์–ด๋– ํ•œ ์ˆ˜์ต๋„ ์ฐฝ์ถœํ•˜์ง€ ์•Š์Œ์„ ๋ฏธ๋ฆฌ ๋ฐํž™๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ LLM๊ณผ ํ•จ๊ป˜ ์—ด์‹ฌํžˆ ๊ณ ๋ฏผํ•œ ๋’ค, ์šฐ์—ฌ๊ณก์ ˆ ๋์— ๋ฐ์ดํ„ฐ๋ฅผ ํฌ๋กค๋งํ•˜๊ธด ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํŒŒ์ด์ฌ์— ๋Œ€ํ•œ ์ง€์‹์ด ๋ถ€์กฑํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋งˆ๋‹ค ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งค๋ฒˆ ์‹คํ–‰์‹œ์ผœ์•ผ ํ–ˆ๊ณ , ๋•๋ถ„์— ์ •์ œ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๋Š” ๋ฐ๊นŒ์ง€ ๊ฝค๋‚˜ ์˜ค๋žœ ์‹œ๊ฐ„์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ํŒ€์›์˜ ๋„์›€์ด ์—†์—ˆ๋‹ค๋ฉด ๋” ๊ธด ์‹œ๊ฐ„์„ ํฌ๋กค๋ง์— ์†Œ๋ชจํ•ด์•ผ ํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฌธ์ œ๋Š” ์ด๊ฒƒ ๋ฟ๋งŒ์ด ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค.

Activity Category Filter

ํ† ๋งˆํ† ๋“ค์€ ๋Œ€์™ธํ™œ๋™๊ณผ ๊ณต๋ชจ์ „์—์„œ ์ ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹ค์–‘ํ•œ ํ•„ํ„ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ข…๋ฅ˜๊ฐ€ ์ด 84๊ฐ€์ง€๋‚˜ ๋์–ด์š”. ํฌ๋กค๋ง๋œ ๋ฐ์ดํ„ฐ์—๋Š” ํ•„ํ„ฐ๊ฐ€ ์—†์—ˆ๊ธฐ์— ๊ทธ ํ•„ํ„ฐ๋ฅผ ์ง์ ‘ ์ ์šฉํ•ด ์ค˜์•ผ ํ–ˆ๋Š”๋ฐ, ์ˆ˜๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์”ฉ ์ฝ์–ด๋ณด๋ฉด์„œ ์ง์ ‘ ์ข…๋ฅ˜์— ๋งž๋Š” ํ•„ํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•ด ์ฃผ๋Š” ๊ฒƒ ๋ง๊ณ ๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ๋– ์˜ค๋ฅด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ ์ž„์‹œ๋ฐฉํŽธ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํฌ๋กค๋งํ•œ ๋’ค ์ •์ œํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ฌด์ž‘์œ„๋กœ ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ•ด์™ธ ๋ด‰์‚ฌํ™œ๋™์ธ๋ฐ ๊ตญ๋‚ด ํ•„ํ„ฐ๊ฐ€ ์ ์šฉ๋˜์–ด ์žˆ๋‹ค๊ฑฐ๋‚˜ ํ•˜๋Š” ์•ˆํƒ€๊นŒ์šด ์ผ์ด ๋ฒŒ์–ด์ง€๊ณ  ๋ง์•˜์ง€๋งŒ, ๋”ฑํžˆ ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ๋– ์˜ค๋ฅด์ง€ ์•Š์•˜๊ณ  ๊ธฐํ•œ ๋‚ด์— ํ”„๋กœ์ ํŠธ๋ฅผ ์™„์ˆ˜ํ•ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์–ด์ฉ” ์ˆ˜ ์—†์ด ์ด๋Ÿฌํ•œ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ •์ œ๋œ ๋ฐ์ดํ„ฐ๋ฅผ Supabase์— ์ €์žฅํ•˜๊ณ , ํ•„์š”์— ๋”ฐ๋ผ ์š”์ฒญ์„ ๋ณด๋‚ด ๋ถˆ๋Ÿฌ์˜ค๋Š” ์‹์œผ๋กœ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„๊ณผ ๊ณ ๋ฏผ

ํ—ค๋”์™€ ๋‚ด๋น„๊ฒŒ์ด์…˜

์ œ๊ฐ€ ๋‹ด๋‹นํ–ˆ๋˜ ํ—ค๋”์™€ ๋‚ด๋น„๊ฒŒ์ด์…˜ ๋ฐ” ์ปดํฌ๋„ŒํŠธ๋Š” ์›น๊ณผ ๋ชจ๋ฐ”์ผ์—์„œ ๋ ˆ์ด์•„์›ƒ์ด ์ƒ์ดํ–ˆ์Šต๋‹ˆ๋‹ค.

Navigation Bar Mobile

๋ชจ๋ฐ”์ผ์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ๋‚ด๋น„๊ฒŒ์ด์…˜ ๋ฐ”๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด ์Šคํฌ๋ฆฐ์˜ ํ•˜๋‹จ์— ์œ„์น˜ํ•˜๋Š” ํ˜•ํƒœ์˜€์Šต๋‹ˆ๋‹ค. ์ด๊ฑธ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ๋– ์˜ฌ๋ ค ๋ดค๊ณ , ์ €๋Š” ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

  1. ์›น๊ณผ ๋ชจ๋ฐ”์ผ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋‚ด๋น„๊ฒŒ์ด์…˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‘ ๊ฐœ ๋งŒ๋“ค๊ณ , ์กฐ๊ฑด๋ถ€๋กœ ๋ Œ๋”๋งํ•˜๊ธฐ
  2. CSS๋ฅผ ํ™œ์šฉํ•ด ํ•˜๋‹ˆ์˜ ๋‚ด๋น„๊ฒŒ์ด์…˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์Šคํฌ๋ฆฐ width์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ๋ Œ๋”๋งํ•˜๊ธฐ โœ…
const containerClasses =
	'flex flex-1 items-center fixed md:static bottom-[30px] left-1/2 transform -translate-x-1/2 md:transform-none z-50';

const listClasses =
	'flex gap-6 lg:gap-10 bg-white h-full px-8 md:px-0 py-4 md:py-0 whitespace-nowrap shadow md:shadow-none border md:border-none border-sub-gray-100 rounded-full md:rounded-none items-center';

const linkItemClasses =
	'whitespace-nowrap text-base lg:text-xl font-medium lg:font-semibold rounded-full py-2 px-3';

const activeLinkClasses = 'bg-sub-yellow-500 text-sub-gray-500';

const inactiveLinkClasses = 'bg-sub-yellow-100 text-sub-gray-400';

์ด๋ ‡๊ฒŒ ์ปค์Šคํ…€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐ˜์‘ํ˜•์œผ๋กœ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํŽ˜์ด์ง€๋„ค์ด์…˜๊ณผ ๊ทธ๋ฆฌ๋“œ ๋ทฐ

ํ—ค๋”์™€ ๋‚ด๋น„๊ฒŒ์ด์…˜์ด ๋ง›๋ณด๊ธฐ์˜€๋‹ค๋ฉด, ํŽ˜์ด์ง€๋„ค์ด์…˜๊ณผ ๊ทธ๋ฆฌ๋“œ ๋ทฐ๊ฐ€ ์ €์—๊ฒŒ๋Š” ๋ฉ”์ธ ๋””์‰ฌ์˜€์Šต๋‹ˆ๋‹ค. ์š”์ฆ˜ ๋ง๋กœ๋Š” ํ‚ฅ์ด๋ผ๊ณ  ํ•  ์ˆ˜๋„ ์žˆ๊ฒ ๋„ค์š”. ํ”ํžˆ ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ํ‘œ์‹œํ•˜์ง€ ์•Š๊ณ  ๋‚˜๋ˆ ์„œ ํ‘œ์‹œํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํŽ˜์ด์ง€๋„ค์ด์…˜(Pagination)์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ํ† ๋งˆํ† ๋“ค์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ดํŽด๋ณผ๊นŒ์š”?

Tomatoes Pagination

์ €๋Š” ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด๋ ‡๊ฒŒ ๋ถ„๋ฆฌํ–ˆ์–ด์š”. ํŽ˜์ด์ง€ ์ปจํŠธ๋กค๊นŒ์ง€ ํฌํ•จํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” Pagination, ๋‚ด๋ถ€ ์ปจํ…์ธ ๋ฅผ ๊ทธ๋ฆฌ๋“œ ํ˜•ํƒœ๋กœ ๋ Œ๋”๋งํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” GridView ์˜€์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ์ด ๋‘ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ •๋ง ๋‹ค์–‘ํ•œ ๊ณณ์—์„œ, ์ •๋ง ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์—ˆ์–ด์š”. ๋จผ์ € GridView ์ปดํฌ๋„ŒํŠธ๋ถ€ํ„ฐ ์‚ดํŽด๋ณผ๊นŒ์š”?

GridView

  • ๋งค๊ฑฐ์ง„
    • ํ† ๋งˆํ†  Pick (์›น 4 * 2 / ๋ชจ๋ฐ”์ผ 2 * 3)
    • ํ† ๋งˆํ†  Tip (์›น 3 * 5 / ๋ชจ๋ฐ”์ผ 1 * 12)
  • ๋Œ€์™ธํ™œ๋™ ๋ฐ ๊ณต๋ชจ์ „
    • ์›น 4 * 4 / ๋ชจ๋ฐ”์ผ 2 * 5
    • ํ™ˆ
      • BEST PICK (์›น 2 * 4 / ๋ชจ๋ฐ”์ผ 2 * 3)
      • ํ† ๋งˆํ† ๋“ค ์ถ”์ฒœํ™œ๋™ (์›น 2 * 4 / ๋ชจ๋ฐ”์ผ ๊ทธ๋ฆฌ๋“œ ๋ทฐ ๋ฏธ์‚ฌ์šฉ)

์ด๋ ‡๊ฒŒ GridView ์ปดํฌ๋„ŒํŠธ๋Š” ์„œ๋น„์Šค ๋‚ด์˜ ๋งŽ์€ ๊ณณ์—์„œ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๋ถ€์— ๋ Œ๋”๋ง๋˜๋Š” ์ฝ˜ํ…์ธ ์˜ ์–‘๋„ ํŽ˜์ด์ง€๋ณ„๋กœ ๋‹ฌ๋ž๊ณ ์š”. ๊ทธ๋ž˜์„œ ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด ๋‘”๋‹ค๋ฉด ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์„ ๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๊ณ , ๊ณ ๋ฏผ ๋์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ GridView ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

export default function GridView<T>({
	items,
	GridItem,
	columnStyle,
	gapStyle,
}: GridViewProps<T>) {
	const columnStyles = {
		web4mobile2: 'grid-cols-2 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-4',
		web3mobile1: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3',
	};

	const gapStyles = {
		gapStyle1: 'gap-x-4 gap-y-8 md:gap-x-8 md:gap-y-12',
		gapStyle2: 'gap-x-6 gap-y-10 md:gap-x-10 md:gap-y-12',
		gapStyle3: 'gap-x-2 gap-y-6 md:gap-x-8 md:gap-y-10',
	};

	const gridClass =
		`grid ${columnStyles[columnStyle]} ${gapStyles[gapStyle]}`.trim();

	return (
		<div className={gridClass}>
			{items.map((item, index) => (
				<GridItem key={index} item={item} />
			))}
		</div>
	);
}

GridView ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ props๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค:

  • items: ๋ Œ๋”๋ง๋˜์–ด์•ผ ํ•˜๋Š” ์ฝ˜ํ…์ธ ์˜ ๋ฐ์ดํ„ฐ
  • GridItem: ๋ Œ๋”๋ง๋˜์–ด์•ผ ํ•˜๋Š” ์ฝ˜ํ…์ธ  ๋ ˆ์ด์•„์›ƒ ์ปดํฌ๋„ŒํŠธ
  • columnStyle: ์—ด์˜ ํ˜•ํƒœ
  • gapStyle: ๊ฐญ์˜ ํ˜•ํƒœ

์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์— ํ•„์š”ํ•œ props๋ฅผ ์ „๋‹ฌํ•˜๋ฉด, ์ด๋ฅผ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ณด๋‹ค ์œ ์—ฐํ•œ ์ปดํฌ๋„ŒํŠธ์˜ ์‚ฌ์šฉ์„ ์œ„ํ•ด์„œ, ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ํ™œ์šฉํ–ˆ์–ด์š”.

GridView JSDoc

๊ทธ๋ฆฌ๊ณ  JSDoc์„ ์‚ฌ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋น ๋ฅด๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋ช…์‹œํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

Pagination

ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ปดํฌ๋„ŒํŠธ๋„ GridView ๋งŒํผ์ด๋‚˜ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€์—์„œ ๋‹ค์–‘ํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  • ๋งค๊ฑฐ์ง„
    • ํ† ๋งˆํ†  Pick (์›น 8๊ฐœ / ๋ชจ๋ฐ”์ผ 6๊ฐœ)
    • ํ† ๋งˆํ†  Tip (์›น 15๊ฐœ / ๋ชจ๋ฐ”์ผ 12๊ฐœ)
  • ๋Œ€์™ธํ™œ๋™ ๋ฐ ๊ณต๋ชจ์ „
    • ์›น 16๊ฐœ / ๋ชจ๋ฐ”์ผ 10๊ฐœ
  • ํ™ˆ
    • BEST PICK (์›น 8๊ฐœ / ๋ชจ๋ฐ”์ผ 6๊ฐœ)
    • ํ† ๋งˆํ† ๋“ค ์ถ”์ฒœํ™œ๋™ (์›น 8๊ฐœ / ๋ชจ๋ฐ”์ผ ๊ทธ๋ฆฌ๋“œ ๋ทฐ ๋ฏธ์‚ฌ์šฉ)

๋ณด๋‹ค์‹œํ”ผ, ํŽ˜์ด์ง€๋„ค์ด์…˜์€ ํ•œ ํŽ˜์ด์ง€๋‹น ํ‘œ์‹œ๋˜๋Š” ์ฝ˜ํ…์ธ ์˜ ๊ฐœ์ˆ˜๊ฐ€ ํŽ˜์ด์ง€๋งˆ๋‹ค, ์›น๊ณผ ๋ชจ๋ฐ”์ผ ํ™˜๊ฒธ๋งˆ๋‹ค ์ƒ์ดํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ํŽ˜์ด์ง€๋‹น ํ‘œ์‹œ๋˜๋Š” ์ปจํ…์ธ ๊ฐ€ ์›น๊ณผ ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋˜๋Š” ๊ฒƒ์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋” ๋‚˜์€ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ(๊ตฌํ˜„ํ•˜๊ธฐ๋„ ๋” ์‰ฝ๊ณ ์š”), ์ตœ๋Œ€ํ•œ ๋””์ž์ธ์„ ๋”ฐ๋ฅด๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ „์—, ์šฐ์„  ์ด๋ ‡๊ฒŒ ํŽ˜์ด์ง€๋‹น ํ‘œ์‹œ๋˜๋Š” ์ปจํ…์ธ ๊ฐ€ ์›น/๋ชจ๋ฐ”์ผ์—์„œ ๋‹ฌ๋ผ์งˆ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ ์— ๋Œ€ํ•ด์„œ ์‚ดํŽด๋ณผ๊นŒ์š”?

๋จผ์ € 60๊ฐœ์˜ ์ปจํ…์ธ ์— ๋Œ€ํ•œ ํŽ˜์ด์ง€๋„ค์ด์…˜์ด ์ด๋ฃจ์–ด์ง„๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. ์›น์€ ํŽ˜์ด์ง€๋‹น 16๊ฐœ์˜ ์ปจํ…์ธ ๋ฅผ, ๋ชจ๋ฐ”์ผ์€ ํŽ˜์ด์ง€๋‹น 10๊ฐœ์˜ ์ปจํ…์ธ ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ์ƒ์„ฑ๋˜๋Š” ํŽ˜์ด์ง€์˜ ์ˆ˜๋Š” ๊ฐ๊ฐ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์›น: ( 16 ร— 3 + 12 ร— 1 ํŽ˜์ด์ง€) = 4 ํŽ˜์ด์ง€
  • ๋ชจ๋ฐ”์ผ: (10 ร— 6 ํŽ˜์ด์ง€) = 6 ํŽ˜์ด์ง€

์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค๋ฅธ ํ™˜๊ฒฝ์—์„œ ์›น๊ณผ ๋ชจ๋ฐ”์ผ ํŽ˜์ด์ง€๋ฅผ ํ™•์ธํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ํฐ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€๋Š” ์•Š๊ฒ ์ง€๋งŒ, ๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์˜ ๊ฐ€๋กœ ํฌ๊ธฐ๋ฅผ ๋ชจ๋ฐ”์ผ๋งŒํผ ์ค„์—ฌ์„œ ๋ณด๋‹ค๊ฐ€ ์›น์˜ ๊ฐ€๋กœ ํฌ๊ธฐ๋งŒํผ ๋Š˜๋ฆฐ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. ์ด๋•Œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ๋ฐ”์ผ์—์„œ 6ํŽ˜์ด์ง€๋ฅผ ๋ณด๊ณ  ์žˆ์—ˆ๋‹ค๋ฉด, ์›น์—์„œ๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€๋ฅผ ๋ณด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋‹น์—ฐํžˆ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค.

export default function useResponsiveItemsPerPage(
	webItemsPerPage: number,
	mobileItemsPerPage: number,
) {
	const [itemsPerPage, setItemsPerPage] = useState(webItemsPerPage);

	useEffect(() => {
		function handleResize() {
			if (window.innerWidth >= 768) {
				setItemsPerPage(webItemsPerPage);
			} else {
				setItemsPerPage(mobileItemsPerPage);
			}
		}

		handleResize();
		window.addEventListener('resize', handleResize);

		return () => {
			window.removeEventListener('resize', handleResize);
		};
	}, [webItemsPerPage, mobileItemsPerPage]);

	return itemsPerPage;
}

๊ทธ๋ž˜์„œ ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ํ›…์€ ์›น๊ณผ ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ ํ•„์š”ํ•œ ํŽ˜์ด์ง€ ๋‹น ์ปจํ…์ธ ์˜ ๊ฐœ์ˆ˜๋ฅผ ํ›…์œผ๋กœ ๋ฐ›์•„, ํ™”๋ฉด์˜ ๊ฐ€๋กœ ํฌ๊ธฐ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ ์ ˆํ•œ ์ปจํ…์ธ  ๊ฐœ์ˆ˜์ธ itermsPerPage๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ Pagination ์ปดํฌ๋„ŒํŠธ์— ์ ์šฉ์‹œ์ผœ ์Šคํฌ๋ฆฐ ํฌ๊ธฐ์— ๋”ฐ๋ผ ์ ์ ˆํ•˜๊ฒŒ ํŽ˜์ด์ง€๋ฅผ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์–ด์š”.

const itemsPerPage = useResponsiveItemsPerPage(
	webItemPerPage,
	mobileItemPerPage,
);

const totalItems = contents.length;
const totalPages = Math.ceil(totalItems / itemsPerPage);

if (currentPage < 1 || currentPage > totalPages) {
	notFound();
}

๋˜ํ•œ, ์•ž์„œ ๋งํ–ˆ๋˜ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•˜๊ฒŒ ๋˜๋Š” ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์€ ์‚ฌ์šฉ์ž๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•  ๊ฒฝ์šฐ notFound()๋ฅผ ํ˜ธ์ถœํ•ด ์ ์–ด๋„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž˜๋ชป๋œ ์ ‘๊ทผ์ž„์„ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ตœ์ข…์ ์œผ๋กœ๋Š” ์›น โ†’ ๋ชจ๋ฐ”์ผ, ๋ชจ๋ฐ”์ผ โ†’ ์›น ์ „ํ™˜ ์‹œ ์ด๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ๋ฐ”๋€ ๋ทฐ์—์„œ ์œ„์น˜ํ•˜๋Š” ํŽ˜์ด์ง€๋ฅผ ์–ด๋ฆผ์žก์•„ ๊ณ„์‚ฐํ•ด ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์—ˆ์ง€๋งŒ, ํ•ด๋‹น ๋ถ€๋ถ„์€ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•„ํ„ฐ์™€ ์ •๋ ฌ ์ฒ˜๋ฆฌํ•˜๊ธฐ

Tomatoes Filter and Sort

๋จผ์ € ๊ณต๋ชจ์ „/๋Œ€์™ธํ™œ๋™์˜ ๋ฉ”์ธ ํŽ˜์ด์ง€๋ฅผ ์‚ดํŽด๋ณด๋ฉด, ์ด๋Ÿฐ ์‹์œผ๋กœ ํ•„ํ„ฐ๋ฅผ ํ† ๊ธ€ํ•˜๊ฑฐ๋‚˜, ์ •๋ ฌ ์˜ต์…˜์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Tomatoes Detail Page

๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ–ˆ๋˜ ํ•„ํ„ฐ๋Š” ์ด๋ ‡๊ฒŒ ์ƒ์„ธ ํŽ˜์ด์ง€์—์„œ๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋˜์–ด ์žˆ์–ด์•ผ ํ–ˆ์–ด์š”. ๋˜ํ•œ ์ด ํ•„ํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ ํ•„ํ„ฐ์— ๋งž๋Š” ์ปจํ…์ธ ๋งŒ์„ ๋ถˆ๋Ÿฌ์˜ค๋„๋ก ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ๋ฐฉ๋ฒ•์œผ๋กœ ์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€, ์ฟผ๋ฆฌ ์ŠคํŠธ๋ง์ด ๋– ์˜ฌ๋ž์Šต๋‹ˆ๋‹ค.

const updateURL = (newTab: string, newFilters: string[], newSort: string) => {
	const params = new URLSearchParams();

	if (newTab) params.set('tab', newTab);
	if (newFilters.length > 0) params.set('filters', newFilters.join(','));
	if (newSort) params.set('sort', newSort);

	router.push(`${pathname}?${params.toString()}`);
};

ํ•„ํ„ฐ๋ฅผ ํ† ๊ธ€ํ•  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” updateURL์€ ์„ ํƒ๋œ ํ•„ํ„ฐ์™€ ์ •๋ ฌ ์˜ต์…˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ URL์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. Next.js์˜ router.push ๋•๋ถ„์—, ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•˜์ง€ ์•Š๊ณ ๋„ URL์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์—ˆ์–ด์š”. ์ด์ œ ํŽ˜์ด์ง€์—์„œ URL์„ ๊ธฐ๋ฐ˜์œผ๋กœ Supabase์— ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ธ ๋’ค ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ–ˆ๋Š”๋ฐ, ์ด๋Š” searchParams๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ํŽ˜์ด์ง€์—์„œ searchParams๋ฅผ ๋ฐ›์•„์˜ค๊ณ , ํ•„ํ„ฐ์™€ ์ •๋ ฌ ์˜ต์…˜์„ ์ถ”์ถœํ•ด ๋ฐ์ดํ„ฐ ํŽ˜์นญ ํ•จ์ˆ˜์— ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

export default async function Page({ searchParams }: PageProps) {
	const filters = searchParams.filters?.split(',').filter(Boolean) || [];
	const sort = searchParams.sort || '๊ด€๋ จ๋„์ˆœ';

	const { data: activitiesContests, error } =
		await fetchActivityContestAbstractWith({
			filters,
			sort,
			mainCategory: '๋Œ€์™ธํ™œ๋™',
		});

	if (error) {
		// ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋กœ์ง
	}

	return <Activity activitiesContests={activitiesContests || []} />;
}

์•„์‰ฌ์› ๋˜ ๋ถ€๋ถ„๋“ค

ํ† ๋งˆํ† ๋“ค์€ ๊ทธ๋ ‡๊ฒŒ ๋งˆ๋ฌด๋ฆฌ๋์ง€๋งŒ, ์•„์‰ฌ์šด ๋ถ€๋ถ„๋“ค์ด ๋‚จ์•„์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋ถ€์‹คํ•œ ๋””์ž์ธ

๊ธฐ์—…์œผ๋กœ๋ถ€ํ„ฐ ๋””์ž์ธ์„ ์ œ๊ณต๋ฐ›์•˜์„ ๋•Œ, ๋””์ž์ธ ์‹œ์Šคํ…œ์ด ์ค€๋น„๋˜์–ด์žˆ๋‹ค๋Š” ์ดˆ๊ธฐ ํ”„๋กœ์ ํŠธ ์„ค๋ช…ํšŒ์˜ ๋ง๊ณผ๋Š” ๋‹ฌ๋ฆฌ ํฐํŠธ์™€ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ ๋ช‡ ๊ฐœ ์ •๋„๊ฐ€ ๋์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ์™€์ด์–ดํ”„๋ ˆ์ž„๋„ ์•„์˜ˆ ์ œ๊ณต๋˜์ง€ ์•Š์€ ๋ถ€๋ถ„๋“ค์ด ๋งŽ์•˜๊ณ (๊ฐœ๋ฐœ์ž์˜ ์ƒ์ƒ๋ ฅ์„ ๋ฏฟ๊ณ  ์žˆ์—ˆ๋Š”์ง€), ๋””์ž์ธ์— ์ผ๊ด€์ ์ธ ๋ถ€๋ถ„์ด ์ ์—ˆ์–ด์š”.

์—†๋Š” ๊ธฐ๋Šฅ๋ช…์„ธ์™€ ๋ฐ์ดํ„ฐ

๊ธฐ๋Šฅ๋ช…์„ธ๋„ ์•„์˜ˆ ์ œ๊ณต๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ฃผ์–ด์ง„ ์™€์ด์–ดํ”„๋ ˆ์ž„์„ ๋ณด๊ณ  ์†Œ์œ„ ๋งํ•˜๋Š” '์•Œ์ž˜๋”ฑ๊น”์„ผ' ์„ ๋ฐœํœ˜ํ•ด์„œ ๋งŒ๋“ค์ˆ˜๋„ ์žˆ์—ˆ๊ฒ ์ง€๋งŒ, ์ œ๊ฐ€ ์ง€์›ํ•œ ๊ณผ์ •์€ โ€˜๊ต์œก ํ”„๋กœ๊ทธ๋žจโ€™ ๊ณผ์ •์ด์—ˆ๊ณ , ๊ทธ๋ž˜์„œ ์ตœ์†Œํ•œ์˜ ์œตํ†ต์„ฑ์„ ๊ธฐ๋Œ€ํ–ˆ์–ด์š”. ๋ฐ์ดํ„ฐ๋„ ์ „ํ˜€ ์ œ๊ณต๋˜์ง€ ์•Š์•„ ์ง์ ‘ ํฌ๋กค๋ง์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋”์šฑ์ด ๊ฐ™์€ ๊ธฐ์—…์˜ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—๋Š” ์ œ๊ณต๋œ ๋””์ž์ธ ์‹œ์Šคํ…œ๊ณผ ์œ ์ € ํ”Œ๋กœ์šฐ ๋“ฑ์ด ์ €ํฌ ํ”„๋กœ์ ํŠธ์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š์•„์„œ, ๊ทธ ๋ถ€์žฌ๊ฐ€ ๋”์šฑ ํฌ๊ฒŒ ๋А๊ปด์กŒ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์›ํ™œํ•˜์ง€ ๋ชปํ–ˆ๋˜ ์†Œํ†ต ํ™˜๊ฒฝ

๊ธฐ์—…๊ณผ์˜ ์†Œํ†ต๋„ ๊ทธ๋ ‡๊ฒŒ ์›ํ• ํ•˜์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ฐ ํŒ€๋ณ„ ๋ฉ˜ํ† ๋Š” ๋’ค๋Šฆ๊ฒŒ ๋ฐฐ์ •๋๊ณ , ํ”ผ๋“œ๋ฐฑ๋„ ๋น ๋ฅด๊ฒŒ ๋ฐ›์•„๋ณผ ์ˆ˜ ์—†์—ˆ์–ด์š”. ๋ฌผ๋ก  ์—ฐ๋ฝ์„ ํ•˜์ž๋งˆ์ž ๋ฐ”๋กœ ๋‹ต๋ณ€์„ ์ค€๋‹ค๊ฑฐ๋‚˜, ๊ผญ๋‘์ƒˆ๋ฒฝ๋ถ€ํ„ฐ ๋‹ต๋ณ€์„ ๋ฐ”๋ž๋˜ ๊ฒƒ์€ ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ†ต์ƒ ๊ฑธ๋ฆฌ๋Š” ํ”ผ๋“œ๋ฐฑ ์‹œ๊ฐ„๋ณด๋‹ค๋„ ์กฐ๊ธˆ์€ ๋” ๊ธธ์—ˆ๋˜ ๊ฒƒ ๊ฐ™์•„์š”. ๋””์ž์ธ๊ณผ ๊ด€๋ จํ•ด์„œ๋„, ๋””์ž์ด๋„ˆ์™€ ์ง์ ‘์ ์ธ ์†Œํ†ต์„ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค๋ฉด ํผ๋ธ”๋ฆฌ์‹ฑ ๊ณผ์ •์ด ๋” ์›ํ™œํ–ˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์™„๋ฒฝํ•œ ์ƒํ™ฉ์€ ์—†๋‹ค

๊ทธ๋ ‡๋‹ค๊ณ  ์ผ๋ฐฉ์ ์œผ๋กœ ํ•œ์ชฝ ํƒ“๋งŒ ํ•  ์ˆ˜๋Š” ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์‹ค๋ฌด์—์„œ๋Š” ์ด๋Ÿฐ ๊ฒฝ์šฐ๊ฐ€ ๋น„์ผ๋น„์žฌํ•˜๋‹ค๊ณ ๋“ค ํ•˜๊ธฐ๋„ ํ•˜๊ณ (๋†€๋ž๊ฒŒ๋„ ์ด๋ณด๋‹ค ๋”ํ•œ ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค๊ณ ๋„ ํ•˜๊ณ ์š”), ์ €ํฌ ํŒ€๋„ ์–ด์จŒ๋“  ์ฃผ์–ด์ง„ ์‹œ๊ฐ„ ์•ˆ์— ํ”„๋กœ์ ํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ๋“  ์™„์„ฑํ•ด ๊ฒฐ๊ณผ๋ฌผ์„ ๊ตฌํ˜„ํ•ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐœ๋ฐœ ๋‹จ๊ณ„์—์„œ ์•„์‰ฌ์šด ๋ถ€๋ถ„๋“ค๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ์ƒํ™ฉ์—์„œ๋„ ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์ฒ˜ํ•˜๋Š” ๊ฐœ๋ฐœ์„ ์œ„ํ•ด์„œ, ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐ์— ์‹œ๊ฐ„์„ ์ข€ ๋” ๋“ค์—ฌ ๋ณด๋‹ค ์ฒด๊ณ„์ ์ธ ๊ณ„ํš๊ณผ ์„ค๊ณ„๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๋ฉด ํ”„๋กœ์ ํŠธ ์ค‘๊ฐ„์— ๊ณ ํ†ต๋ฐ›๋Š” ์ผ์ด ์—†์—ˆ์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ผ๋‹จ ์–ด๋–ป๊ฒŒ๋“  ๋งŒ๋“ค๊ณ  ๋ณด์ž๋Š” ๋งˆ์Œ์— ์ œ๋Œ€๋กœ ์ค€๋น„๋ฅผ ํ•˜์ง€ ๋ชปํ•œ ์ฑ„ ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ–ˆ๊ณ , ๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ ๊ณ„์†ํ•ด์„œ ์˜๊ฒฌ์ด ๋ฐ”๋€Œ๋Š” ๋ฐ”๋žŒ์— ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋‚˜ ํŽ˜์ด์ง€๋ฅผ ๋ช‡๋ฒˆ์ด๊ณ  ๋‹ค์‹œ ์ˆ˜์ •ํ•ด์•ผ ํ–ˆ๋˜ ์ˆœ๊ฐ„๋“ค์ด ์žˆ์—ˆ์–ด์š”. ์ตœ์†Œํ•œ ๊ธฐ๋Šฅ ๋ช…์„ธ๋ผ๋„ ๋งŒ๋“ค๊ณ  ์‹œ์ž‘ํ–ˆ์–ด์•ผ ํ–ˆ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋จธ๋ฆฌ๋ฅผ ์Šค์ณค์Šต๋‹ˆ๋‹ค.

์ œ๋Œ€๋กœ ํ™œ์šฉํ•˜์ง€ ๋ชปํ–ˆ๋˜ ๊ธฐ์ˆ ์Šคํƒ

๊ทธ๋ž˜์„œ ์ด๋Ÿฐ์ €๋Ÿฐ ์ƒํ™ฉ์— ์ž„๊ธฐ์‘๋ณ€์‹์œผ๋กœ ๋Œ€์ฒ˜ํ•˜๋‹ค ๋ณด๋‹ˆ, ์ผ์ •์— ์ฐจ์งˆ์ด ์ƒ๊ธฐ๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ํ˜ธ๊ธฐ๋กญ๊ฒŒ ์‹œ์ž‘ํ–ˆ๋˜ ํ”„๋กœ์ ํŠธ๋Š” ์–ด๋А์ƒˆ ์ด๊ฒƒ๋งŒ์ด๋ผ๋„ ์ œ๋Œ€๋กœ ๊ตฌํ˜„ํ•ด๋ณด์ž๋Š” ์ƒํƒœ๋กœ ์ง„ํ–‰๋๊ณ , ๊ฒฐ๊ตญ ํ”„๋กœ์ ํŠธ์—์„œ 100% ํ™œ์šฉํ•ด ๋ณด๊ณ  ์‹ถ์—ˆ๋˜ ๊ฒƒ๋“ค์„ ํ™œ์šฉํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์ œ๋Œ€๋กœ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•œ Next.js์˜ ์žฅ์ 
  • ๋‹ค์†Œ ์ง€์ €๋ถ„ํ•œ ์ฝ”๋“œ
  • ์ž„์‹œ๋ฐฉํŽธ์œผ๋กœ ๋งŒ๋“ค์—ˆ๋˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์™€ ์ฟผ๋ฆฌ
  • ์ ‘๊ทผ์„ฑ
  • ์„ฑ๋Šฅ ์ตœ์ ํ™”

ํ† ๋งˆํ† ๋“ค ํ”„๋กœ์ ํŠธ์™€ ์—ฐ๊ธˆ๋ณต๊ถŒ์˜ ๊ณตํ†ต์ ์ด๋ผ๋ฉด โ€˜๋ญ”๊ฐ€ ๊ณ„์† ๋‚˜์˜จ๋‹คโ€™๋ผ๋Š” ๊ฒ๋‹ˆ๋‹ค.

๋‚˜์˜ค๋ฉด์„œ: ๊ทธ๋ ‡๊ฒŒ ๋˜ ์„ฑ์žฅํ•œ๋‹ค

๊ทธ๋ž˜๋„ 3์ฃผ๋ผ๋Š” ๊ธฐ๊ฐ„๋™์•ˆ ์•„๋ฌด๊ฒƒ๋„ ์–ป์–ด๊ฐ€์ง€ ๋ชปํ•œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์šฐ์„  Next.js๋ฅผ ํ™œ์šฉํ•ด ๋ณธ ๋‘ ๋ฒˆ์งธ ํ”„๋กœ์ ํŠธ์ด๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ธ”๋กœ๊ทธ๋ฅผ ๋งŒ๋“ค๋ฉด์„œ ์ ์šฉํ•ด ๋ณธ ๊ฒƒ๊ณผ, ํ† ๋งˆํ† ๋“ค์„ ๋งŒ๋“ค๋ฉด์„œ ์ ์šฉํ•ด๋ณธ ๋ถ€๋ถ„๋“ค์ด ์„œ๋กœ ๋‹ฌ๋ž๊ธฐ์— ์ƒํ˜ธ๋ณด์™„์ ์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š”. ๋˜ํ•œ ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์— ๋Œ€์ฒ˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ข‹์€ ์ดˆ์„์„ ์Œ“์•„์•ผ ํ•˜๋Š” ์ด์œ ๋ฅผ ๋ชธ์†Œ ๋А๊ผˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํŽ˜์ด์ง€๋„ค์ด์…˜๊ณผ ๊ฐ™์ด ๋” ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฒฝํ—˜๋„ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์žˆ์—ˆ๊ณ ์š”. ์ฒ˜์Œ ์‚ฌ์šฉํ•ด๋ณด๋Š” ํด๋” ๊ตฌ์กฐ๋ฅผ ์ ์šฉํ•ด ๋ณธ ๊ฒƒ๋„ ์žˆ๊ณ , ๋Œ์•„๋ณด๋ฉด ๋ฐฐ์› ๋˜ ์ ๋“ค์ด ๊ฝค ๋งŽ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋ฌด์—‡๋ณด๋‹ค๋„, ๋‹ค์‹œ ํ•œ๋ฒˆ ๋‚ด๊ฐ€ ๋ฌด์—‡์„ ๋ชจ๋ฅด๋Š”์ง€ ์•Œ๊ฒŒ ๋๋‹ค๋Š” ์ ์ด ๊ฐ€์žฅ ํฐ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์Šค์Šค๋กœ ์–ด๋–ค ๋ถ€๋ถ„์ด ๋ถ€์กฑํ•˜๊ณ , ์–ด๋–ค ๋ถ€๋ถ„์„ ์–ด๋–ป๊ฒŒ ์ฑ„์›Œ๋‚˜๊ฐ€์•ผ ํ•˜๋Š”์ง€๋ฅผ ์กฐ๊ธˆ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋˜ 3์ฃผ์˜€์–ด์š”. ํ”„๋กœ๊ทธ๋žจ ๊ธฐ๊ฐ„์€ ๋๋‚ฌ์ง€๋งŒ ์•„์ง ํ† ๋งˆํ† ๋“ค์€ ๋๋‚˜์ง€ ์•Š์•˜๊ณ , ๋‹ค์Œ์ฃผ๋ถ€ํ„ฐ ๋˜ ํŒ€์›๋“ค๊ณผ ๋ฆฌํŒฉํ† ๋ง ๊ณ„ํš์— ๋Œ€ํ•ด์„œ ์ด์•ผ๊ธฐํ•ด ๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

profile
์•ž์œผ๋กœ ๊พธ์ค€ํžˆ ๋‚˜์•„๊ฐ€๊ธฐ

0๊ฐœ์˜ ๋Œ“๊ธ€