ํฌ๋ก์ค ํ๋ซํผ ๋์์ธ ์์คํ , 1.5๋ ์ ๊ธฐ๋ก (1,2)
ํฌ๋ก์ค ํ๋ซํผ ๋์์ธ ์์คํ , 1.5๋ ์ ๊ธฐ๋ก (1,2) ๊ด๋ จ
*FEConf2023์์ ๋ฐํํ <ํฌ๋ก์ค ํ๋ซํผ ๋์์ธ ์์คํ , 1.5๋ ์ ๊ธฐ๋ก>๋ฅผ ์ ๋ฆฌํ ๊ธ์ ๋๋ค. ๋ฐํ ๋ด์ฉ์ 2ํ๋ก ๋๋์ด ๋ฐํํฉ๋๋ค. 1ํ์์๋ ๋์์ธ ์์คํ ๊ณผ ๋์์ธ ํ ํฐ์ ๋ํด ์์๋ด ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์ฑ์์๋ฅผ ํ์ ํด ๋์์ด๋์ ๊ฐ๋ฐ์์ ์์ฌ์ํต ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด ๋ด ๋๋ค. 2ํ์์๋ 1ํ์ ๋ด์ฉ์ ๋ฐํ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๊ณ API๋ฅผ ์ค๊ณํด ๋ด ๋๋ค. ๋ณธ๋ฌธ์ ์ฝ์ ๋ ์ด๋ฏธ์ง์ ์ถ์ฒ๋ ๋ชจ๋ ์ด ์ฝํ ์ธ ์ ๊ฐ์ ์ ๋ชฉ์ ๋ฐํ ์๋ฃ๋ก, ๋ฐ๋ก ์ถ์ฒ๋ฅผ ํ๊ธฐํ์ง ์์์ต๋๋ค. ๋ฐํ ์๋ฃ๋ FEConf2023 ํํ์ด์ง์์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.
FEConf2023์์ ๋ฐํ๋ 'ํฌ๋ก์ค ํ๋ซํผ ๋์์ธ ์์คํ , 1.5๋ ์ ๊ธฐ๋ก'/ํํ์ ๋น๊ทผ ํ๋ก ํธ์๋ ์์ง๋์ด
์๋ ํ์ธ์. ์ ๋ ๋น๊ทผ์์ ๋์์ธ ์์คํ ์ ๋ง๋ค๊ณ ์ด์ํ๊ณ ์๋ ํํ์์ ๋๋ค. ์ด๋ฒ ๊ธ์์๋ ์ ๊ฐ 1๋ ๋ฐ ๋์ ๋์์ธ ์์คํ ์ ๋ง๋ค๋ฉฐ ์๋ํ๋ ๋ค์ํ ์ ๊ทผ ๋ฐฉ๋ฒ๊ณผ ๊ทธ ๊ณผ์ ์์ ํจ์ ์ ๋น ์ง ๊ฒฝํ, ๊ทธ๋ฆฌ๊ณ ์ด ๊ฒฝํ์ ํตํด ๋ฐฐ์ด ๊ฒ ๋ค์ ๊ณต์ ํ๊ณ ์ ํฉ๋๋ค.
1. ๋์์ธ ์์คํ
๋์์ธ ์์คํ ์ ๋ชฉํ
๋์์ธ ์์คํ ์ ๋ง๋ค๋ค ๋ณด๋ฉด '๋์์ธ ์์คํ '์ด๋ผ๋ ๋จ์ด๊ฐ ๊ต์ฅํ ๋์ ์คํํธ๋ผ์ ๊ฐ์ง๊ณ ์๊ณ ์ด๋ก ์ธํด ํ์๊ฐ ์ํต์ ์ค๋ฅ๋ ํ์ ๋ฐฉํฅ์ฑ์ด ํํธ๋ฌ์ง๋ ๊ฒฝํ์ ํ๊ฒ ๋ฉ๋๋ค. ์ด๋ฒ ์ฅ์์๋ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋์์ธ ์์คํ ์ ๋ฐฉํฅ์ฑ์ ๋ช ํํ๊ฒ ์ค์ ํ๊ณ ๋์์ธ ์์คํ ์ ์ค๊ณ ๋ชฉํ๋ฅผ ์ ํํ๊ฒ ํ์ ํ๋ ๋ฐฉ๋ฒ, ๋ชฉํ๋ฅผ ์ค์ ํ ๋ ๋น ์ง ์ ์๋ ํจ์ ์ ๋๋นํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
์๋ ๊ทธ๋ฆผ์ ์คํ์์ค ๋์์ธ ์์คํ ์ผ๋ก ์ ๋ช ํ ์ฐจํฌ๋ผ์ ์ด๋๋น์ ์คํํธ๋ผ ๋์์ธ ์์คํ ์ ๋๋ค. ๋์ผํ ๊ธฐ๋ฅ์ ํ๋ ๋ ์ธ์ง ์ฌ๋ผ์ด๋๋ฅผ ๊ตฌํํ๋๋ฐ๋ ์ฐจ์ด๊ฐ ๋ง์ด ๋ฉ๋๋ค. ์ฐจํฌ๋ผ๋ ๋ชจ๋ ์๋ธ ์ปดํฌ๋ํธ๋ฅผ ๋ช ์ํด์ผ ํ๋ ๋ฐ๋ฉด์ ์คํํธ๋ผ์ ๋ ์ธ์ง ์ฌ๋ผ์ด๋ ํ ์ค๋ง ๋ช ์ํ๋ฉด ๋ฉ๋๋ค.
์ ์ด๋ฐ ์ฐจ์ด๊ฐ ์๊ฒผ์๊น์? ์ ์๊ฐ์๋ ๋ ๋์์ธ ์์คํ ์ด ์ถ๊ตฌํ๋ ๊ฐ์น๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฐจํฌ๋ผ๋ '์คํ์์ค๋ฅผ ํ์ฉํ๋ ๊ฐ๋ฐ์๋ค์ด ์ ์ฐํ๊ฒ ์ฌ์ฉํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ'๋ผ๋ ๋ชฉ์ ์ผ๋ก ๋ง๋ค์ด์ก๊ณ , ์คํํธ๋ผ์ ์ด๋๋น ์ ํ๊ตฐ์ ์ฌ์ฉ๋ ๋ชฉ์ ์ผ๋ก ๋ง๋ค์ด์ก์ต๋๋ค. ์ฐจํฌ๋ผ๋ ์ ์ฐ์ฑ์ ๋ ์ค์ํ ๊ฐ์น๋ก ์๊ฐํ๊ณ , ์คํํธ๋ผ์ ์ผ๊ด์ฑ์ ๋ ์ค์ํ ๊ฐ์น๋ก ์๊ฐํ๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ์ฐจ์ด๊ฐ ๋ง๋ค์ด์ง ๊ฒ์ ๋๋ค.
์ด๋ฐ ์ด์ ๋ก ์ ๋ ๋ ๋์์ธ ์์คํ ์ ๋ค๋ฅธ ๊ด์ ์์ ๋ฐ๋ผ๋ณด๊ณ ์๊ณ , ์ฐจํฌ๋ผ์ ๊ฐ์ ๋์์ธ ์์คํ ์ '๋ฒ์ฉ ๋์์ธ ์์คํ '์ด๋ผ๊ณ ๋ถ๋ฅด๊ณ ์คํํธ๋ผ๊ณผ ๊ฐ์ ๋์์ธ ์์คํ ์ '์ ํ ์ธ์ด'๋ผ๊ณ ๋ถ๋ฅด๋ฉฐ ๊ตฌ๋ถํ๊ณ ์์ต๋๋ค. ์ด๋ฐ ์ ํ ์ธ์ด์๋ ์คํํธ๋ผ๋ฟ๋ง ์๋๋ผ Material, Carbon, Fluent ๋ฑ ๋ง์ ์ข ๋ฅ๊ฐ ์์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ์ ๋ง์ ํ์ฌ๊ฐ ๋ฒ์ฉ ๋์์ธ ์์คํ ์ ์ฌ์ฉํ์ฌ ๋์์ธ ์์คํ ์ ๊ตฌ์ถํ์ง ์๊ณ ๋์์ธ ์์คํ ์กฐ์ง์ ๋ฐ๋ก ๋๊ณ ์ ํ ์ธ์ด๋ฅผ ๋ง๋ค๊ฒ ๋ ๊น์?
๊ทธ ์ด์ ๋ UI์ ๋ธ๋๋ฉ, ์ฑ์ ํน์ฑ ๋ฑ ํ์ฌ์ ๊ณ ์ ํ ์์ฌ๊ฒฐ์ ์ด ๋ฐ์๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ ํ ์ธ์ด๋ ์ผ๋ฐ์ ์ธ ๋์์ธ ์์คํ ์ ๊ธฐ๋ฅ ์ธ์ '์์ฌ ๊ฒฐ์ ์ ์งํฉ์ ๊ด๋ฆฌ'ํ๋ค๋ ์๋ฏธ๊ฐ ์ถ๊ฐ์ ์ผ๋ก ํฌํจ๋ฉ๋๋ค. ๋ ๊ฐ์กฐํด์ ๋งํ๋ฉด ์ ํ ์ธ์ด์ ๋ณธ์ง์ ๋์์ธ ์์ฌ๊ฒฐ์ ์ ์งํฉ์ด๊ณ UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ทธ๊ฒ์ ๊ตฌํํ๋ ์๋จ์ผ ๋ฟ์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค.
ํ์ฌ์์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ๋ ๊ทธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ฌ๊ฒฐ์ ์ ๊ด๋ จ์ด ์๊ฑฐ๋ ์์ฌ๊ฒฐ์ ์ ๊ทธ๋๋ก ๋ฐ์ํ ์ ์๋ ๊ฒฝ์ฐ์ ๋๋ค. ๊ทธ๋ฌ๋ UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ฌ ๊ฒฐ์ ์ ๋ฐ์ํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง๊ณ ์ด๋ก ์ธํด ๋ง์ ํ์ฌ๋ค์ด ๋์์ธ ์์คํ ์กฐ์ง์ ๋๊ณ ์ ํ ์ธ์ด๋ฅผ ๋ง๋ค๊ฒ ๋ฉ๋๋ค.
ํจ์ : ๋์์ธ ์์คํ ์ ๋ชฉํ ์ค์
์ ๋ ๋์์ธ ์์คํ ์ ๊ตฌ์ถํ ๋ ์ฌ๋ฌ ํจ์ ์ ๋น ์ก์์ต๋๋ค. ๋จผ์ ๋ชฉํ๋ฅผ ๋ช ํํ๊ฒ ์ค์ ํ์ง ์์์ ์ฐธ๊ณ ํ ๋์์ ์ ๋ชป ํ๋จํ์ต๋๋ค. ๋น๊ทผ ์ฑ์ ํ์ํ ๋์์ธ ์์คํ ์ ์ ํ ์ธ์ด์ฌ์ผ ํ๊ณ ๋ชจ๋ฐ์ผ์ด ์ต์ฐ์ ์ด๋ฉฐ ์น, IOS, ์๋๋ก์ด๋ ๊ตฌํ์ด ๋ชจ๋ ํ์ํฉ๋๋ค. ์ ๋ ํ์ ๊ตฌ์ฑํ๋ ์ด๊ธฐ์ ๋ฐ์ํ ์น์ ๋์์ผ๋ก ํ๋ ๋์์ธ ์์คํ ์ ์ฐธ๊ณ ํ๊ณ , ์ด๋ ๋ฐ์ํ ์น์๋ ๋ง์ง๋ง ์ฐ๋ฆฌ ์ ํ์๋ ์๋ชป๋ ์ ๊ทผ์ ํ๊ฒ ํ ์์ธ์ด ๋์์ต๋๋ค.
๋ค๋ฅธ ํจ์ ์ ํ๋์ ๋์์ธ ์์คํ ์ผ๋ก ์ฌ๋ฌ ํ๊ฒฝ๊ณผ ์ ํ์ ์ปค๋ฒํ๋ ค๋ ์์ฌ์ด์์ต๋๋ค. ์๋น์ค๊ฐ ์ฑ์ฅํจ์ ๋ฐ๋ผ ๋ชจ๋ฐ์ผ ์ฑ๋ฟ๋ง ์๋๋ผ ์น์ฌ์ดํธ, ์ด๋๋ฏผ ๋ฑ ๋ ๋ง์ ์ ํ์ ์ง์ํ ํ์๊ฐ ์๊ฒผ๋๋ฐ, ๋ธ๋๋ฉ์ ๋ชจ๋ ์ ํ์ ๋์ฒด๋ก ๋น์ทํ๊ธฐ ๋๋ฌธ์, ์ ๋ง๋ ๋ฒ์ฉ ๋์์ธ ์์คํ ํ๋๋ก ๋ชจ๋ ์ ํ์ ์ปค๋ฒํ๊ณ ์ ํ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฐ ์๋๋ ๋ถ๊ฐ๋ฅํ๊ฑฐ๋ ์ ํ ์ธ์ด๋ฅผ ๋ง๋๋ ๊ฒ๋ณด๋ค ๋ ํฐ ๋น์ฉ์ด ๋๋ ์ํฉ์ ์๊ธฐ๊ฒ ํ์ต๋๋ค.
์ด ๊ฒฝํ์ ํตํด ์๋ฒฝํ ๋ฒ์ฉ ๋์์ธ ์์คํ ์ ๋ง๋๋ ๊ฒ๋ณด๋ค ์ด๋ค ์ ํ ์ธ์ด๋ฅผ ๋ง๋ค๋๋ผ๋ ๋ฐ๋ณต๋๋ ๋ฐฉ๋ฒ๋ก ์ด ์กด์ฌํ๊ณ ์ด๋ฅผ ํ์ฉํ๋ ๊ฒ์ด ๋ ์ค์ํ๋ค๋ ๊ฒ์ ์๊ฒ ๋์์ต๋๋ค. ๊ทธ์ค ๊ฐ์ฅ ์ค์ํ ๊ฒ์ '๋์์ธ ์์ฌ๊ฒฐ์ ์ ์งํฉ์ ์ ํ ๋์์ธ๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ์์ญ์ ํจ๊ณผ์ ์ผ๋ก ๋๊ธฐํํ๋ ์์คํ '์ ๋๋ค. ์ ๋ ์ด๋ฅผ ๋๋ด ์ผ์ '๋์์ธ ์์คํ -์์คํ '์ด๋ผ๊ณ ๋ถ๋ฅด๋๋ฐ์. ๋ค์ ์ฅ์์๋ ์ด๋ฌํ ๋์์ธ ์์ฌ ๊ฒฐ์ ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ๋๊ธฐํํ๊ธฐ ์ํ '๋์์ธ ํ ํฐ'์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
2. ๋์์ธ ํ ํฐ
์ด๋ฒ ์ฅ์์๋ ์๋ ๋ด์ฉ์ ๋ํด ์์๋ด ๋๋ค.
- ๋์์ธ ํ ํฐ์ด ๊ฐ์ง๋ ์๋ฏธ ํ์
- ๋์์ธ ํ ํฐ ํ์ฉ ์ฌ๋ก ์์๋ณด๊ธฐ
- ๋์์ธ ํ ํฐ ์ด์ฉ ์ ๋น ์ง ์ ์๋ ํจ์ ๋๋น
๋์์ธ ์์คํ
์ ๊ตฌ์ถํ๋ ๊ฒ์ ๊ฒฐ๊ตญ ๋์์ธ ๊ฒฐ์ ์ ์ฐ์์
๋๋ค. โ๋ฒํผ ์ปดํฌ๋ํธ์ ๋์ด๋ฅผ 40px๋ก ํ ๊ฒ์ด๋ค.โ,โ๋ธ๋๋ ์ปฌ๋ฌ๋ฅผ #ff6f0f
์์์ผ๋ก ํ ๊ฒ์ด๋ค.โ ๋ฑ์ ๋ชจ๋ ๊ฒ๋ค์ด ๋์์ธ ๊ฒฐ์ ์ ํด๋นํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋๋ถ๋ถ์ ์ ํ์ด ๊ทธ๋ ๋ฏ์ด ์์ฌ๊ฒฐ์ ์ ์๊ฐ์ ๋ฐ๋ผ ๋ณํ๊ธฐ ๋ง๋ จ์ ๋๋ค. ์ ํ์ด ์ฑ์ฅํจ์ ๋ฐ๋ผ ๋ ๋์ UI๊ฐ ๋ฌด์์ธ์ง ์๋ก ๋ฐฐ์ฐ๊ฒ ๋๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋ฌ๋ฉด ์ด๋ฐ ์์ฌ๊ฒฐ์ ์ ๋ณํ๋ฅผ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ชจ๋ ์ ํ์ ๋ฐ์ํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ผ๊น์?
๊ทธ๊ฒ์ ๋ฐ๋ก ์์ฌ๊ฒฐ์ ์ ๊ธฐ๊ณ๊ฐ ์ฝ์ ์ ์๋ ๋ฐฉ์์ผ๋ก ์ธ์ฝ๋ฉํ๊ณ ์ ํ์์ ๊ทธ๊ฒ์ ์ฝ์ด ๋ฐ์ํ๋ ์ ๊ทผ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด๋ฒ ์ฅ์ ์ ๋ชฉ์ด๊ธฐ๋ ํ '๋์์ธ ํ ํฐ'์ ์์ ์ค๋ช ๊ณผ ๊ฐ์ด ๋์์ธ ์์ฌ๊ฒฐ์ ์ ์ฌ๋๊ณผ ๊ธฐ๊ณ ๋ชจ๋๊ฐ ์ฝ์ ์ ์๋ ๋ฐฉ์์ผ๋ก ์ธ์ฝ๋ฉํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์ด์ ๋์์ธ ํ ํฐ์ ๋ํด ์ข ๋ ์์ธํ๊ฒ ์์๋ณด๊ฒ ์ต๋๋ค.
๊ฐ์ ์ธ์ฝ๋ฉ
๋จผ์ ๋์์ธ ํ ํฐ์ ๊ฐ์ ์ธ์ฝ๋ฉํ ์ ์์ต๋๋ค.
'์ด ์์์ ์ด๋ฆ์ $carrot-500
์ด๋ค.'๋ผ๊ณ ํํํ ์ ์๊ฒ ์ฃ ? ์ด ํํ๋ ํ๋ฆฐ ๋ง์ ์๋์ง๋ง ์ ๋ ์กฐ๊ธ ๋ ์ค์ํ ์๋ฏธ๋ฅผ ํฌํจํ๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ ๊ฐ ์๊ฐํ๋ ์ ํํ ์๋ฏธ๋ '์ฐ๋ฆฌ๋ ์ ํ์ ์ด ์์์ ์ฌ์ฉํ ๊ฒ์ด๊ณ ๊ทธ ์์์ ์ด๋ฆ์ $carrot-500
์ด๋ค.'์
๋๋ค.
๋ ํํ์ ๋น์ทํด ๋ณด์ด๊ณ ๋ง์ฅ๋ ๊ฐ์ง๋ง ์ฌ๊ธฐ์๋ ์ค์ํ ์ฐจ์ด๊ฐ ์์ต๋๋ค. ์ ํ์ ์ด ์์์ ์ฌ์ฉํ ๊ฒ์ด๋ผ๋ ๊ฒ์ ์๋ฏธ๋ ์ ์ธํ์ง ์์ ์์์ ์ฌ์ฉํ์ง ์๊ฒ ๋ค๋ ๋ป์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด๋ฅผ ํตํด์ ๋์์ธ ์์คํ ํ์ ๋์์ธ ๊ฒฐ์ ์ ์ ์ฐํ ์งํฉ์ผ๋ก ์ ์งํ๊ณ ๋์์ธ ์์ฌ ๊ฒฐ์ ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ํ์ง๋ง ๋์์ธ์ ์ ์ฐ์ฑ๊ณผ ์์ ๋๋ ๋จ์ด์ง ์ ์์ต๋๋ค.
์ธ์์๋ ๋ฌดํํ ๊ฐ๋ ์ด ์กด์ฌํ์ง๋ง ์ฐ๋ฆฌ๋ ์ ํํ ๋จ์ด๋ง์ผ๋ก๋ ์ถฉ๋ถํ ์ํตํ๋ฉฐ ์ด์๊ฐ ์ ์์ต๋๋ค. ์ ๋ ๊ฐ์ ๋งฅ๋ฝ์ผ๋ก ๋ฌดํํ ๋์์ธ ๊ฐ์ด ์กด์ฌํ์ง๋ง ์ ํํ ๋์์ธ ํ ํฐ์ผ๋ก ์ํตํ ์ ์๋ค๊ณ ๋ฏฟ์ต๋๋ค.
์๋๋ฅผ ์ธ์ฝ๋ฉ
๋์์ธ ํ ํฐ์ ์ข ๋ ์ ์ฐํ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํด ๊ณ์ธต์ ์ถ๊ฐํ ์๋ ์์ต๋๋ค. ์๋์ ๊ฐ์ด ๊ฐ์ ์ธ์ฝ๋ฉํด์ ์ ํํ๊ฒ ๊ตฌ์ฑ๋ ๋์์ธ ํ ํฐ์ ์๋๋ฅผ ์ธ์ฝ๋ฉํ๋ ๊ณ์ธต์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
๋งฅ๋ฝ
๋ง์ง๋ง์ผ๋ก ๋์์ธ ํ ํฐ์ ๋งฅ๋ฝ์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ฐ์ ๋ถ์ฌํ ์ ์์ต๋๋ค.
์์ ์ธ ๊ฐ์ง๋ฅผ ์ ๋ฆฌํ๋ฉด ๋์์ธ ํ ํฐ์ ๋ค์๊ณผ ๊ฐ์ด ๋งฅ๋ฝ๊ณผ ๊ณ์ธต์ ํตํด ๊ตฌ์ฑ๋ฉ๋๋ค.
๋น๊ทผ์์๋ ์ด ์ ์๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ๋จํ DSL(Domain-Specific Languages : ๋๋ฉ์ธ ํนํ ์ธ์ด)์ ๋ง๋ค์ด์ ๋์์ธ ํ ํฐ์ ๊ด๋ฆฌํฉ๋๋ค. ์ด ํํ์์ ์ฌํด ์ถ๊ฐ๋ Figma Variables์ ์๋ฏธ์ ์ผ๋ก ์ผ์นํ๊ธฐ ๋๋ฌธ์ ์๋ก ๋์์ธ ํ ํฐ์ ๊ตฌ์ถํ๋ ํ์ด ์๋ค๋ฉด ์ด๋ฅผ ์ ๊ทน์ ์ผ๋ก ๊ณ ๋ คํด ๋ณด๋ ๊ฒ๋ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค. ๋น๊ทผ์์๋ ํผ๊ทธ๋ง ์ปดํฌ๋ํธ ํ๋ ์ ์์ ์ด DSL์ ๋ฃ์ด์ ์ด ์ปดํฌ๋ํธ๋ฅผ ์ง์ค์ ์์ฒ์ผ๋ก ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
๋์์ธ ํ ํฐ์ ์ฝ๋๋ก
ํ๋ก ํธ์๋์์์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ ์์ธํ๊ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ด alias ํจํค์ง๋ ์ด๋ชจ์ ์์๋ ์๋ ์ฒซ ๋ฒ์งธ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์๊ณ , vanilla-extract์์๋ ๋ ๋ฒ์งธ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค. ์กฐ์ง ๋ณ๋ก ์ฌ์ฉ๋๋ ๊ธฐ์ ์ด ๋ค์ํ ๋น๊ทผ์ ํน์ฑ์ ํน์ CSS In JS ๊ธฐ์ ๋ง ์ ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์๋์ ๊ฐ์ด ๋ค์ํ ์ ๊ทผ์ผ๋ก ๊ธฐ์ ์ ๋ง๊ฒ ์ ์ฉ๋์ด ์์ต๋๋ค.
// ์ฌ์ฉ์ฌ๋ก: @emotion/styled
const Info = styled.p`
${vars.$sementic.typography.label4Regular}
display: flex;
align-items: center;
color: ${vars.scale.color.gray600}
`;
// ์ฌ์ฉ์ฌ๋ก: @vanilla-extract/recipes
// ..
variants: {
selected: {
true: {
backgroundColor: vars.$scale.color.gray800,
border: `1px solid ${vars.$scale.color.gray800}`,
color: vars.$scale.color.gray00
},
false: {
backgroundColor: vars.$scale.color.paperDefault,
border: `1px solid ${vars.$scale.color.divider1}`,
color: vars.$scale.color.gray900
}
},
},
});
ํจ์ : ์๋งจํฑ ํ ํฐ์ ์ฃ๋ถ๋ฅธ ์ถ์ํ
๋์์ธ ํ ํฐ์ ๋ง๋ค๋ฉฐ ์ด๋ ค์์ ๊ฒช์๋ ๋ถ๋ถ์ ๊ธฐ์ ์ ์ธ ๋ถ๋ถ๋ณด๋ค๋ ์ด์์ ์ธ ๋ถ๋ถ์ด์์ต๋๋ค. ํนํ ๊ธฐ์ต์ ๋จ๋ ์๋ชป๋ ํ๋จ์ ์๋งจํฑ ํ ํฐ์ ์ฑ๊ธํ๊ฒ ์ ์ํ๋ ๊ฒ์ ๋๋ค.
์ ๊ฒฝํ์ผ๋ก ์๊ฐํด ๋ณด๋ฉด ์ด๋ฌํ ์ฃ๋ถ๋ฅธ ์๋งจํฑ ํ ํฐ ์ ์๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๊ธฐ๋ณด๋ค๋ ๋ ํฐ ๋์์ธ ํผ๋์ ๋ง๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ ์ฉํ ์๋งจํฑ ํ ํฐ์ ์ ์ํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ผ๊น์? ์๋์ ๊ฐ์ด ๋ค์ํ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๊ณ ๋ คํ์ฌ ์ด๋ค ๊ด์ฌ์ฌ๋ฅผ ๊ณต์ ํ๋์ง ์ดํด๋ณด๋ ๊ฒ์ ๋๋ค.
์๋งจํฑ ํ ํฐ์ ์ ์ ์ํ์ฌ ์ฌ์ฉํ๋ฉด ๋ถ๋ช ๊ฐ๋ ฅํ ๋๊ตฌ๊ฐ ๋ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์๋ชป ์ ์๋ ์๋งจํฑ ํ ํฐ์ ๋ ํฐ ํผ๋์ ์ผ๊ธฐํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ฃ๋ถ๋ฅด๊ฒ ์๋งจํฑ ํ ํฐ์ ์๋๋ฅผ ๋ถ์ฌํ๋ ๊ฒ์ ์ํํฉ๋๋ค. ์ฆ ์ถ์ํ๋ ๊ด์ฐฐ์ ํตํด ์ป์ด์ง๊ธฐ ๋๋ฌธ์, ์ฌ๋ฌ ์ฌ๋ก๋ฅผ ๊ณต์ ํ๋ ๊ณตํต์ ๊ด์ฌ์ฌ๋ฅผ ์ดํด๋ณด๊ณ ์ด๋ฅผ ํตํด ์๋๋ฅผ ์ถ์ถํ๋ ์ ๊ทผ์ด ๋ ์์ ํฉ๋๋ค.
์ง๊ธ๊น์ง ๋์์ธ ํ ํฐ์ ๋ํด ์์๋ดค์ต๋๋ค. ๋์์ธ ํ ํฐ์ ๋์์ธ ์์คํ ์กฐ์ง์ ์ด์ํ ๋ ๊ต์ฅํ ๊ฐ๋ ฅํ ์๋จ์ด์ง๋ง ์ฌ์ฉ์๊ฐ ๋์์ธ ์์คํ ์ ๊ธฐ๋ํ๋ ๊ฒ์ ์ปดํฌ๋ํธ์ผ ๊ฒ์ ๋๋ค. ๋ค์ ์ฅ์์๋ ๋์์ธ ์์คํ ์์์ ์ปดํฌ๋ํธ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
3. ์ปดํฌ๋ํธ
์ด๋ฒ ์ฅ์์๋ ์๋ ๋ด์ฉ์ ๋ํด ์์๋ด ๋๋ค.
- Atomic Design์ด ํผ๋์ค๋ฌ์ด ์ด์
- ์ปดํฌ๋ํธ์ ๊ตฌ์ฑ์์ ์ ํํ๊ฒ ์ดํด
- ๋์์ด๋-๊ฐ๋ฐ์ ๊ฐ ์์ฌ์ํต ๋ฌธ์ ํด๊ฒฐ
Atomic Design
์ํ ๋ฏน ๋์์ธ์ ๋ช ๋ ์ ๊น์ง๋ง ํด๋ ์์ฃผ ์ธ๊ธ๋๋ค๊ฐ ์ธ์ ๊ฐ๋ถํฐ ์ ๋ค๋ฆฌ์ง ์๊ฒ ๋ ํค์๋์ ๋๋ค. ํน์ ์ํ ๋ฏน ๋์์ธ์ ๋ณ๋ค๋ฅธ ๋ณํ ์์ด ์ ํ์ ์ ์ ์ฉํ๊ณ ๊ณ์ ๊ฐ์? ์ ์ด๋ ์ ๋ ์ํ ๋ฏน ๋์์ธ์ ์๋ ๊ทธ๋๋ก ์ ์ฉํ๊ธฐ ์ด๋ ต๋ค๊ณ ๋๋ผ๊ณ ์์ต๋๋ค.
์ฌ์ค ์ ๋ต์ ํ๋๋ก ์ ํด์ง์ง ์์ต๋๋ค. ๊ธฐ์ค์ ๋ฐ๋ผ ์ ๋ต์ด ๋ฌ๋ผ์ง๊ธฐ ๋๋ฌธ์ ๋๋ค. ํํ ๋จ์๋ก๋ ๋ ธ๋ ๋ฐ์ค๊ฐ ์ํฐ์ด์ง๋ง ๊ธฐ๋ฅ ๋จ์๋ก๋ ๋ผ๋์ค ๋ฒํผ 1๊ฐ๋ก๋ ์๋ฏธ๊ฐ ์๊ธฐ ๋๋ฌธ์ ํ๋ ๋ฐ์ค์ ๊ธฐ๋ฅ ๋จ์๊ฐ ์ํฐ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๊ทผ์ฑ ๋จ์๋ก๋ ํผ ์์์ ๋ ๋ฒจ์ ์ ๊ณตํ ์๋ฌด๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋นจ๊ฐ ๋ฐ์ค์ ์ ๊ทผ์ฑ ๋จ์๊ฐ ์ํฐ์ด ๋ฉ๋๋ค.
์ด๋ ๊ฒ ๊ธฐ๋ฅ๊ณผ ํํ๋ฅผ ๋๋ ์ ๋ฐ๋ผ๋ณด๋ ์ ๊ทผ๋ฒ์ ๋ํด ๊ฐ๋จํ๊ฒ ์์๋ณด๊ฒ ์ต๋๋ค.
์ปดํฌ๋ํธ: ํํ
์ปดํฌ๋ํธ: ๊ธฐ๋ฅ
๊ทธ๋์ ๋ ๋๋ง์ ์ ๊ฑฐํ๊ณ ์ํ๋ง ๋จ๊ธฐ๋ฉด ์ปดํฌ๋ํธ์ ๊ธฐ๋ฅ์ ์ธก๋ฉด์ด ๋์ฑ ํ์คํด์ง๋๋ค. ๋ฐ๋ผ์ ์ปดํฌ๋ํธ์ ๊ธฐ๋ฅ์ ์ธก๋ฉด์ ๋ ๋๋ง์ ์ ์ธํ๊ณ ์ ์ ์ ๋ ฅ์ ๋ํด์ ์ปดํฌ๋ํธ์ ์ํ๊ฐ ์ด๋ป๊ฒ ์ ์ด๋๋์ง ์ ์๋ฉ๋๋ค.
Atomic Design์ด ํผ๋์ค๋ฌ์ด ์ด์
๊ทธ๋ ๋ค๋ฉด ์ํ ๋ฏน ๋์์ธ์ด ํผ๋์ค๋ฌ์ด ์ด์ ๋ ๋ฌด์์ผ๊น์? ๊ฒฐ๋ก ์ ์ผ๋ก ์ํ ๋ฏนํ ๊ธฐ๋ฅ, ์ํ ๋ฏนํ ํํ๋ ์กด์ฌํ ์ ์์ต๋๋ค. ํ์ง๋ง ์ํ ๋ฏนํ ์ปดํฌ๋ํธ๋ ํ๋๋ก ์ ํด์ง์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ์ปดํฌ๋ํธ๋ง์ ๋ถ๋ฅํด์ ์ต์ ๋จ์๋ก ์ ์ํ๋ ค๊ณ ํ๋ฉด ์คํจํ๊ธฐ ์ฝ์ต๋๋ค. ํํ์ ์ํ ๋ฏน์ ์ ๊ณตํ๋ ์คํ์ผ ์ํธ์ ๊ธฐ๋ฅ์ ์ํ ๋ฏน์ ์ ๊ณตํ๋ ํค๋๋ฆฌ์ค ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํด์ ์๊ฐํด์ผ ๋ฌด์์ด ์ต์ ๋จ์์ธ์ง์ ๋ํ ํผ๋์ ์์จ ์ ์๊ณ , ํ์ด ์์ผ๋ก ๋์๊ฐ ์ ์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ด์ ์ํ ๋ฏน ๋์์ธ์์ ๋ฒ์ด๋ ๊ธฐ๋ฅ๊ณผ ํํ ๊ฐ๊ฐ์ ๋ํด์ ์ปดํฌ๋ํธ์ ๊ตฌ์ฑ ์์๋ฅผ ํด๋ถํด ๋ด ์๋ค.
์ปดํฌ๋ํธ ํด๋ถํด ๋ณด๊ธฐ: ๊ธฐ๋ฅ
๋จผ์ ๊ตฌ์กฐ๋ ์ปดํฌ๋ํธ๊ฐ ์ด๋ค ๋ถํ๋ค๋ก ๊ตฌ์ฑ๋์ด ์๊ณ ๊ฐ ๋ถํ์ด ์ ์ ์ํธ์์ฉ์ ์ด๋ค ์ญํ ์ ๊ฐ์ง๋์ง ์ ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์ ์ปดํฌ๋ํธ๋ ์ปจํธ๋กค์ด๋ผ๋ ์ญํ ์ ๊ฐ์ง ์ฒดํฌ๋ฐ์ค์ ๋ผ๋ฒจ์ด๋ผ๋ ์ญํ ์ ํ๋ Item Label ํ ์คํธ๋ก ๊ตฌ์ฑ๋์ด ์๊ณ ์ด๋ฅผ ๊ฐ์ธ๋ Root๊ฐ ์์ต๋๋ค.
๋ ๋ฒ์งธ๋ก ์ํ๋ ์ ์ ์ ๋ ฅ์ ์ํด ๋ณํ ์ ์๋ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ์ ์ํฉ๋๋ค. ๋ํ์ ์ผ๋ก Pressed (active), Hover, Focused, Selected(Checked) ๋ฑ์ด ์์ต๋๋ค.
์ธ ๋ฒ์งธ๋ก ์ํธ์์ฉ์ ์ํ์ ๋ณ๊ฒฝ์ ์ ๋ฐํ๋ ๋จ์์ ๋๋ค. ์ฒดํฌ๋ฐ์ค๋ฅผ ์๋ก ๋ค๋ฉด ํด๋ฆญ์ ํ๋ฉด Checked๊ฐ ๋ฐ๋๊ณ ํญ์ผ๋ก ํฌ์ปค์ค๋ฅผ ์ก์ผ๋ฉด Focused๊ฐ ๋ฐ๋๋๋ค.
๋ง์ง๋ง์ผ๋ก ๋งฅ๋ฝ์ ์ฝ๋์์ ์ฃผ์ ํ๋ ์ต์ ์ผ๋ก ๋์์ ๊ด์ฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด Disabled ์ต์ ์ ์ฃผ์ ํ๋ฉด ์ฒดํฌ๋ฐ์ค๊ฐ ๋นํ์ฑํ๋๊ณ ์๋ฌด๋ฆฌ ํด๋ฆญํด๋ Checked๊ฐ ๋ฐ๋์ง ์์ต๋๋ค. ๋ฌผ๋ก ์ํ๋ ๋์์ ๊ด์ฌํ ์ ์์ง๋ง ์ํ๋ ์ ์ ์ ์ ๋ ฅ์ ์ํด์ ๋ณ๊ฒฝ๋๋ ๊ฒ์ด๊ณ ๋งฅ๋ฝ์ ์ฝ๋์ ์ํด์๋ง ๋ณ๊ฒฝ๋๋ค๋ ์ค์ํ ์ฐจ์ด์ ์ด ์์ต๋๋ค.
์ปดํฌ๋ํธ ํด๋ถํด ๋ณด๊ธฐ: ํํ
๋ค์์ผ๋ก ์ปดํฌ๋ํธ์ ํํ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ์ปดํฌ๋ํธ์ ํํ๋ ๊ตฌ์กฐ, ์๊ฐ ์ต์ , ์ํ ์ต์ , ๋์์ธ ๊ฒฐ์ ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
๋จผ์ ๊ตฌ์กฐ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ํํ์์์ ๊ตฌ์กฐ๋ ๊ธฐ๋ฅ์์์ ๊ตฌ์กฐ์ ๊ต์งํฉ์ด ๋ง์ง๋ง ๋ฐ๋์ ์ผ์นํ์ง๋ ์์ต๋๋ค. ์ฌ๊ธฐ์ ๊ตฌ์กฐ๋ ์ปดํฌ๋ํธ๊ฐ ์ด๋ค ๋ถํ๋ค๋ก ๊ตฌ์ฑ๋์ด ์๊ณ ๊ฐ ๋ถํ์ด ์ด๋ค ๋ ์ด์์์ ๊ฐ์ง๋์ง ์ ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์์ด์ฝ์ ๊ธฐ๋ฅ์ ์ผ๋ก๋ ์กด์ฌํ์ง ์์ง๋ง, ํํ์ ์ผ๋ก๋ ์กด์ฌํฉ๋๋ค.
์ง๊ธ๊น์ง ๊ธฐ๋ฅ๊ณผ ํํ ๊ฐ๊ฐ์ ๋ํด ์ด๋ค ๊ตฌ์ฑ์์๋ฅผ ๊ฐ์ง๋์ง ์์๋ดค์ต๋๋ค.
๊ธฐ๋ฅ๊ณผ ํํ ๊ตฌ์กฐ์ ๋ฌธ์ ์
์ ๋ ์ด๊ธฐ์ ํผ๊ทธ๋ง์๋ ์ด๋ฐ ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ๊ทธ๋ ค์ผ ํ๋ค๊ณ ์ฃผ์ฅํ ์ ๋ ์์ต๋๋ค. ๋น์ฐํ ํ์๋ฐ์ง ๋ชปํ๊ณ , ์ค์ ๋ก๋ ๋ถํ์ํ ์์ ์ด์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ๊ฒฝํ์ ์ผ๋ก ์ํ๋ค ์ฌ์ด์ ์ฐ์ ์์๊ฐ ์กด์ฌํ๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด Disabled ์ผ ๋๋ ํธ๋ฒ๋ฅผ ๊ณ ๋ คํ ํ์๊ฐ ์์ต๋๋ค. ์ค์ ๋ก ๋ ๋๋ง์ด ๋ณํ ํ์๊ฐ ์๋ ์ํ ์กฐํฉ์ ์ ํ์ ์ด๊ณ , ๊ทธ ์ ํ์ ์ธ ์ํ๋ ๊ณง ๋์์ด๋์ ์๊ฐ์ผ๋ก ๋ฐ๋ผ๋ณธ ๊ฒฝ์ฐ์ ์์ ์ผ์นํ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ ์ํ์ ๋งฅ๋ฝ์ ์กฐํฉ์ ์กฐ๊ฑด์ ๋ฐ๋ผ 1์ฐจ์ enum์ผ๋ก ์ ๋ฆฌํ์ฌ ์ํ๋ฅผ ์์ถํ๋ฉด ๋งฅ๋ฝ๊ณผ ์ํ ์ต์ ์ ๋น ์ง์์ด ํ์ ํ๊ณ ์ํตํ ์ ์์ต๋๋ค.
์ํ ์์ถ
์ํ, ๋งฅ๋ฝ ์กฐํฉ์ 1์ฐจ์ enum์ผ๋ก ์ ๋ฆฌ
State | Condition |
---|---|
enabled | isDisabled OFF, isHovered OFF, isFocused OFF, isPressed OFF |
hovered | isDisabled OFF, isHovered ON, isPressed OFF |
focused | isDisabled OFF, isFocused ON, isPressed OFF |
pressed | isDisabled OFF, isPressed ON |
disabled | isDisabled ON |
๊ด์ฌ์ฌ ๋ถ๋ฆฌ
์ด๋ ๊ฒ ์ํ ์์ถ๊น์ง ๋ง์น๋ฉด ๊ธฐ๋ฅ๊ณผ ํํ์ ๊ณตํต ๊ด์ฌ์ฌ์ ๊ณ ์ ๊ด์ฌ์ฌ๋ฅผ ํ์ ํ ์ ์์ต๋๋ค. ๊ตฌ์กฐ, ์ํ, ๋งฅ๋ฝ์ ์์ชฝ ๋ชจ๋ ๊ณตํต์ ์ผ๋ก ์กด์ฌํ๋ ๊ด์ฌ์ฌ์ด๊ณ , ์ํธ์์ฉ์ ๊ธฐ๋ฅ์๋ง, ์๊ฐ ์ต์ ๊ณผ ๋์์ธ ๊ฒฐ์ ์ ํํ์๋ง ์กด์ฌํ๋ ๊ด์ฌ์ฌ์ ๋๋ค.
์์ฌ์ํต ์ํ ์ฐธ์กฐ
๊ด์ฌ์ฌ ๋ถ๋ฆฌ๋ ์์ฌ์ํต์ ์ํ ์ฐธ์กฐ๋ฅผ ํด๊ฒฐํ๋ ํค์๋์ ๋๋ค. ์๋์ ๊ฐ์ ์ํฉ์ ์๊ฐํด๋ณด๊ฒ ์ต๋๋ค.
๊ฐ๋ฐ์: ๋์์ธ์ด ์์ด์ ์์ง ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ ์ ์์ด์.
๋์์ด๋: ์ปดํฌ๋ํธ๋ฅผ ๋์์ธํ๋ ค๋๋ฐ ์ด๋ค Variant๋ค์ด ํ์ํ์ฃ ?
๋์์ด๋: ์ผ๋จ ๋์์ธ ํด๋จ๋๋ฐ ๊ฐ๋ฐ์๊ฐ ์ด๋๋ก ๋ง๋ค๋ฉด ์ ๋๋์.
๊ฐ๋ฐ์: ๊ทผ๋ฐ ์ด๋ฏธ ํผ๊ทธ๋ง์ ๋ฐฐํฌํด์ ๋์์ด๋๋ค์ด ์ฐ๊ณ ์์ด์.
์ด์ ๊ฐ์ ์ํฉ์ ์์ฌ์ํต์ ์ํ ์ฐธ์กฐ ๋ฌธ์ ๋ผ๊ณ ํฉ๋๋ค. ์ค์ ๋ก ๋์์ธ ์์คํ ํน์ ์ปดํฌ๋ํธ ๋จ์๋ก ๊ฐ๋ฐํ๋ ์กฐ์ง๋ค์์ ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ๋ค์ ๋๋ค. ์ ๋ ์ด๋ฐ ๋ฌธ์ ๋ฅผ '๋์์ธ์ ๋จผ์ ํ๊ณ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๋ ๋ฐฉ์์ ๋ฌธ์ '๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋์์ธ์ ํ ๋ ๊ฐ๋ฐ์ ์ด๋ค ์ํ๋ค์ด ์กด์ฌํ๊ฒ ๋ ์ง ๋ฏธ๋ฆฌ ์๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ์ ๋ํ ์์กด์ฑ์ด ์๊น๋๋ค. ๋ฐ๋ฉด ๊ฐ๋ฐ์ ํ ๋๋ ๋์์ธ์ด ๋์์ผ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ๋์์ธ์ ๋ํ ์์กด์ฑ์ด ์๊น๋๋ค.
์์ฌ์ํต ์ํ ์ฐธ์กฐ ํด๊ฒฐ
๊ทธ๋ ๋ค๋ฉด ์๋ก์๊ฒ ์์กด์ ์ธ ์์ฌ์ํต ์ํ ์ฐธ์กฐ๋ฅผ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์๊น์? ๊ฐ๋ฐ์์๋ ํํ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํด์ ์์กด ๋ฐฉํฅ์ ์ญ์ ์ํค๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ์ฐ๋ฆฌ๊ฐ ์ผํ๋ ๋ฐฉ์์๋ ์ ์ฉํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์์์ ์ธ๊ธํ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ๋ฅผ ๋ฐํ์ผ๋ก ๋์์ธ๊ณผ ๊ฐ๋ฐ์ ๊ณตํต ์ธํฐํ์ด์ค๊ฐ ๋ฌด์์ธ์ง ์๊ณ ์์ต๋๋ค. ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ ๊ฐ ์๊ฐํ๋ ๋์์ธ ์์คํ ํ์ ์ผํ๋ ๋ฐฉ์์ ์๊ฐํ๊ฒ ์ต๋๋ค.
๋จผ์ ์์ฑํ๋ ค๋ ์ปดํฌ๋ํธ์ ๊ฐ๋จํ ์ค์ผ์น๋ฅผ ๋์์ด๋์ ๊ฐ๋ฐ์๊ฐ ํจ๊ป ๊ทธ๋ฆฌ๊ณ ์ด๋ค ๊ตฌ์กฐ์ ์ํ ์ต์ ์ ๊ฐ์ง๊ฒ ๋ ์ง ์ ์ํฉ๋๋ค.
์ ๋ฆฌํ๋ฉด, ์์ ๋งํ '๋์์ธ์ ๋จผ์ ํ๊ณ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๋ ๋ฐฉ์์ ๋ฌธ์ ' ์ฆ, ํผ๊ทธ๋ง์์ ๋์์ธํ ๋ด์ฉ์ด ๊ฐ๋ฐ๋ก ์ด์ด์ง๋ ๋ฐฉ์์ผ๋ก ์ผํ๋ ๊ฒ์ด ์๋๋ผ, ๊ตฌ์กฐ๋ ์ํ์ ๊ฐ์ ๊ณตํต ์ธํฐํ์ด์ค๋ฅผ ๋จผ์ ์ ์ํ๊ณ ์ด ๋ด์ฉ์ด ํผ๊ทธ๋ง์ ๊ฐ๋ฐ๋ก ์ด์ด์ง๋ ๋ฐฉ์์ผ๋ก ๋ฐ๊พธ์ด ์์ฌ์ํต์ ์ํ ์ฐธ์กฐ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
์ ์ฐ์ฑ VS ์ผ๊ด์ฑ
์์ ์ดํด๋ณธ ์ฐจํฌ๋ผ์ ์คํํธ๋ผ์ API๋ฅผ ๋ค์ ํ๋ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ ํ ์ธ์ด๋ฅผ ๋ง๋๋ ์ ์ฅ์์ ์ผ๊ด์ฑ์ ์ต์ฐ์ ์ผ๋ก ์ถ๊ตฌํ์ฌ ์ค๋ฅธ์ชฝ์ API์ฒ๋ผ ๊ฐ๊ฒฐํ๊ฒ ์ ๊ณตํ๊ณ ์ถ์ ๊ฒ์ ๋น์ฐํ ์๊ฐ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ผ๊ด์ฑ์ ์ถ๊ตฌํ๋ ํํ๋ก ์ ๊ณตํจ์ผ๋ก์จ ๋ฐ์ํ ์ ์๋ ๋ชจ๋ ์ผ์ด์ค์ 90%๋ฅผ ์ปค๋ฒํ ์ ์๋ค๊ณ ํ๋๋ผ๋, ์ฌ์ฉ์ ์ ์ฅ์์๋ ์ปค๋ฒํ์ง ๋ชปํ๋ 10%์ ์ผ์ด์ค๋ก ์ธํด ๊ฐ๋ฐ์ด ์ง์ฐ๋ ์ ์์ต๋๋ค.
์ค์ ๊ตฌํ์์๋ ์๋์ ๊ฐ์ด ํจํค์ง๋ฅผ Core, Composable, Pre-Composed๋ผ๋ ์ธ ๊ฐ์ง ๊ณ์ธต์ผ๋ก ๋ถ๋ฆฌํฉ๋๋ค. ์ฌ์ ์กฐํฉ(Pre-Composed) ๋ ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํด ์ผ๊ด์ฑ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ Styled์ ์ ์ฌํ ๋ฐฉ์์ ์คํ์ผ๋ง ํ๋กํผํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋จ, margin ๋ฑ์ ๋ ์ด์์์๋ง ํ์ ํด์ ์ ๊ณตํฉ๋๋ค. ๊ทธ ์ด์์ ์ ์ฐ์ฑ์ด ํ์ํ ๊ฒฝ์ฐ์๋ Composable ํจํค์ง๋ฅผ ์ฌ์ฉํ๊ณ , ๊ทธ๊ฒ์ ์ฌ์ฉํ๋ ๋ฐฉ์์ด ์ฌ์ ์กฐํฉ๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋นํด ์ด๋ ต์ง ์๊ฒ ํฉ๋๋ค.
์ปดํฌ๋ํธ ๊ตฌํ
์ด๋ฒ ๊ธ์์๋ ์ํ ์ฐจํธ์ ํ์ฉ์ ๋ค๋ฃจ์ง ์๊ณ Dom Binding์ ๋ํด์๋ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๊ธฐ๋ฅ: Dom Binding
๋จผ์ ์๋์ ๊ฐ์ ์๊ตฌ ์ฌํญ์ ๊ฐ์ง ์ปดํฌ๋ํธ๊ฐ ํ์ํ๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค. 4๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ , ์ฒดํฌ ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ์ํ๋ฅผ ๊ฐ์ง๋๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋ฆญ์ ํ๋ฉด ๊ทธ ์ฒดํฌ ์ฌ๋ถ๊ฐ ์ ํ์ด ๋๋ฉฐ, Dissabled๊ฐ ์ฃผ์ ๋๋ฉด ์ ํ์ด ๋ฐ์ํ์ง ์์์ผ ํ๋ ์ปดํฌ๋ํธ์ ๋๋ค.
- ๊ตฌ์กฐ - Root, Control, Input, Label
- ์ํ - isSelected : boolean
- ์ํธ์์ฉ - click
- ๋งฅ๋ฝ - isDisabled : boolean
Dom Binding์ ๊ตฌํํ๊ธฐ ์ํด ๋จผ์ ๊ตฌ์กฐ์ ๋ํด ํํํด ๋ณด๊ฒ ์ต๋๋ค. ์์ ๋งํ 4๊ฐ์ ๊ตฌ์กฐ๋ฅผ ์๋์ ๊ฐ์ด ์ ์ธํ ์ ์์ต๋๋ค.
export function connect() {
return {
rootProps: { /* ... */ },
controlProps: { /* ... */ },
inputProps: { /* ... */ },
labelProps: { /* ... */ },
}
}
์ด ํ๋กํผํฐ๋ค์ ์ต์ข ์ ์ผ๋ก JSX์ ์๋์ ๊ฐ์ด ์คํ๋ ๋ ๋์ด์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
const api = useCheckbox(otherProps);
return {
<div {...api.rootProps}>
<div {...api.controlProps}>
<input type="checkbox" {...api.inputProps} />
</div>
<div {...api.labelProps}>{label}</div>
</div>
}
์ํ๋ฅผ Dom์ ์ ์ฉํ๋ ๊ฒ์ ์ํ ์ฐจํธ๋ก๋ถํฐ ์ ๋ฌ๋ฐ์ ์ํ๋ฅผ ๋ฐํ์ผ๋ก ์๋ฆฌ๋จผํธ์ ํ๋กํผํฐ๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์
๋๋ค. ์๋์ ๊ฒฝ์ฐ์๋ isSelected
๋ฅผ inputProps
์ checked
์ ๋ฐ์ธ๋ฉํ๋ ๊ฒ์ผ๋ก ๊ตฌํํ ์ ์์ต๋๋ค.
export function connect(state) {
return {
rootProps: { /* ... */ },
controlProps: { /* ... */ },
inputProps: {
checked: state.isselected
},
labelProps: { /* ... */ },
}
}
์ํธ์์ฉ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ํ ์ฐจํธ์ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ผ๋ก ๊ตฌํํฉ๋๋ค. ์๋์ ๊ฒฝ์ฐ์๋ inputProps
์ onChange
๊ฐ ๋ฐ์ํ๋ฉด ์ํ ์ฐจํธ์ 'TOGGLE'์ด๋ผ๋ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํฉ๋๋ค. ์ํ ์ฐจํธ๋ 'TOGGLE'์ด๋ผ๋ ์ด๋ฒคํธ์ isDisabled
๋ผ๋ ๋งฅ๋ฝ์ ๋ฐํ์ผ๋ก ํ์ฌ ์ํ๊ฐ ๋ฐ๋์ด์ผ ํ๋์ง ์๋์ง๋ฅผ ํ๋จํ์ฌ ๊ฐฑ์ ๋ ์ํ๋ฅผ Dom Binding์ ์ ๋ฌํ๊ฒ ๋ฉ๋๋ค.
export function connect(state, send) {
return {
rootProps: { /* ... */ },
controlProps: { /* ... */ },
inputProps: {
checked: state.isselected,
onChange: (e) => {
send("TOGGLE", { event: e });
},
},
labelProps: { /* ... */ },
}
}
๋งฅ๋ฝ์ ์ ์ฉํ๋ ๊ฒ๋ ์ํ ์ ์ฉ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์๋ฆฌ๋จผํธ์ ํ๋กํผํฐ๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ผ๋ก ๊ตฌํ๋ฉ๋๋ค. ๋์ ์ฐจ์ด๋ ์ํ ์ฐจํธ์์ ์ ๊ณตํ๋ ์ํ๊ฐ ์๋ ์ธ๋ถ์์ ์ฃผ์
ํ ํ๋กํผํฐ๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋ค๋ ๊ฒ์
๋๋ค. ์๋ ๊ฒฝ์ฐ์๋ inputProps
์ disabled
ํ๋กํผํฐ์ ์ธ์ฃผ์์ ์ฃผ์
๋ ctx
์ isDisabled
๋ฅผ ๋ฐ์ธ๋ฉ ํ๋ ๊ฒ์ผ๋ก ํํ๋๊ณ ์์ต๋๋ค.
export function connect(state, send, ctx) {
return {
rootProps: { /* ... */ },
controlProps: { /* ... */ },
inputProps: {
disabled: ctx.isDisabled,
checked: state.isselected,
onChange: (e) => {
send("TOGGLE", { event: e });
},
},
labelProps: { /* ... */ },
}
}
์ํ์ ๋งฅ๋ฝ์ ๋ํ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๊ฐ ์ ์ธํ ๋ค์ ์ด๊ฒ์ extends
ํด์ ์ํ ๋ณํ์ ๋ํ ๋ชจ๋ ์ฝ๋ฐฑ์ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ํค๋๋ฆฌ์ค ์ฒดํฌ๋ฐ์ค ์ปดํฌ๋ํธ๊ฐ ์๊ตฌํ๋ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์ ์ธํ ์ ์์ต๋๋ค.
interface State {
isSelected: boolean;
}
interface Context {
isDisabled: boolean;
}
export interface CheckboxBehaviorProps extends State, Context {
onSelectedChange: {isSelected: boolean } => void;
}
๊ทธ๋ฆฌ๊ณ ์๋์ ๊ฐ์ด ์ด ํ๋กํผํฐ๋ฅผ ๋ฐ์์ ์ํ ์ฐจํธ์ ์ ๋ฌํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ Dom Binding์ ์ ๋ฌํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ก ๋ฆฌํดํ๋ ๊ฒ๋ง์ผ๋ก ๋ฆฌ์กํธ ๋ํผ๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ์ค์ ์ฝ๋์์๋ ๋ฆฌ์กํธ์์ ์ํ ๋๊ธฐํ๋ฅผ ์ํด useSyncExternalStore
๋ useEffect
์ ๊ฐ์ ๋ช ๊ฐ์ง ๊ธฐ๋ฒ๋ค์ด ๋ ํฌํจ๋์ด์ผ ํ์ง๋ง ์๋์์๋ ์๋ตํ์ฌ ํํํ์์ต๋๋ค.
export function useCheckbox(props: CheckboxBehaviorProps) {
const [state, send] = useMachine(machine);
return connect(state, send, props);
}
ํํ
์ง๊ธ๊น์ง ๊ธฐ๋ฅ ์์ญ์ ์ปดํฌ๋ํธ ๊ตฌํ์ ๋ํด ์์๋ดค์ต๋๋ค. ์ด๋ฒ์๋ ํํ์ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. CSS์ ์๋ฐ์คํฌ๋ฆฝํธ ์ธ์ด๋ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ Hook์ฒ๋ผ ๋ํผ๋ฅผ ์์ฑํ๊ธฐ๋ ์ด๋ ต์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ CSS๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ ์๋ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด๋ฒ์๋ ์๋์ ๊ฐ์ ์๊ตฌ์ฌํญ์ ์ปดํฌ๋ํธ๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
- ๊ตฌ์กฐ - Root, Control, Icon, Label
- ์๊ฐ ์ต์ - size = large, medium
- ์ํ ์ต์ - selected
- ๋์์ธ ๊ฒฐ์ - large์ผ๋, root height = 32px / medium์ผ๋, root height = 24px / selected์ผ๋, control ๋ฐฐ๊ฒฝ= primary
๋จผ์ ๊ตฌ์กฐ์ ๋ํด ํํํด ๋ณด๊ฒ ์ต๋๋ค. Dom binding๊ณผ ์ ์ฌํ๊ฒ ๊ตฌ์กฐ๋ฅผ ํํํ๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค.
const checkbox = defineReceipt({
name: 'checkbox',
slots: ["root", "control", "icon", "label"],
base: {
root: { /* ... */ },
control: { /* ... */ },
icon: { /* ... */ },
label: { /* ... */ },
},
variants: { /* ... */ },
});
๊ทธ๋ฆฌ๊ณ ์๋์ ๊ฐ์ด Variants ํํ์์ ์ฌ์ฉํ์ฌ ์๊ฐ ์ต์
์ ํํํ ์ ์์ต๋๋ค. ์๋์ ๊ฒฝ์ฐ์๋ large ์ผ ๋ root์ height
๊ฐ 32px
์ด ๋๊ณ , medium ์ผ ๋ height
๋ 24px
์ด ๋๋ค๊ณ ํํํ๊ณ ์์ต๋๋ค.
const checkbox = defineReceipt({
name: 'checkbox',
slots: ["root", "control", "icon", "label"],
base: {
root: { /* ... */ },
control: { /* ... */ },
icon: { /* ... */ },
label: { /* ... */ },
},
variants: {
size: {
large: {
root: { height: "32px" },
},
medium: {
root: { height: "24px" },
}
}
},
});
๋ค์์ผ๋ก ์ํ ์ต์
์ ๋ฐ์ดํฐ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ ํ์๋ก ์ฌ์ฉํ๋ ๊ฒ์ผ๋ก ํํํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด์ ์๋์ ๊ฐ์ด data-selected
๋ผ๋ ๋ฐ์ดํฐ ์ดํธ๋ฆฌ๋ทฐํธ๊ฐ ์กด์ฌํ๋ฉด ์ปจํธ๋กค์ ๋ฐฐ๊ฒฝ ์์(background
)์ primary๋ก ๋ฐ๊พธ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด data-selected
๋ผ๋ ์ ํ์๋ HTML์ด ์์์ ์ถ๊ฐํด ์ฃผ์ง ์์ต๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ Dom binding์๋ ๊ด๋ จ ์ฝ๋๋ฅผ ๋ค์ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
const checkbox = defineReceipt({
name: 'checkbox',
slots: ["root", "control", "icon", "label"],
base: {
root: { /* ... */ },
control: {
"&[data-selected]": {
background: $semantic.color.primary,.
}
},
icon: { /* ... */ },
label: { /* ... */ },
},
variants: { /* ... */ },
});
์๋์ ๊ฐ์ด Dom binding์ controlProps
์ selected
์ฌ๋ถ๋ฅผ ๋ฐ์ดํฐ ์ดํธ๋ฆฌ๋ทฐํธ๋ก ์ ๋ฌํ๋ ๋ก์ง์ด ์ถ๊ฐ๋ฉ๋๋ค. ์ด๊ฒ์ ์ํ ์ต์
์ด ๊ณตํต ๊ด์ฌ์ฌ์๋ ๊ฒ์ ์๊ฐํ๋ฉด ๋น์ฐํ ์ถ๊ฐ๋์ด์ผ ํ๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
export function connect(state, send, ctx) {
return {
rootProps: { /* ... */ },
controlProps: {
"date-selected": state.isSelected,
},
inputProps: {
checked: state.isselected,
onChange: (e) => {
send("TOGGLE", { event: e });
},
},
labelProps: { /* ... */ },
}
}
๋ง์ง๋ง์ผ๋ก ์์ฑ๋ CSS ์ฝ๋์ ๋์๋๋ CSS in JS ์ฝ๋๋ฅผ ํจ๊ป ์์ฑํฉ๋๋ค. ์๋ ์ฝ๋๋ ๋ ๊ฐ์ง ํํธ๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค. ๋จผ์ ์๊ฐ ์ต์
์ ๋ํ๋ด๋ ์ธํฐํ์ด์ค์ธ checkboxVariantProps
์ ์๊ฐ ์ต์
์ Slot ๋ณ ํด๋์ค ๋ค์์ผ๋ก ๋ณํํ๋ ํจ์๋ฅผ ํจ๊ป ์ ๊ณตํฉ๋๋ค. ์๋ฅผ ๋ค์ด์ size๊ฐ large๋ก ์ ๋ฌ๋๋ฉด ์๊ฐ ์ต์
์์ ์์ ์์ฑํ checkbox__rootโsize_large
์ ๊ฐ์ ํด๋์ค ๋ช
์ ๋ฐํํ๋ ๋ฐฉ์์
๋๋ค.
type CheckboxSlots = "root" | "control" | "icon" | "label";
export interface CheckboxVariantProps {
size: "large" | "medium" | "small";
}
export function checkbox(
props: CheckboxVariantProps
): Record<CheckboxSlots, string> {
// props์ ๋ฐ๋ฅธ slot๋ณ, className ๋ฐํ
}
์ต์ข ์ ์ผ๋ก ์ด๋ ๊ฒ ๋ง๋ค์ด์ง ๊ธฐ๋ฅ๊ณผ ํํ ์ธํฐํ์ด์ค๋ฅผ ๋ค์ extends ํ๊ณ ํ์ํ ์ถ๊ฐ ํ๋กํผํฐ๋ฅผ ๋ฐ์์ ์ฒดํฌ๋ฐ์ค์ ์ปดํฌ๋ํธ ์ธํฐํ์ด์ค๋ฅผ ์์ฑํฉ๋๋ค.
export interface CheckboxBehaviorProps extends State, Context {
onSelectedChange: (isSelected: boolean) => void;
}
export interface CheckboxVariantProps {
size: "large" | "medium" | "small";
}
export interface CheckboxProps extends CheckboxBehaviorProps, Checkbox VariantProps {
label: string;
}
๊ทธ๋ฆฌ๊ณ ์๋์ ๊ฐ์ด ํฉ์ณ์ง ํ๋กํผํฐ๋ฅผ ํตํด ๊ธฐ๋ฅ์ Hooks๋ฅผ ํธ์ถํ๊ณ ํํ์ ํด๋์ค ๋ค์ ์์ฑ ํจ์๋ฅผ ๊ฐ๊ฐ ํธ์ถํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ return
๋ฌธ ์๋์ JSX๋ฅผ ์ดํด๋ณด๋ฉด, ๊ธฐ๋ฅ์ Hooks์์ ์ป์ด์จ API์ ํํ์์ ์ป์ด์จ ํด๋์ค ๋ค์๋ค์ ๊ฐ๊ฐ JSX์ ์คํ๋ ๋ํ๊ณ ํด๋์ค ๋ค์์ ๋ฐ์ธ๋ฉ ํด์ ๊ธฐ๋ฅ๊ณผ ํํ๋ฅผ ํฉ์ฑํฉ๋๋ค. ์ด ์ฝ๋๋ ๋งค์ฐ ๋จ์ํ๊ณ ๋ฐ๋ณต์ ์ด๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์๊ฐ Composable
ํจํค์ง๋ฅผ ์ฌ์ฉํด์ ๋ค์ ๊ตฌํํ๋๋ฐ ๋ถ๋ด์ด ์ ์ต๋๋ค.
const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
(props, ref) => {
const { label, size, ...otherProps} = props;
const api = useCheckbox(otherProps); // ๊ธฐ๋ฅ
const classNames = checkbox({ size }); // ํํ
return (
<div className={classNames.root} {...api.rootProps}>
<div className={classNames.control} {...api.controlProps}>
<div className={classNames.icon} />
<input ref={ref} type="checkbox" {...api.inputProps} />
</div>
</div>
<div className={classNames.label} {...api.labelProps}>
{label}
</div>
);
}
);
์ ๊ฐ ์ง๊ธ๊น์ง ์ค๋ช ํ ์ปดํฌ๋ํธ์ ๋ํ ์ ๊ทผ๊ณผ ๊ตฌํ์ ๋ชจ๋ ๊ฑฐ์ธ์ ์ด๊นจ ์์ ์์ ๋ฐ๋ผ๋ณด๋ฉฐ ์ป์ด์ง ๊ฒ๋ค์ ๋๋ค. ํนํ ์ด๋๋น ์คํํธ๋ผ, Zag.js, Class Variance Authority์ ์ํฅ์ ํฌ๊ฒ ๋ฐ์์ต๋๋ค. ํน์ ๋์์ธ ์์คํ ์ ๊ตฌ์ถํ๋ ค๋ ํ์ด๋ ๊น๊ฒ ์ดํดํ๋ ค๊ณ ํ๋ ๋ถ๋ค์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ดํด๋ณด๋ ๊ฒ์ ์ถ์ฒ๋๋ฆฝ๋๋ค.
๋ง์น๋ฉฐ
์ค๋ ๋ค๋ฃฌ ์ฃผ์ ๋ค์ ์ ๋ฆฌํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๋์์ธ ์์คํ ์ ๋ชฉํ ์ค์
- ๋์์ธ ํ ํฐ์ ์ ์์ ํ์ฉ
- ์ํ ๋ฏน ๋์์ธ์ด ํผ๋์ค๋ฌ์ด ์ด์
- ์ปดํฌ๋ํธ ๊ตฌ์ฑ ์์ ํด๋ถ
- ๋์์ด๋์ ๊ฐ๋ฐ์์ ์์ฌ์ํต ๋ฌธ์ ํด๊ฒฐ
- ์ปดํฌ๋ํธ์ ๊ตฌํ๊ณผ API ์ค๊ณ
์ด ๋ด์ฉ์ ๋ฐํ์ผ๋ก ์ ๊ฐ ๋ฐฐ์ด ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ์ด ๋ด์ฉ์ ์ ๊ฐ ์๋ก ๋์์ธ ์์คํ ์ ๋ง๋ค ๋ ๊ผญ ์ ๊ฒฝ ์ธ ๋ถ๋ถ์ด๊ธฐ ๋๋ฌธ์ ๊ธฐ์ตํด ์ฃผ์๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
- ๋์์ธ ์์คํ ์ ๋ชฉํ์ ๋ฒค์น๋งํน ๋์ ๋ช ํํ๊ฒ ์ค์ ํ๊ธฐ
- ๋์์ธ ์๋๋ฅผ ์ธ์ฝ๋ฉํ ๋ ์ฃ๋ถ๋ฅธ ์ถ์ํ ๊ฒฝ๊ณํ๊ธฐ
- ์ปดํฌ๋ํธ์ ๊ธฐ๋ฅ/ํํ๋ฅผ ๋ถ๋ฆฌํด์ ์ต์ ๋จ์ ์ ์ํ๊ธฐ
- ์ํ ์์ถ์ผ๋ก ์์ฌ์ํต์ ๊ฐ์ ํ๊ณ ์ํ ํญ๋ฐ ์ ๊ฑฐํ๊ธฐ
- ๊ด์ฌ์ฌ ๋ถ๋ฆฌ๋ฅผ ํตํ ์์ฌ์ํต์ ์ํ ์ฐธ์กฐ ์ ๊ฑฐํ๊ธฐ
- ์ ์ ๊ฐ ์ปดํฌ๋ํธ๋ฅผ ์ง์ ์กฐ๋ฆฝํ๊ธฐ ์ฌ์ด ํ๊ฒฝ ์ ๊ณตํ๊ธฐ
๊ถ๊ทน์ ์ผ๋ก ์ ๋ด์ฉ์ ๋ฐํ์ผ๋ก ์ผ๊ด์ฑ๊ณผ ์ ์ฐ์ฑ์ ๋์์ ๋ฌ์ฑํ๋ ๊ฒ์ด ์ ๊ฐ ์ง๊ธ๊น์ง ๋์์ธ ์์คํ ์ ๋ง๋ค๋ฉฐ ๋ฐฐ์ด ๊ฒ๋ค์ ๋๋ค. ์ด ๊ธ์ ํตํด์ ํ์ ์ ๊ฐ์ง๊ณ ํ๋ณตํ๊ฒ ๋์์ธ ์์คํ ์ ๋ง๋๋ ๊ฐ๋ฐ์๊ฐ ๋ ๋ง์์ง๊ธธ ๋ฐ๋ผ๋ฉฐ ๊ธ์ ๋ง์นฉ๋๋ค. ๊ฐ์ฌํฉ๋๋ค.