๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • What would life be If we had no courage to attemp anything?
๐“๐จ๐๐š๐ฒ ๐ˆ ๐‹๐ž๐š๐ซ๐ง

์‚ฌ๋‚ด ๋ณด์•ˆ ๋ฆฌ์†Œ์Šค ํ†ตํ•ฉ ํ”Œ๋žซํผ ๊ตฌ์ถ•๊ธฐ : 2. ๊ณ„์ธตํ˜• ๋ ˆํผ๋Ÿฐ์Šค ํ•„ํ„ฐ UI ๊ฐœ์„ ๊ธฐ

by DevIseo 2025. 6. 13.

๐Ÿงฑ ๋ณต์žกํ•œ ํŠธ๋ฆฌ๊ตฌ์กฐ ํ•„ํ„ฐ, ๊ณ„์ธตํ˜• ํ•„ํ„ฐ๋กœ ๊ฐœ์„ ํ•˜๊ธฐ


โŒ ๊ธฐ์กด UI์˜ ๋ฌธ์ œ์ 

๊ธฐ์กด์˜ ์ฒด์ปค ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํŠธ๋ฆฌ ๊ตฌ์กฐ ๊ธฐ๋ฐ˜์˜ ๋ ˆํผ๋Ÿฐ์Šค ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

  • ํŠธ๋ฆฌ ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ๋œ ํ•„ํ„ฐ๋Š” ์‹œ๊ฐ์ ์œผ๋กœ ๋ณต์žกํ•˜๋ฉฐ, ์ค‘์ฒฉ ๋ ˆ๋ฒจ์ด ๋งŽ์•„์ง€๋ฉด ๊ฐ€๋…์„ฑ๊ณผ ์‚ฌ์šฉ์„ฑ์ด ๊ธ‰๊ฒฉํžˆ ๋–จ์–ด์ง€๋Š” ๊ตฌ์กฐ
  • ๊ฐ ์ฑ•ํ„ฐ/๋ฃฐ ๋‹จ์œ„๋กœ ์„ ํƒํ•  ์ˆ˜๋Š” ์žˆ์—ˆ์ง€๋งŒ, ์ „์ฒด ์„ ํƒ/ํ•ด์ œ ๋กœ์ง์ด ์ง๊ด€์ ์ด์ง€ ์•Š์•˜๊ณ , ๋งˆ์šฐ์Šค ์—†์ด ์กฐ์ž‘ํ•˜๊ธฐ์—๋„ ๋ถˆํŽธ
  • ์Šคํฌ๋กค์ด ๋งŽ๊ณ  ๊ตฌ์กฐ๊ฐ€ ํ‰ํ‰ํ•˜์ง€ ์•Š์•„, ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋Š” ์–ด๋–ค ๊ธฐ์ค€์œผ๋กœ ์„ ํƒํ• ์ง€ ํŒŒ์•…์ด ์–ด๋ ค์›Œ ๋ณด์ž„
  • ์ฒซ๋ฒˆ์งธ ์„ ํƒ ํ•ญ๋ชฉ์˜ ๊ฒฝ์šฐ ํ•„ํ„ฐ ๋ ˆ์ด์•„์›ƒ์„ ๋ฒ—์–ด๋‚œ UI๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Œ

 

โœ… ๊ฐœ์„  ๋ฐฉํ–ฅ: 3๋‹จ๊ณ„ ๊ณ„์ธตํ˜• ํ•„ํ„ฐ UI

๊ธฐ์กด์— ํ•œ๋ˆˆ์— ๋ณด๊ธฐ ์–ด๋ ค์šด UI๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด 3๋‹จ๊ณ„ ๊ณ„์ธต ๊ตฌ์กฐ์— ๊ธฐ๋ฐ˜ํ•œ ์ปค์Šคํ…€ ํ•„ํ„ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„ํ–ˆ๋‹ค.

 
 
๐Ÿ“Œ ๊ตฌ์กฐ ๊ฐœ์„ 

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

