Project๐Ÿ› ๏ธโš™๏ธ

twMerge ์ปค์Šคํ…€ ํด๋ž˜์Šค ์Šคํƒ€์ผ ์ถฉ๋Œ ํ•ด๊ฒฐ

Gaeun Lee 2025. 6. 17. 02:26

์•ฝ์† ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Tailwind CSS๋ฅผ ํ™œ์šฉํ•ด ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ๋ฅผ ์Šคํƒ€์ผ๋งํ•˜๋ฉฐ, twMerge, clsx, ๊ทธ๋ฆฌ๊ณ  cva๋ฅผ ์กฐํ•ฉํ•˜์—ฌ variant ๊ธฐ๋ฐ˜ ์Šคํƒ€์ผ๋ง๊ณผ ํด๋ž˜์Šค ์ค‘๋ณต ์ œ๊ฑฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค. ์ด ์ค‘ twMerge๋Š” Tailwind ํด๋ž˜์Šค ๊ฐ„ ์ถฉ๋Œ์„ ๊ฐ์ง€ํ•˜๊ณ , ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์ •์˜๋œ ํด๋ž˜์Šค๋ฅผ ๋ณ‘ํ•ฉํ•ด์ฃผ๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ๋กœ, ๋‹คํฌ๋ชจ๋“œ ๋ฐ ๋ฐ˜์‘ํ˜• ํด๋ž˜์Šค ๋“ฑ ๋‹ค์–‘ํ•œ ๋ณ€ํ˜•์ด ๋งŽ์€ Tailwind ํ™˜๊ฒฝ์—์„œ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉ๋œ๋‹ค.

 

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋””์ž์ธ ์‹œ์Šคํ…œ์— ๊ธฐ๋ฐ˜ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด text-head1, text-head2 ๋“ฑ์˜ ์ปค์Šคํ…€ ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ ์œ ํ‹ธ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

  --text-head1--line-height: 52px;
  --text-head1--letter-spacing: -0.6px;
  --text-head1--font-weight: 800;
  --text-head2: 36px;
  --text-head2--line-height: 46px;
  --text-head2--letter-spacing: -0.6px;
  --text-head2--font-weight: 800;
  --text-head3: 36px;
  --text-head3--line-height: 46px;
  --text-head3--letter-spacing: -0.6px;
  --text-head3--font-weight: 800;

 

 

๊ทธ๋Ÿฌ๋‚˜ ์ด์ฒ˜๋Ÿผ text- ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค๋“ค์€ Tailwind์˜ ๊ธฐ๋ณธ ํ…์ŠคํŠธ ์ƒ‰์ƒ ํด๋ž˜์Šค(text-white, text-gray-700 ๋“ฑ)์™€ ๋™์ผํ•œ ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, twMerge๋Š” ์ด๋ฅผ ๋™์ผํ•œ class group์œผ๋กœ ์ธ์‹ํ•œ๋‹ค. ์ด๋กœ ์ธํ•ด ๋ณ‘ํ•ฉ ์‹œ ๋งˆ์ง€๋ง‰์œผ๋กœ ์ž‘์„ฑ๋œ ํด๋ž˜์Šค๋งŒ ๋‚จ๊ธฐ๊ณ , ๋‚˜๋จธ์ง€ ํด๋ž˜์Šค๋Š” ์ œ๊ฑฐ๋˜๋Š” ์ถฉ๋Œ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•œ๋‹ค.

<p className="text-white text-head2">hello world</p> // text-head2๋กœ ๋ณ‘ํ•ฉ

 

 

์ด ๋•Œ twMerge์—์„œ ์ œ๊ณตํ•˜๋Š” extendTailwindMerge API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด twMerge์˜ ๋ณ‘ํ•ฉ ๊ทœ์น™ ํ™•์žฅ์„ ํ†ตํ•˜์—ฌ ์ปค์Šคํ…€ ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ ํด๋ž˜์Šค์™€ ๊ธฐ๋ณธ ํ…์ŠคํŠธ ์ปฌ๋Ÿฌ ํด๋ž˜์Šค๊ฐ€ ์•ˆ์ •์ ์œผ๋กœ ๊ณต์กดํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์ด ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปค์Šคํ…€ text-* ํด๋ž˜์Šค๋“ค์„ ๋ช…์‹œ์ ์œผ๋กœ font-size class group์— ๋“ฑ๋กํ•˜๋ฉด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

import { ClassValue, clsx } from 'clsx'
import { extendTailwindMerge } from 'tailwind-merge'

const customTwMerge = extendTailwindMerge({
  extend: {
    classGroups: {
      'font-size': [
        'text-head1',
        'text-head2',
        'text-head3',
        'text-head4',
        'text-head5',
        'text-head6',
        'text-subhead1',
        'text-subhead2',
        'text-subhead3',
        'text-body1',
        'text-body2',
        'text-caption1',
      ],
    },
  },
})

export function cn(...inputs: ClassValue[]) {
  return customTwMerge(clsx(inputs))
}