-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
๐จ refactor: ์จ๋ณด๋ฉ ํ์ด์ง ์ํ๊ด๋ฆฌ ๋ฆฌํฉํ ๋ง #96
Conversation
This reverts commit d441d7d.
๐ Storybook Preview ๋ณด๋ฌ๊ฐ๊ธฐ: https://65a6c73d536a3c43b7c5c9bb-saqtcazota.chromatic.com/ |
year: '' as unknown as number, | ||
month: '' as unknown as number, | ||
day: '' as unknown as number, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ด ๋ถ๋ถ์ react-hook-form์ ์ ์ด ์ปดํฌ๋ํธ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ๊ฒฝ์ฐ์๋ ๋ฐ๋์ defaultValue๊ฐ ๋ค์ด๊ฐ์ผ ํด์ ์์ฑํ ๋ถ๋ถ์ธ๋ฐ์,
submit ๋์์์์ ์ ํจ์ฑ ๊ฒ์ฌ ๋ก์ง์ zod ์คํค๋ง๋๋ก ๋์ํ๊ณ ์ถ์๋ฐ, ์ฌ์ฉ์๊ฐ Input์ ๋ดค์ ๋ ๊ธฐ๋ณธ ๊ฐ์ ๋น์ด์๋๋ก ํ๊ณ ์ถ์ด์ ์์ฑํ ๋ถ๋ถ์
๋๋ค.. (ํ์
์ด ์๋ number์ฌ์ผ ํ๋๋ฐ, 0์ผ๋ก ํ๋ฉด Input์ ๊ธฐ๋ณธ ๊ฐ 0์ด ๋ค์ด๊ฐ ์๋ ๋ฌธ์ )
์ด ๋ถ๋ถ์์ ๋๋ ๊ณ ๋ฏผ์ด defaultValue ๊ฐ์ ํ์ ์ zod ์คํค๋ง์๋ ๋ค๋ฅด๊ฒ ํ๊ณ ์ถ์๋ฐ ๋ฐฉ๋ฒ์ด ์์์ง? ๊ณ ๋ฏผ๋์์ด์
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3
๊ทธ๋ฐ ๊ณ ๋ฏผ์ด๋ผ๋ฉด ํ์
๋จ์ธ์ ํ์ฉํ์ง ์๋ ์กฐ๊ธ ๋ ์ข์ ํด๊ฒฐ์ฑ
์ด ์๊ฒ ๋ค์.
ํนํ as unknown์ TS๋ฅผ ์ฌ์ฉํ ๋๋ raw ๋ฐ์ดํฐ์ ํ์
ํ์
์ด ์ด๋ ค์ธ ๋ ์ ๋ง ์ตํ์ ์๋จ์ผ๋ก ์ฌ์ฉํ๋ ๊ทธ๋ฐ ํ
ํฌ๋์ด๋๊น์.
์ํ๋์ด ๊ฐ์ง ๋์ผํ ์ํฉ์ ๋ํด discussion์ด ์๋๋ฐ
useForm<{ price: number | string }, void, { price: number }>
์ ๋ค๋ฆญ ์ ๋์จ์ ํ์ฉํ๊ณ 3๋ฒ์งธ ์ธ์๋ฅผ ํตํด submit๋๋ ๊ฐ์ ๋ณํํ๋ ์์ด๋์ด๋ ์ข๋ค๊ณ ์๊ฐ์ด ๋ค์ด์.
์ ๋ ์ง์ ํธ๋ผ์ด ํ์ง ๋ชปํ์ง๋ง ์ด๊ฑฐ ํ๋ฒ ์ฐธ๊ณ ํด๋ณด์ธ์!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ํ.. ์ ๋ค๋ฆญ ์ธ์๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ด ์์๊ตฐ์.. ๋์ค์ปค์ ๋งํฌ๊น์ง.. ๊ฐ์ฌํฉ๋๋ค!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ใ ใ ์๋ฆฌ์๋ฆฌ,, ์ ์๋ฃจ์ ์ ์ ๋ค๋ฆญ ๋ง๊ณ ์ ๋์จ ํ์ ์๊ธฐ์๋ค์~~
onChange={async (e) => { | ||
e.target.value = clampValue( | ||
e.target.value, | ||
formLiteral.year.max, | ||
); | ||
field.onChange(e); | ||
trigger('birthday.year'); | ||
}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RHF์ onChange ์ฝ๋ฐฑ์ด ๋์ํ๊ธฐ ์ ์ ๋ฏธ๋ฆฌ intercept ๋์์ ๋ถ์ฌํ๊ธฐ ์ํด์(Input์์ ์ซ์๋ง ํํฐ๋งํ๋ ๋ก์ง) Controller๋ก ์ ์ด ์ปดํฌ๋ํธ ๋ฐฉ์์ ์ฌ์ฉํ์ต๋๋ค.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as unknwon as ๋ฅผ ์ฌ์ฉํ default value ๋ก์ง์ด ํด๊ฒฐ๋๋ค๋ฉด ์ด ๋ถ๋ถ๋ ์ถํ์ ๊ฐ์ ๋ ์ ์๊ฒ ๋ค์!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ ๋ดค์ต๋๋ค!
๋ฆฌ๋ทฐ ์์ฒญ ์ฃผ์
์ ๊ฐ์ฌํด์.
์ฝ๋ฉํธ ๋ฌ๋ฉด์๋ ๋ช
์พํ ๋ต๋ณ์ด ์๋ ๊ฒ ๊ฐ์ ๊ฐ์ธ์ ์ธ ์์ฌ์์ด ์๋๋ฐ
์๊ฒฌ์ ๊ฐ๋ณ๊ฒ ์ฐธ๊ณ ๋ง ํด์ฃผ์ธ์ ใ
ใ
์ ๊ฐ ๋ฐ๋์ ์ณ์ง๋ ์์์!!
๊ถ๊ธํ ์ ์ด ์๋ค๋ฉด ์ฌ๋๊ธ์ด๋ ์ฌ๋์ผ๋ก ํธํ๊ฒ ์ง๋ฌธ ์ฃผ์ธ์~!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๊ฒฐ๊ตญ์๋ react-hook-form ์ ์ฌ์ฉํ๋ ๋ฐฉํฅ์ผ๋ก ๊ตฌํํ๊ฒ ๋์๋๋ฐ, ์ฌ์ค HTML์ ์ ํต์ ์ธ input์ด ์๋ ์์๋ ์กด์ฌํด์ setValue๋ก imperativeํ๊ฒ ๊ฐ์ ๋ณ๊ฒฝํด์ผ ํ๊ธด ํ์ง๋ง, ์ฃผ ๊ด์ฌ์ฌ๊ฐ ์ฌ์ฉ์์ ์ ๋ ฅ์ ๋ฐ๋ ํผ์ ๊ฐ๊น๋ค๋ ์๊ฐ ๋๋ฌธ์ด์์ด์. (์ฌ์ฉ์ ์ ๋ ฅ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฑ ์๋ก์ด ์๊ตฌ์ฌํญ์ด ๋ค์ด์๋ ๋น ๋ฅด๊ฒ ๋์ํ ์ ์๋ค๊ณ ์๊ฐํด์?)
๋ค zustand๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ด๊ธฐ ์ํ๋ฅผ ๊ฐ์ ํ ํด๊ฒฐ์ฑ
์ด ๋ ์ ์์ง๋ง
์ง๊ธ์ฒ๋ผ form๋ง์ ์ ์ดํ๋ ํ์ฌ์ ํ๊ฒฝ์์๋ react-hook-form์ด ๋ ์ ํฉํ๋ค์.
(= hook form์ ๊ธฐ๋ฐ์ผ๋ก ๋ฆฌ๋ ๋๋ง์ ์ต์ ํ๋ฅผ ๊ณ ๋ฏผํ๋ ๋ฐฉํฅ์ด ๋ ์ ํฉํ๋ค)
๊ทธ๋์ react-hook-form์ผ๋ก ์ต์ข
๊ฒฐ์ ํ ๊ฒ์ ์ข์ ์ ํ์ด์์
๋ค๋ง input์ด ์๋ ์์๋ ์กด์ฌ
๊ฐ ์ ํํ ์ด๋ค ์ผ์ด์ค์ผ๊น ๊ถ๊ธํด์ง๋๋ฐ
ํ์ฌ์ ๋์์ธ ๊ฐ์ด๋๋ก ๋ดค์ ๋๋
์ ๊ณต๋๋ UI๋ง ๋ค๋ฅผ ๋ฟ, radio, checkbox์ ๊ฐ๋
์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์
๋์์ธ์์คํ
์์์ ์ถฉ๋ถํ 'input ํ๊ทธ'๋ฅผ ์ค์ฌ์ผ๋ก ๊ตฌํํ ์ ์๊ฒ ๋ค๋ ์๊ฐ์ ๋ค์์ด์!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๊ทธ๋ ๋ค๋ฉด, react-hook-form์ ๋ ๋๋ง ์ต์ ํ๊ฐ ๊ด๊ฑด์ธ๋ฐ,
์ง๊ธ ์ํ๋์ด ์ง๋ฉดํ ์ด์๋ react-hook-form์ ๋์
ํ๋ ๊ฐ๋ฐ์๋ค์ด ํ๋ฒ์ฏค์ ๊ฒช์์ ๋ณดํธ์ ์ด์๋ก ๋ณด์ฌ์ ์ถฉ๋ถํ ์๋ฃจ์
์ด ๋ง๊ฒ ๋ค๋ ์๊ฐ์ ๋ค์์ด์!
ํน์ useWatch
๋ฅผ ์ฌ์ฉํ์ฌ ํธ๋ฌ๋ธ ์ํ
ํด๋ณด์
จ์๊น์?
watch์ ์ ์ฒด ๋ ๋๋ง ๋จ์ ์ ๋ณด์ํ API ์ธ๋ฐ ์ฐธ๊ณ ๋ก ์ ๋ ์ค์ ์ฌ์ฉ ๊ฒฝํ์ด ์์ด์ ํ๋ต์ผ๋ก๋ ๋ชป ๋๋ฆฐ๋ค๋ ์ ๐ญ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tabs -> compound ํจํด
์ด ๊ฒฝ์ฐ์๋ Tabs.Root ์ปดํฌ๋ํธ์์ ์ฃผ์ ํ value ์ค์์ ํ๋๋ผ๋ ๋ณ๊ฒฝ๋๋ฉด ๋ชจ๋ ํ์ ํธ๋ฆฌ๊ฐ ๋ฆฌ๋ ๋๋ง๋๊ธฐ ๋๋ฌธ์.. ๋ ๋๋ง ์ต์ ํ๋ฅผ ์ด๋ค ๋ฐฉ์์ผ๋ก ํ๋ฉด ์ข์์ง? ๊ถ๊ธํด์!
Tabs ๊ฐ์ด atomic ๋ณด๋ค๋ molecule์ ๊ฐ๊น์ด ๋ณต์กํ ์ปดํฌ๋ํธ๋ ์ํ๋ ๋ง์๋๋ก Context API๋ฅผ ํตํด state๋ฅผ component scope๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ ํ ํฌ๋์ด์ฃ !
๋ค๋ง 'value ์ค์์ ํ๋๋ผ๋ ๋ณ๊ฒฝ๋๋ฉด ๋ชจ๋ ํ์ ํธ๋ฆฌ๊ฐ ๋ฆฌ๋ ๋๋ง๋๊ธฐ ๋๋ฌธ์' ๋ผ๋ ์ด์๊ฐ ์์ธํ ๊ถ๊ธํด์ ธ์.
๋ณดํธ์ ์ธ Tabs๋ผ๋ฉด ์ต์ด ๋ ๋๋ง๋ Tab label์ ๋ถ๋ณํ ๊ฒ์ด๊ณ ,
Tab์ ๋ณ๊ฒฝํ์ ๋ content๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋ ๊ฒ์ ๋ถ๊ฐํผํ ๋ ๋๋ง์ผํ
๋ฐ
๊ทธ ์ธ์ ๋ ๋๋ง ์ต์ ํ๋ฅผ ํ๋ค๋ฉด ์ด๋ ๋ถ๋ถ์ด ์์๊น์?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tabs.Root ์ปดํฌ๋ํธ๋ฅผ ์ ์ธํ๋ ๊ณณ๋ง๋ค ์๋ก์ด ์ํ๋ฅผ ๊ฐ๊ณ ํ์ ์์๋ค์๊ฒ ๋ฟ๋ ค์ค์ผ ํ๊ธฐ ๋๋ฌธ์ zustand๊ฐ์ ์ ์ญ ์คํ ์ด๋ฅผ ํ๋๋ง ์์ฑํ๋ ๋ฐฉ์์ผ๋ก๋ ์ด๋ ค์ธ ๊ฒ ๊ฐ๊ณ .. ์ด๋ฐ ๋ฐฉ์์ผ๋ก selector๋ฅผ ์ง์ํ๋ ์ธ๋ถ ์คํ ์ด๋ฅผ ref๋ก ๋ด์์ ๋ฟ๋ฆฌ๋ ๋ฐฉ์๋ ์ฃผ๋ก ์ฌ์ฉ๋ ๊น์..?
๋ณต์กํ ์๋น์ค์์ Tabs๋ฅผ ๋ฃจํธ์์ ์กฐ๊ฑด๋ถ ๋ ๋๋ง ํ๋ฉด
์คํ๋ ค ์กฐ๊ฑด ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๋ถํธํ๊ณ ์ฌ์ด๋ ์ดํํธ๊ฐ ํฌ๊ฒ ๋ผ์.
๊ทธ๋์ ์ ๋ ๊ฐ๋ณ ํ์ด์ง ๋จ์์ Tabs๋ฅผ ๋งค๋ฒ import ํ๋ ๋ฐฉ์์ ์ ํํ์ด์, store์ ๋ํ ๋์ฆ๋ ๋คํํ ์์์ด์.
(์ ๋ ๋ฃจํธ์์ ๊ด๋ฆฌํ๋ Toast, Popup, Header ๋ฑ์์ store๋ฅผ ์ฌ์ฉํ๊ณ ์์ฃ !)
ํน์ ํ์ฌ ์๋น์ค๋ Tabs๋ฅผ Root์์ ์ทจ๊ธํ๋์? ๊ทธ๋ ๋ค๋ฉด ์ ์ญ store์ ๋ํ ๋์ฆ๊ฐ ์์ ๊ฒ์ด๊ณ , ์ ๋ ์ด๋ฐ ui๋ฅผ ์ํ store๋ฅผ ๊ณผ๊ฐํ ๋ง๋ค์ด์. (์ด์ฐจํผ store๋ค์ ๋จ์ผ ์ฑ ์์ ๋ง๊ฒ ๋๋๋ฉด ํ์ผ์ ์ปค์ง ์ ๋ฐ์ ์์ง๋ง, ์ด๋ฅผ ํด๋ ๊ตฌ์กฐ๋ก ์ ์ ๋ฆฌํ๋ค๋ฉด ์ฌ์ฉ์ ๋ถํธํจ์ ํฌ๊ฒ ์์ผ๋ฏ๋ก)
+) ๋ค๋ง ์ ๋ root ๋จ์์ ui store๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ provider์ ๋์ฆ๊น์ง๋ ์์์ด์!
ref & provider๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํ ๋จ๊ณ ๋ ๊ณ ๋ฏผ์ด ๋๊ฒ ์ง๋ง, ์ ๊ฐ ์๊ฐํ๋ ๋์์ธ์์คํ
์ Tabs๋ store๊ฐ ๋ถํ์ํ ์ค๊ณ ๋ฐฉ์์ด ๋ ๋ณดํธ์ ์ด๋ผ ์๊ฐํด์, ์ด ๋ถ๋ถ์ ๋ํด ํฐ ๊ณ ๋ฏผ์ ์ ํด๋ดค๋ ๊ฒ ๊ฐ์์.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๋ง๋ฌด๋ฆฌ
์ ์ญ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ํ์ฉํ๋ ๊ฒ์ผ์ง ๊ถ๊ธํด์
์ ์ญ ์ํ๋ '์ฌ๋ฌ ํด๊ฒฐ์ฑ
์ ๊ณ ๋ฏผํ ๋ค ๊ทธ๋ผ์๋ ๋ถ๊ฐํผํ ๋ ๋์
'ํ๋ค๋ฉด ๋๋ถ๋ถ์ ์ข์ ๊ฒฐ์ ์ด๋๋ผ๊ตฌ์.
(๊ฐ์ธ์ ์ผ๋ก prop drilling์ ์ง์ํ๋ ์ฑํฅ์ด ์์ด์, ์ฌ๋งํ๋ฉด store๋ context๋ฅผ ์ฌ์ฉํ๋ ํธ!)
์๋ฒ ๊ด๋ จ ๋ก์ง์ Tanstack query๋ฅผ ํตํด ์ฒ ์ ํ ์๊ฒฉ์ผ๋ก ์ํ ๊ด๋ฆฌํ๋ ๊ฒ์ ์์ฆ ํธ๋ ๋์ ์ ํฉํด์.
form ๊ด๋ จ ๋ฐ์ดํฐ๋ react-hook-form + provider๋ฅผ ์ฌ์ฉํ ๊ฒ ๋ํ react-hook-form์ ์์ฒด ๊ธฐ๋ฅ์ ํ์ฉํ๊ธฐ ์ฉ์ดํ๊ณ , ์ ์ญ ์ํ๊ด๋ฆฌ์ ๋จ์ ์ ๋ณด์ํ ์ ์์ผ๋ฏ๋ก ์ข์ ์ ํ์ด์์.
Compound UI์์ context ์ฌ์ฉ ๋ํ ์ ํฉํด์. UI์ ์ ์ญ ์ํ๋ฅผ ๋์ ํ์ง ์์ผ๋ฉด, ์ํ ์์กด์ฑ์ด ์์ด์ ธ ๋์์ธ์์คํ ์ ์ฌ์ฌ์ฉ์ฑ์ ๊ทน๋ํ ํ ์ ์๊ฑฐ๋ ์.
๊ฒฐ๋ก ์ ์ผ๋ก ์ ์ญ ์ํ๊ด๋ฆฌ๋ฅผ ๋์ ํ๋ ๋๋ถ๋ถ์ ๊ณ ๋ฏผ์ ๋น์ฆ๋์ค ๋ก์ง์ ๊ฐ๋ฐํ๋ฉด์ ๋ง์ด ํ๊ฒ ๋์ฃ . ์ ์ผ์ด์ค๋ค์ฒ๋ผ ํน์ scope(form, ui)์์์ ์ํ ๊ด๋ฆฌ๋, ์๋ฒ์์ ์ํ ๊ด๋ฆฌ๋ ์ํ๋์ ์๊ฐ์ด ๋ ์ ํฉํ๋ฏ๋ก ์ถํ ์๋น์ค ๊ณ ๋ํ ํ๋ฉด์ ์ ์ญ ์ํ๋ค ๋ง๋ค๋ฉด ๋ ๊ฒ ๊ฐ์์.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๋์์ธ์์คํ ์์์ ์ถฉ๋ถํ 'input ํ๊ทธ'๋ฅผ ์ค์ฌ์ผ๋ก ๊ตฌํ
์.. UI๊ฐ ๋ฌ๋ผ์ Input์ด๋ผ๋ ์๊ฐ์ ๋ชปํ์๋๋ฐ
๋์์ ๊ด์ ์์ ์ถฉ๋ถํ input์ radio, checkbox๋ก๋ ๊ตฌํ์ด ๊ฐ๋ฅํ๊ฒ ๊ตฐ์ ๐
useWatch๋ฅผ ์ฌ์ฉํ์ฌ ํธ๋ฌ๋ธ ์ํ
useWatch์ watch์ ์ฐจ์ด์ ์ด ๋จ์ํ control ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ๋์ง์ ์ฐจ์ด์ธ์ค ์์๋๋ฐ..
๋ ๋๋ง ์ต์ ํ๋ผ๋ ์ค์ํ ํฌ์ธํธ์์ ์ฐจ์ด๊ฐ ์์๊ตฐ์!! ํ
์คํธ ํด๋ณด๋ ์ ๋๋ ๊ฒ ๊ฐ์ต๋๋ค ๊ฐ์ฌํฉ๋๋ค!!
Tab์ ๋ณ๊ฒฝํ์ ๋ content๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋ ๊ฒ์ ๋ถ๊ฐํผํ ๋ ๋๋ง
์ํ.. Tab์ด ๋ณ๊ฒฝ๋๋ฉด Tabs์ Content๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋ ๊ฒ์ด ๋ง๊ธฐ ๋๋ฌธ์ ์ต์ ํ๋ฅผ ๊ณ ๋ คํด๋ณผ ์ ์๋ ๋ถ๋ถ์ด ์๊ฒ ๊ตฐ์!!
์ฌ์ค ์์์ ์ ์ฌํ ์ํฉ์ด Funnel ์คํ
์ ์กฐ์ํ๋ ํธ๋ค๋ฌ (toNext, toPrev) ๋ฅผ ํ์ ํธ๋ฆฌ์ ๊ณต์ ํ๊ณ ์ถ์์ ๋ ์๋๋ฐ์..
๋น์ ๊ฒฐ๋ก ์ ์ฌ์ค ํธ๋ค๋ฌ ํจ์์ ๊ฐ์ด ์ต์ด ๋ง์ดํธ ์์ ์ดํ์๋ ๋ณ๊ฒฝ๋์ง ์๊ธฐ๋ ํ๊ณ , Provider๊ฐ ๊ฐ์ธ๊ณ ์๋ ์คํ ์์ญ์ด ๋ณํ๊ฐ ์ผ์ด๋๋ฉด ์ด์ฐจํผ ๋ค๋ฅธ ์คํ ์ ๋ณด์ฌ ์ค์ผ ํ๋ ๋ฑ Content๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋ ๊ฒ์ด ๋ง๊ธฐ ๋๋ฌธ์ ์์ ์ปดํฌ๋ํธ์ Provider์์ Context API๋ก ๋ฟ๋ ค์ฃผ๋ ๋ฐฉ์์ ์ ํํ์๋๋ฐ, ์ด ๊ณผ์ ์ ๋ ๋๋ง ์ต์ ํ๊ฐ ํ์ํ๋ ค๋ ์ถ์ ์๊ฐ์ ๋ง์ฐํ๊ฒ ๋ ์ค๋ฅธ ๊ณ ๋ฏผ์ด์์ต๋๋ค ๐
(์ง๊ธ์ ํธ๋ค๋ฌ๋ง ๊ณต์ ํ๊ณ ์๊ธฐ์ ๋ฌธ์ ๋ ๋ถ๋ถ์ ์์ง๋ง.. ๋ง์ฝ Compound Pattern์์ ๊ฐ์ด ์์ฃผ ๋ณ๊ฒฝ๋๋ state๋ฅผ Provider์์ ๋ฟ๋ ค์ค๋ค๋ฉด ๋ ๋๋ง ์ต์ ํ๊ฐ ํ์ํ ๊ฒฝ์ฐ์๋ ์ด๋ป๊ฒ ํด๊ฒฐํ ๊น? ํ๋ ๊ณ ๋ฏผ)
์๋ ์ํ ๊ด๋ฆฌ ๋ฐ ๋ ๋๋ง ์ต์ ํ์ ๋ํด์ ๋ง์ฐํ ๊ณ ๋ฏผ์ผ๋ก๋ง ๊ฐ์ง๊ณ ์์๋๋ฐ, ์ค๋ ๋ฆฌ๋ทฐ ํด์ฃผ์ ๋๋ถ์ ๋ ๋๋ง ์ต์ ํ๊ฐ ์ ๋ง ํ์ํ ๋ถ๋ถ์ผ์ง, ํน์ ์ํ๊ฐ ํน์ scope๋ฅผ ๊ฐ์ ธ์ผ ํ๋์ง ํน์ ์ฑ ์ ์ฒด์์ ํ๋๋ง ์กด์ฌํด๋ ๋๋์ง ๋ฑ์ ๋จผ์ ์๊ฐํด๋ณด๋ ๊ฒ๋ ์ข๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์์ด์!! ๊ฐ์ฌํฉ๋๋ค!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compound, Composition
์ ๊ฐ Compound ํจํด๊ณผ, Composition ์ปดํฌ๋ํธ์ ์ ์์์ ํท๊ฐ๋ฆฌ๋ ๋ถ๋ถ์ด ์๋๋ฐ์.. ๐
Compound ํจํด์ด Composition ์ปดํฌ๋ํธ๋ฅผ ํ์ฉํ๋ฉด์๋ ์ํ๋ฅผ ํ์ ํธ๋ฆฌ์ ๊ณต์ ํ๋ ๋ ์ข์ ์งํฉ์ ๊ฐ๋
์ผ๋ก ์ดํดํ๋ ๊ฒ์ด ๋ง์๊น์??
(Compound ํจํด์ ๊ตฌํํ๊ธฐ ์ํด์๋ Composition ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉ?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compound, composition
์ ๋ ์์ฑํ๊ณ ๋ณด๋๊น ์ ๊ฐ ์ ์ํ๋ ๋ ๋จ์ด์ ๊ฐ๋
์ด ์ํ๋๊ณผ ๋ค๋ฅธ ๊ฒ์ ์ธ์งํ์ด์.
์ด๊ฑฐ ์ง์ด์ฃผ์
์ ๋ ๊ฐ์ฌํด์~!
"Tabs ์ปดํฌ๋ํธ๊ฐ์ด, ์ฌํ์ฉ๋๊ธฐ ์ข์ ์ปดํฌ๋ํธ๋ฅผ Headless UI๋ก ๊ตฌ์ฑํ๋ค๊ณ ํ ๋ ์ํ๋ฅผ ์บก์ํํด์ ์ธ๋ถ๋ก ๋ค์ด๋ด์ง ์์ผ๋ฉด์๋ ํ์ ์ปดํฌ๋ํธ๊ฐ ์ด๋ฅผ ๋ฐ์์ ํ์ฉํ ์ ์๋๋ก Context API๋ก ์์กด์ฑ ์ฃผ์ ์ ํด์ฃผ๋ ๋ฐฉ์์ด ์์ฃผ ์ฌ์ฉ๋๋ค๊ณ ๋ค์๋๋ฐ์!"
์ฌ๊ธฐ์ '์ํ~ ์ปดํฌ๋ํธ ๋์์ธ ํจํด์ธ compound pattern์ context API๋ฅผ ํตํด ์ค๊ณ' ํ๋ค๋ ๋ง์ด๊ตฌ๋
๋ผ๊ณ ์๊ฐ ํ์๊ณ
const Page = () => {
return (
<Tabs.Root>
<Tabs.Item>์์ดํ
1์ Tabs.Root์ ์ํ๋ฅผ ์ฌ์ฉํ ์ ์์ด์</Tabs.Item>
<Tabs.Item>์์ดํ
2๋ Tabs.Root์ ์ํ๋ฅผ ์ฌ์ฉํ ์ ์์ด์</Tabs.Item>
</Tabs.Root>
);
}
๋ค์์ผ๋ก ์๋ ์ฝ๋๋ก? ๋ณด์ด๋ ์ด ์์๋ฅผ ๋ณด์์ ๋
'Tabs๋ ํ์ ์ปดํฌ๋ํธ๋ค์ ์กฐ๋ฆฝํด์ ๋ค์ํ ์ผ์ด์ค๋ฅผ ์ ์ํด์ผ ํ ๋์ฆ๊ฐ ์๋ UI๊ฐ ์๋ ๊ฒ ๊ฐ์
compound pattern + Context API๋ฅผ ์ฌ์ฉํ๊ธฐ์๋ ์ ํฉํ์ง ์๊ฒ ๊ตฐ" ์ด๋ผ๊ณ ์๊ฐํ๋ค์
composition์ ๋์์ธ ํจํด๋ณด๋ค๋ '์ปดํฌ๋ํธ๋ฅผ ํฉ์ฑํ๋ค'๋ ๋ ํฌ๊ด์ ์ธ ์๋ฏธ์ ๊ฐ๊น์์
์ฌ์ค children์ผ๋ก ReactNode๋ฅผ ๋ฐ๋ ๊ฒ์ด๋ compound pattern ๋ฑ์ ๋๊ฒ ๋ณด๋ฉด ๋ค composition์ด ์๋๊น ์๊ฐ์ด ๋ค์ด์.
์ ๋ฆฌํ์๋ฉด ์ ์๋๋
"Tabs๋ Context API๋ฅผ ํ์ฉํ compound pattern์ผ๋ก ๊ตฌํํ๊ธฐ์๋ ์ ์ด์ธ๋ฆฌ๋ UI๋ ์๋ ๊ฒ์ผ๋ก ๋ณด์ฌ, ๋จ์ํ property๋ฅผ ํตํด component composition ํ์ฌ๋ ๊ด์ฐฎ๊ฒ ๋ค" ๋ผ๋ ์๋ฏธ์์ต๋๋คใ ใ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compound ํจํด์ด Composition ์ปดํฌ๋ํธ๋ฅผ ํ์ฉํ๋ฉด์๋ ์ํ๋ฅผ ํ์ ํธ๋ฆฌ์ ๊ณต์ ํ๋ ๋ ์ข์ ์งํฉ์ ๊ฐ๋
ํ๋นํ์ฃ !
๋ค๋ง ์งํฉ์ผ๋ก ๋น์ ํ๊ธฐ์ ๋์ ์ฑ๊ฒฉ์ด ๋ค๋ฅผ ์ ์๋ค ์๊ฐํด์
compound pattern์ ์ปดํฌ๋ํธ ๋์์ธ ํจํด์ ๊ฐ๊น๊ณ
composition์ ๋์ ์๋ฏธ์ '์ปดํฌ๋ํธ๋ฅผ ํฉ์ฑํ๋ค'๋ผ๋ ํ๋์ ๋ฐฉ๋ฒ๋ก ์ผ๋ก ๊ตฌ๋ถํ๋ ๊ฒ๋ ์ข์๋ณด์ฌ์~!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ํ!! ์๋ฒฝํ ์ดํดํ์ต๋๋ค ๐
compound pattern์ ๋์์ธ ํจํด์ ์ผ์ข ์ด๊ณ , composition์ ๊ทธ๋ณด๋ค ํจ์ฌ ํฌ๊ด์ ์ธ ์๋ฏธ์ ๋ฐฉ๋ฒ๋ก ์ค ํ๋์ธ ๊ฒ์ด๊ตฐ์!!
Tabs์ ์์์ ๊ฒฝ์ฐ์๋ ํ์คํ ํ์ ์ปดํฌ๋ํธ๋ฅผ ์กฐํฉํด์ ์ํ๋ฅผ ๊ณต์ ํด์ผ ํ ์ผ์ด์ค๊ฐ ๋ค์ํ์ง ์๊ธฐ์ compound ํจํด์ ์ ์ฉํ๊ธฐ์๋ ์ ํฉํ์ง ์๊ฒ ๋ค์..
ํ์์ ํผ๋๋๋ ๊ฐ๋ ์ด์๋๋ฐ.. ์์ธํ๊ฒ ์ ๋ฆฌํด์ฃผ์ ๋๋ถ์ ๋ช ํํ๊ฒ ์ดํด๊ฐ ๋์์ด์! ์ ๋ง ๋๋ฌด๋๋ฌด ๊ฐ์ฌ๋๋ฆฝ๋๋ค!! ๐๐๐
year: '' as unknown as number, | ||
month: '' as unknown as number, | ||
day: '' as unknown as number, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3
๊ทธ๋ฐ ๊ณ ๋ฏผ์ด๋ผ๋ฉด ํ์
๋จ์ธ์ ํ์ฉํ์ง ์๋ ์กฐ๊ธ ๋ ์ข์ ํด๊ฒฐ์ฑ
์ด ์๊ฒ ๋ค์.
ํนํ as unknown์ TS๋ฅผ ์ฌ์ฉํ ๋๋ raw ๋ฐ์ดํฐ์ ํ์
ํ์
์ด ์ด๋ ค์ธ ๋ ์ ๋ง ์ตํ์ ์๋จ์ผ๋ก ์ฌ์ฉํ๋ ๊ทธ๋ฐ ํ
ํฌ๋์ด๋๊น์.
์ํ๋์ด ๊ฐ์ง ๋์ผํ ์ํฉ์ ๋ํด discussion์ด ์๋๋ฐ
useForm<{ price: number | string }, void, { price: number }>
์ ๋ค๋ฆญ ์ ๋์จ์ ํ์ฉํ๊ณ 3๋ฒ์งธ ์ธ์๋ฅผ ํตํด submit๋๋ ๊ฐ์ ๋ณํํ๋ ์์ด๋์ด๋ ์ข๋ค๊ณ ์๊ฐ์ด ๋ค์ด์.
์ ๋ ์ง์ ํธ๋ผ์ด ํ์ง ๋ชปํ์ง๋ง ์ด๊ฑฐ ํ๋ฒ ์ฐธ๊ณ ํด๋ณด์ธ์!
onChange={async (e) => { | ||
e.target.value = clampValue( | ||
e.target.value, | ||
formLiteral.year.max, | ||
); | ||
field.onChange(e); | ||
trigger('birthday.year'); | ||
}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as unknwon as ๋ฅผ ์ฌ์ฉํ default value ๋ก์ง์ด ํด๊ฒฐ๋๋ค๋ฉด ์ด ๋ถ๋ถ๋ ์ถํ์ ๊ฐ์ ๋ ์ ์๊ฒ ๋ค์!
src/utils/arrayUtils.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์์ํ ํจ์๋ค์ด util๋ก ์ ๋ถ๋ฆฌ๋์๊ณ
ํ
์คํธ ์ฝ๋๋ ์ ๊ฐ์ถฐ์ ธ ์์ด์
์ด๋ฐ ๋ถ๋ถ์ ๋ฆฌํฉํฐ๋ง์ ์ฐธ ์๋ฏธ ์๋ค์ ๐
seokzin ๋์ด ๋๋ฌด ์ข์ ๋ฆฌ๋ทฐ๋ฅผ ๋จ๊ฒจ์ฃผ์ จ๋ค์..! ๊ฐ์ฌํฉ๋๋ค ๐ ๋ณด๋ฉด์ ์ ๋ ๋ง์ด ์์๊ฐ๊ณ ๋ฐฐ์๊ฐ๋๋ค! |
๐งฉ ์ด์ ๋ฒํธ
โ ์์ ์ฌํญ
์คํ ํ๋ฉด
GOMCAM.20240212_0132560725.mp4
https://dnd-10th-4-frontend-ne5k21wv6-bbearcookie.vercel.app/onboarding Preview ์ฃผ์์์ ์คํ ํ์ธ ๊ฐ๋ฅํฉ๋๋ค!
#64 ์์ ์์ ํ๋ ๊ธฐ์กด ์จ๋ณด๋ฉ ํ์ด์ง์ ํผ ์ํ๋ ๊ฐ ์คํ ์์ ์ง์ญ ์ํ๋ก ๋ค๋ค์ง๊ณ , ๋ค์ ์คํ ์ผ๋ก ๋์ด๊ฐ๊ธฐ ์ ์ ๊ฐ๊ฐ API ํธ์ถ์ด ๋ฐ์ํ๊ณ ์์๋๋ฐ์. API ํธ์ถ์ด ๋ฐฉ์์ด ๋ง์ง๋ง ์๋ฃ ์คํ ์์ ํ ๋ฒ๋ง ์ผ์ด๋๋๋ก ๋ช ์ธ๊ฐ ๋ณ๊ฒฝ๋ ์์ ์ด๊ธฐ์ ์คํ ๊ฐ์ ํผ ๋ฐ์ดํฐ์ ์ํ ๊ณต์ ๊ฐ ํ์ํด์ก์ด์.
๊ทธ๋์ react-hook-form ์ผ๋ก ํผ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๊ณ , ์์์ FormProvider ์์ ๋ฟ๋ ค์ฃผ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ์ด์.
์ถ๊ฐ๋ก, ๋ง์ด ํ์ด์ง์์๋ ์จ๋ณด๋ฉ ํ์ด์ง์ ๋์ผํ ๋ก์ง์ด ์กด์ฌํ๋๋ฐ์. (์ฑ๋ณ ๋ณ๊ฒฝ, ์๋ ์์ผ ๋ณ๊ฒฝ ๋ฑ), ๊ทธ๋์ ์จ๋ณด๋ฉ ํ์ด์ง์ ์ปดํฌ๋ํธ์ ๊ฒฐํฉ๋์ด ์๋ ๋ก์ง์ ๋ถ๋ฆฌํ ํ์์ฑ์ ๋๊ผ์ด์. ์ฌ์ค ์ฒ์ ์์ฑํ ๋ ์ด๋ฐ ๋ก์ง์ด ๋น์ฆ๋์ค ๋ก์ง์ด๋ผ๊ณ ์๊ฐํ์๋๋ฐ, ๋๋ฉ์ธ ๋งฅ๋ฝ์ ์ ๊ฑฐํ๋ค๋ณด๋ ์๊ฐ๋ณด๋ค ์ ํธ์ฑ์ ๊ฐ๊น์ธ ์ ์๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์์ด์. ๊ทธ๋์ ๋๋ฉ์ธ ๋งฅ๋ฝ์ ์ต๋ํ ์ ๊ฑฐํด์ ์ฌํ์ฉ ๊ฐ๋ฅํ ์ ํธ ํจ์๋ก ๋ถ๋ฆฌํ์ด์.
๋ง์ด ํ์ด์ง ์ค๊ณ ํ๋ฉด
์ฃผ๋ก ์ํ ๊ด๋ฆฌ ๋ฐ ์ํ ๊ณต์ ์ ๋ํ ๊ณ ๋ฏผ์ด ๋ค์๋๋ฐ.. @seokzin ๋! ํน์ ์ฝ๋๋ฆฌ๋ทฐ๋ฅผ ์์ฒญ๋๋ ค๋ ๊ด์ฐฎ์๊น์??
๐ฉโ๐ป ๊ถ๊ธ ์ฌํญ
react-hook-form vs zustand
์คํ ๊ฐ ํผ ์ํ๋ฅผ ๊ณต์ ํด์ผ ํ๋๋ฐ.. ํ์ ์์ ์ด๋ฐ ์ํฉ์ ๋ณดํต ์ด๋ค ๋ฐฉ์์ ์ฑํํ์ค์ง ๊ถ๊ธํด์.
์ ๋ ๊ฐ ์คํ ์์ ์ง์ญ์ ์ผ๋ก ๋ค๋ค์ง๋ ํผ ๊ด๋ จ ์ํ๋ฅผ ์ด๋ป๊ฒ ์ ์ญ์ ์ผ๋ก ๊ด๋ฆฌํ ๊ฒ์ธ์ง๋ฅผ ๊ณ ๋ฏผํ๋๋ฐ์.. ์๊ฐํด ๋ณธ ๊ฒฐ๊ณผ 2๊ฐ์ง๋ก ์ถ๋ ค๋ณผ ์ ์์์ด์.
๊ฐ๊ฐ์ ์ ํํ์ ๋ ์ฅ๋จ์ ์ ๋ค์๊ณผ ๊ฐ๋ค๊ณ ์๊ฐํ๋๋ฐ์:
react-hook-form
zustand
๊ฒฐ๊ตญ์๋ react-hook-form ์ ์ฌ์ฉํ๋ ๋ฐฉํฅ์ผ๋ก ๊ตฌํํ๊ฒ ๋์๋๋ฐ, ์ฌ์ค HTML์ ์ ํต์ ์ธ input์ด ์๋ ์์๋ ์กด์ฌํด์ setValue๋ก imperativeํ๊ฒ ๊ฐ์ ๋ณ๊ฒฝํด์ผ ํ๊ธด ํ์ง๋ง, ์ฃผ ๊ด์ฌ์ฌ๊ฐ ์ฌ์ฉ์์ ์ ๋ ฅ์ ๋ฐ๋ ํผ์ ๊ฐ๊น๋ค๋ ์๊ฐ ๋๋ฌธ์ด์์ด์. (์ฌ์ฉ์ ์ ๋ ฅ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฑ ์๋ก์ด ์๊ตฌ์ฌํญ์ด ๋ค์ด์๋ ๋น ๋ฅด๊ฒ ๋์ํ ์ ์๋ค๊ณ ์๊ฐํด์?)
๊ทธ๋ฐ๋ฐ.. ๊ด์ฐฎ์ ์ ๊ทผ์ด์์์ง? ๋ ์ข์ ๋ฐฉ๋ฒ์ ์์์์ง? ๊ถ๊ธํด์
Compound ํจํด
Tabs ์ปดํฌ๋ํธ๊ฐ์ด, ์ฌํ์ฉ๋๊ธฐ ์ข์ ์ปดํฌ๋ํธ๋ฅผ Headless UI๋ก ๊ตฌ์ฑํ๋ค๊ณ ํ ๋ ์ํ๋ฅผ ์บก์ํํด์ ์ธ๋ถ๋ก ๋ค์ด๋ด์ง ์์ผ๋ฉด์๋ ํ์ ์ปดํฌ๋ํธ๊ฐ ์ด๋ฅผ ๋ฐ์์ ํ์ฉํ ์ ์๋๋ก Context API๋ก ์์กด์ฑ ์ฃผ์ ์ ํด์ฃผ๋ ๋ฐฉ์์ด ์์ฃผ ์ฌ์ฉ๋๋ค๊ณ ๋ค์๋๋ฐ์!
์ด ๊ฒฝ์ฐ์๋ Tabs.Root ์ปดํฌ๋ํธ์์ ์ฃผ์ ํ value ์ค์์ ํ๋๋ผ๋ ๋ณ๊ฒฝ๋๋ฉด ๋ชจ๋ ํ์ ํธ๋ฆฌ๊ฐ ๋ฆฌ๋ ๋๋ง๋๊ธฐ ๋๋ฌธ์.. ๋ ๋๋ง ์ต์ ํ๋ฅผ ์ด๋ค ๋ฐฉ์์ผ๋ก ํ๋ฉด ์ข์์ง? ๊ถ๊ธํด์!
(Tabs.Root ์ปดํฌ๋ํธ๋ฅผ ์ ์ธํ๋ ๊ณณ๋ง๋ค ์๋ก์ด ์ํ๋ฅผ ๊ฐ๊ณ ํ์ ์์๋ค์๊ฒ ๋ฟ๋ ค์ค์ผ ํ๊ธฐ ๋๋ฌธ์ zustand๊ฐ์ ์ ์ญ ์คํ ์ด๋ฅผ ํ๋๋ง ์์ฑํ๋ ๋ฐฉ์์ผ๋ก๋ ์ด๋ ค์ธ ๊ฒ ๊ฐ๊ณ .. Tabs.Root๊ฐ ์ํ๋ฅผ ๊ฐ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํด์ผ ํ ๊ฒ ๊ฐ์๋ฐ.. ํน์ https://docs.pmnd.rs/zustand/guides/initialize-state-with-props ์ด๋ฐ ๋ฐฉ์์ผ๋ก selector๋ฅผ ์ง์ํ๋ ์ธ๋ถ ์คํ ์ด๋ฅผ ref๋ก ๋ด์์ ๋ฟ๋ฆฌ๋ ๋ฐฉ์๋ ์ฃผ๋ก ์ฌ์ฉ๋ ๊น์..? ์ฌ์ฉํด๋ณด๋ ๋ณด์ผ๋ฌ ํ๋ ์ดํธ๊ฐ ์ปค์ง๋ ๋๋๋ ๋ฐ์์์ด์..)
๋ง๋ฌด๋ฆฌ
๊ฒฐ๋ก ์ ์ผ๋ก๋.. ์ ์ญ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ํ์ฉํ๋ ๊ฒ์ผ์ง ๊ถ๊ธํด์.
API ํต์ ์ผ๋ก ๊ฐ์ ธ์จ ๋ฐ์ดํฐ์๋
TanStack Query
๋ฅผ, ํผ ๋ฐ์ดํฐ์ ๋ํด์๋react-hook-form
์, Compound ํจํด์์ ์์กด์ฑ ์ฃผ์ ์๋Context API
๋ฅผ ์ฌ์ฉํ๋ค๋ณด๋.. ๋ ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ์ํ ๊ด๋ฆฌ ๋๊ตฌ๋ฅผ ํ์ฉํด๋ณด์ ์ถ์ด๋ ์ ๋ชปํ์๊ฑฐ๋ ์.. ๐๋ํ, ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ฆฌํค๋ ์ํ๋ฅผ ์ฌ๋ฌ ๊ณณ์ ๋ถ์ฐํด์ ๊ด๋ฆฌํ๋ ๋ฐฉ์์ ์ด๋จ์ง..? ๊ถ๊ธํด์.
(ex. ๋ก๊ทธ์ธํ ์ฌ์ฉ์ ์ ๋ณด๊ฐ TanStack Query์ ์ํด ๊ด๋ฆฌ๋๊ณ ์๋๋ฐ, ์ด ๊ฑธ Zustand์ ๊ฐ์ ๋ค๋ฅธ ์คํ ์ด์ ์ถ๊ฐ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ)
์ด๋ฐ ๋ฐฉ์์ด single source of truth์ ์๋ฐฐ๋๋ ๊ฑธ์ง, ์๋๋ฉด ๋๋ฆ๋๋ก ํธํ๊ฒ ์ฌ์ฉํ ์ ์๋ ์์๊ฐ ์์์ง ๊ถ๊ธํด์!!