๐Ÿ“Œ ๊ธฐ๋Šฅ ๊ฐœ์„ 

  • ์„ ํƒ๋œ ํ•ญ๋ชฉ์€ ๋‚ด๋ถ€ ์ƒํƒœ์— ๋”ฐ๋ผ ์ž๋™ ๋™๊ธฐํ™”๋˜๋ฉฐ, ์ „์ฒด ์„ ํƒ/ํ•ด์ œ ๊ธฐ๋Šฅ๋„ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌํ˜„
  • shadcn/ui์™€ Tailwind CSS ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋˜์–ด, ํ‚ค๋ณด๋“œ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ง€์›๊ณผ ๋ฐ˜์‘ํ˜• ๋””์ž์ธ๋„ ๊ณ ๋ ค๋จ
  • ์ด๋ฆ„์ด ๊ธธ์–ด ์ž˜๋ฆฌ๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ฆฌ์‚ฌ์ด์ฆˆ ๊ฐ€๋Šฅํ•˜๊ฒŒ shadcnUI์˜ resizable ์ปดํฌ๋„ŒํŠธ ํ™œ์šฉ
  • ํ•„ํ„ฐ ์ดˆ๊ธฐํ™”, ์ ์šฉ, ์„ค์ • ๊ฐ„ UX ํ๋ฆ„๋„ ์ง๊ด€์ ์œผ๋กœ ๊ฐœ์„ ๋จ

 

๐Ÿ” ๊ฐœ๋ฐœ : ๋ฐ์ดํ„ฐ ๋ฐ ์ƒํƒœ ๊ด€๋ฆฌ ๊ณ ๋ฏผ

๋ ˆํผ๋Ÿฐ์Šค ๋ฐ์ดํ„ฐ๋Š” ๋ฐฑ์—”๋“œ์—์„œ 3๋‹จ๊ณ„ ์ค‘์ฒฉ ๊ตฌ์กฐ๋กœ ์ œ๊ณต๋˜๋ฉฐ, ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์„ค๊ณ„ํ–ˆ๋‹ค.

interface CascadingFilterProps {
  data: ReferenceItem[];
  selected: {
    firstSelectedId: string;
    secondSelectedIds: string[];
    thirdSelectedValues: Record<string, string[]>;
  };
  onChange: (newSelected) => void;
  onReset: () => void;
}
  • firstSelectedId: ์„ ํƒ๋œ ์ตœ์ƒ์œ„ ๊ทธ๋ฃน
  • secondSelectedIds: ์„ ํƒ๋œ ์ค‘๊ฐ„ ๊ทธ๋ฃน๋“ค
  • thirdSelectedValues: ๊ฐ ์ค‘๊ฐ„ ๊ทธ๋ฃน๋ณ„ ์„ ํƒ๋œ ํ•˜์œ„ ํ•ญ๋ชฉ๋“ค (Key-Value ํ˜•ํƒœ)

์ด ๊ตฌ์กฐ๋Š” ์ค‘์ฒฉ ํ•„ํ„ฐ ํ•ญ๋ชฉ ๊ฐ„์˜ ์˜์กด์„ฑ์„ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์‚ฌ์šฉ์ž ์กฐ์ž‘์— ๋”ฐ๋ผ ์ž๋™ ์ƒํƒœ ๋™๊ธฐํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค๊ณ„ํ–ˆ๋‹ค.

๐ŸŽฏ ๊ฐœ์„  ํšจ๊ณผ

  • ์‹œ๊ฐ์  ๊ณ„์ธต์ด ๋ช…ํ™•ํ•ด์ ธ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ํ•ญ๋ชฉ์„ ๋” ๋น ๋ฅด๊ณ  ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์Œ
  • ์ด์ „๋ณด๋‹ค ๋ณต์žกํ•œ ๋ ˆํผ๋Ÿฐ์Šค ๊ตฌ์กฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํƒ์ƒ‰ ๋ฐ ์„ ํƒ ๊ฐ€๋Šฅ

๐Ÿ”ง ํ–ฅํ›„ ๊ฐœ์„  ์˜ˆ์ •

  • ๋ ˆํผ๋Ÿฐ์Šค ํ•„ํ„ฐ ํ•ญ๋ชฉ์ด ๋งŽ์•„์งˆ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ Œ๋”๋ง ์ง€์—ฐ, ์Šคํฌ๋กค ๋ฒ„๋ฒ…์ž„ ๋“ฑ์˜ ์„ฑ๋Šฅ ์ด์Šˆ๋ฅผ ๊ณ ๋ คํ•ด, ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ๋Œ€์‘์„ ์œ„ํ•œ ๊ฐ€์ƒํ™”(virtual scroll) ์ ์šฉ
  • ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „์ฒด ๊ฐฏ์ˆ˜ ๋ฐ ์„ ํƒ ๋œ ๊ฐฏ์ˆ˜ ์ œ๊ณต
  • ํ‚ค๋ณด๋“œ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ง€์› ๊ฐ•ํ™”

๋Œ“๊ธ€