NDD ํ๋ก์ ํธ์ FE์์๋ recoil์ ๋์ ํ๊ฒ ๋์์ต๋๋ค!!
NDD ํ๋ก์ ํธ์ FE์์๋ recoil์ ๋์ ํ๊ฒ ๋์์ต๋๋ค!! ์ ๋ ์ง๊ธ๊น์ง mobx์ redux๋ง์ ์ฌ์ฉํด ์๊ธฐ ๋๋ฌธ์, recoil์ ๋ํด์๋ ์๋กญ๊ฒ ํ์ต์ด ํ์ํ์ต๋๋ค. ๊ทธ์ ๋ฐ๋ผ (์ ๋ง ์ ๋ง) ๊ฐ๋ณ๊ฒ ํบ์๋ณด๋ ค ํฉ๋๋ค!
Recoil์ React ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ์ด๋ React์ ๊ธฐ๋ณธ์ ์ธ ์ํ๊ด๋ฆฌ ์์ญ์์ ํ์ฅ๋์ด, ํนํ ๋ณต์กํ๊ณ ๋๊ท๋ชจ์ ์๋น์ค์์์ ํจ์จ์ ์ธ ์ํ๊ด๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. Recoil์ Facebook์์ ๊ฐ๋ฐ๋์์ผ๋ฉฐ, React์ ๊ธฐ์กด ๊ฐ๋ ๊ณผ ์ ํตํฉ๋๋๋ก ์ค๊ณ๋์์ต๋๋ค!
๋ฐ๋ก ๊ณต์๋ฌธ์๋ฅผ ๋ค์ด๊ฐ ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค!
๋ค์ด๊ฐ์ ๋ง์ ํ๋จ์ ์ธ ์์๊ฐ ๋์ ๋๋๋ค!
๊ณต์๋ฌธ์ ํ์ ์ธ ์์๊ฐ ์๋ฌด๋๋ recoil์ ํ ๋ง๋ฅผ ๊ฒฐ์ ํ๋ ์ฃผ์ํ ๊ธฐ๋ฅ์ธ๋ฏํฉ๋๋ค. ์ด๋ฅผ ์ค์ฌ์ผ๋ก ํ์ตํ๋ฉฐ ๊ธฐ์กด์ ์ ๊ฐ ํ์ตํด์ค๋ mobx์ ๋น๊ตํ๋ฉด ์ข์๋ฏ ํฉ๋๋ค!
~~์ ๊ท์ฌ์ด ์ ๋๋ฉ์ด์ ์ด ๋ ์ค๋ฅด๋ ์ ๋ชฉ์ธ๋ฏํฉ๋๋ค...!~~
ํด๋น ์ ๋ชฉ์ ์ฃผ๋ ๋ด์ฉ์ ํฌ๊ฒ ๋๊ฐ์ง๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋จผ์ "์๊ณ "๋ผ๋ ๋ถ๋ถ์ recoil์ด ๊ฐ๋ณ๊ฒ ๋์ ํ ์ ์์ผ๋ฉฐ, ํฐ ๋ฌ๋ ์ปค๋ธ๋ฅผ ์ํ์ง ์์์ ์๋ฏธํ๋๋ฏ ํฉ๋๋ค. ๋๋ฒ์งธ๋ก "React์ค๋ฌ์ด" ์ด๋ผ๋ ๋ถ๋ถ์ ๋น์ฐํ Facebook์์ ๋ง๋ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค ๋ณด๋, ๊ทธ ์ฐ๊ฒฐ์ ๊ณค๊ณ ํ ํ๊ธฐ ์ํด ๋์ ๋์๋ค๊ณ ์๊ฐํ ์์๋๋ฐ ์๋ง๋ ์ด๋ฅผ ๊ฐ์กฐํ๋๋ฏ ํฉ๋๋ค.
Recoil์ React์ ์ฃผ์ ์ฒ ํ์ธ ์ ์ธ์ UI, ์ปดํฌ๋ํธ ์ค์ฌ์ ์ค๊ณ, ๊ทธ๋ฆฌ๊ณ ํ ์ค(Hooks)๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค. React์์ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํด ํ ์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ๋งค์ฐ ์ง๊ด์ ์ด๊ณ ๊ฐ๊ฒฐํฉ๋๋ค. Recoil๋ ์ด๋ฌํ ํจํด์ ๋ฐ๋ฆ ๋๋ค. ์๋๋ ์ ๋ง ๊ฐ๋จํ๊ฒ recoil์ ํตํ์ฌ ์ํ๊ด๋ฆฌ๋ฅผ ์งํํ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
import React from "react";
import { atom, useRecoilState } from "recoil";
// Atom ์ ์: ์ ์ญ ์ํ๋ฅผ ๋ํ๋ด๋ ๋จ์
const textState = atom({
key: "textState", // ๊ณ ์ ํ ํค
default: "", // ๊ธฐ๋ณธ๊ฐ
});
function TextInput() {
const [text, setText] = useRecoilState(textState); // ์ฌ์ค์ useState์ ๋์ผํ ์ญํ
const onChange = (event) => {
setText(event.target.value);
};
return <input type="text" value={text} onChange={onChange} />;
}
์ ์์์์ textState๋ ์ ์ญ์ ์ผ๋ก ๊ณต์ ๋๋ ์ํ(atom)์ด๋ฉฐ, TextInput ์ปดํฌ๋ํธ๋ ์ด ์ํ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ ๋๋งํ๊ณ ์ ๋ฐ์ดํธํฉ๋๋ค. ์ด ๊ณผ์ ์ React์ useState ํ ์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋งค์ฐ ์ ์ฌํ๋ฉฐ, Recoil์ ์ด๋ฌํ ์ผ๊ด์ฑ์ ํตํด React ๊ฐ๋ฐ์๋ค์๊ฒ ์น์ํ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
Recoil์ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํ ์ ๋ง ์ต์ํ์ API๋ง์ ์ ๊ณตํจ์ผ๋ก์จ ๋ฌ๋์ปค๋ธ๋ฅผ ๋ฎ์ถ๊ณ , ํจ์จ์ ์ธ ๊ฐ๋ฐ ๊ฒฝํ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
Recoil์ Selector๋ Atom์์์ ํ์ ์ํ๋ฅผ ์์ฑํ๊ธฐ ์ํ ๊ฐ๊ฒฐํ๊ณ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ React์ ์ปดํฌ๋ํธ ๋ ๋๋ง ์ต์ ํ์ ์ ์ฌํ ๊ฐ๋ ์ ์ํ ๊ด๋ฆฌ์ ์ ์ฉํฉ๋๋ค.
import { selector } from "recoil";
const charCountState = selector({
key: "charCountState",
get: ({ get }) => {
const text = get(textState);
return text.length;
},
});
function CharacterCount() {
const count = useRecoilValue(charCountState);
return <>Character Count: {count}</>;
}
์ ์์์์ charCountState๋ textState์ ๋ณ๊ฒฝ์ ์์กดํ๋ ํ์ ์ํ(selector)์ ๋๋ค. ์ด๋ ์์ ํจ์๋ก ์ ์๋๋ฉฐ, textState์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง ์ฌ๊ณ์ฐ๋ฉ๋๋ค. ์ด ๋ฐฉ์์ React์ ์ ์ธ์ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ๋ฐ๋ฅด๋ฉด์, ์ํ ๊ด๋ฆฌ์์๋ ๋ถํ์ํ ๊ณ์ฐ์ ์ต์ํํฉ๋๋ค.
"๋ฐ์ดํฐ ํ๋ฆ ๊ทธ๋ํ (Data-Flow Graph)"๋ ์๋น์ค์ ์ํ์ ๊ทธ ์ํ(state)์ ์์กดํ๋ ํ์ ๋ฐ์ดํฐ ๊ฐ์ ๊ด๊ณ๋ฅผ ๋ํ๋ ๋๋ค. ์ด๋ ๋ฐ์ดํฐ์ ํ๋ฆ๊ณผ ์ ๋ฐ์ดํธ๋ฅผ ๋ช ํํ๊ฒ ๊ด๋ฆฌํ๊ณ ๊ฐ์ํ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ฒ ํฉ๋๋ค.
๋ฐ์ดํฐ ํ๋ฆ ๊ทธ๋ํ๋ ์ํ(Atoms)์ ์ด ์ํ์ ์์กดํ๋ ํ์ ๋ฐ์ดํฐ(Selectors) ๊ฐ์ ๊ด๊ณ๋ฅผ ๋ํ๋ ๋๋ค. ๊ฐ Atom์ ๊ทธ๋ํ์ ๋ ธ๋๋ก, Selector๋ Atom ๋ ธ๋์ ์์กดํ๋ ๋ค๋ฅธ ๋ ธ๋๋ก ํํ๋ฉ๋๋ค. Atom์ ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด, ์ด ๋ณ๊ฒฝ์ ์์กดํ๋ ๋ชจ๋ Selector์ ์ ํ๋ฉ๋๋ค. Selector๋ Atom์ ์๋ก์ด ์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ ๊ณ์ฐ๋๋ฉฐ, ์ด๋ฅผ ํตํด ๊ด๋ จ๋ ์ปดํฌ๋ํธ๊ฐ ์ ๋ฐ์ดํธ๋ฉ๋๋ค. Selector๋ ํ์ํ ๋๋ง ์ฌ๊ณ์ฐ๋ฉ๋๋ค. Atom์ ์ํ๊ฐ ๋ณ๊ฒฝ๋์ด๋, ํด๋น Selector์ ์ํฅ์ ์ฃผ์ง ์๋ ๋ณ๊ฒฝ์ธ ๊ฒฝ์ฐ Selector๋ ์ฌ๊ณ์ฐ๋์ง ์์ต๋๋ค. ์ด๋ ๋ถํ์ํ ๊ณ์ฐ์ ๋ฐฉ์งํ๊ณ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค.
// atom ์ text์ ์ํ๋ฅผ ์๋ฏธํฉ๋๋ค.
const textState = atom({
key: "textState",
default: "",
});
// ์ด Atom์ ์ฌ์ฉ์๊ฐ ์
๋ ฅํ๋ ํ
์คํธ๋ฅผ ์ ์ฅํฉ๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ๋ฅผ ๋ํ๋ด๋ ๊ธฐ๋ณธ ๋จ์์
๋๋ค.
// selector๋ atom์ผ๋ก ๋ณ๊ฒฝ๋๋ ํ์ ๊ฐ์ ์๋ฏธํฉ๋๋ค.
const charCountState = selector({
key: "charCountState",
get: ({ get }) => {
const text = get(textState);
return text.length;
},
});
์ด Selector๋ textState Atom์ ์์กดํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ํ ์คํธ๋ฅผ ์ ๋ ฅํ ๋๋ง๋ค textState์ ์ํ๊ฐ ๋ณ๊ฒฝ๋๊ณ , charCountState๋ ์ด ๋ณ๊ฒฝ์ ๊ฐ์งํ์ฌ ๋ฌธ์ ์๋ฅผ ๋ค์ ๊ณ์ฐํฉ๋๋ค.
์ปดํฌ๋ํธ์์์ ์ํธ์์ฉ
function TextInput() {
const [text, setText] = useRecoilState(textState);
// ... ์
๋ ฅ ์ฒ๋ฆฌ ๋ก์ง
return <InputArea value={text} onChange(setText)>
} // ์ฌ๊ธฐ์ TextInput์ text๋ฅผ ๊ตฌ๋
ํฉ๋๋ค. ๊ตฌ๋
์ ๋ํ ๋ด์ฉ์ ์๋ ํ์ ํฉ๋๋ค.
function CharacterCount() {
const count = useRecoilValue(charCountState);
// ... ๋ฌธ์ ์ ํ์ ๋ก์ง
return <div>{count}</div>
}
TextInput ์ปดํฌ๋ํธ๋ textState๋ฅผ ์ ๋ฐ์ดํธํ๊ณ , CharacterCount ์ปดํฌ๋ํธ๋ charCountState๋ฅผ ์ฌ์ฉํ์ฌ ๊ณ์ฐ๋ ๋ฌธ์ ์๋ฅผ ํ์ํฉ๋๋ค. ์ด๋ Recoil์ด ๋ฐ์ดํฐ ํ๋ฆ์ ์ด๋ป๊ฒ ๊ด๋ฆฌํ๋์ง ๋ณด์ฌ์ค๋๋ค.
Recoil์์์ "๊ตฌ๋ (subscription)"์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ(atom) ๋๋ ํ์ ๋ฐ์ดํฐ(selector)์ ๋ณ๊ฒฝ์ ๊ฐ์งํ๊ณ , ์ด๋ฌํ ๋ณ๊ฒฝ์ ๋ฐ์ํ๋ ๊ฐ๋ ์ ๋งํฉ๋๋ค. Recoil์ ํต์ฌ ๊ธฐ๋ฅ ์ค ํ๋๋ ์ํ์ ๋ณ๊ฒฝ์ ๊ตฌ๋ ํ๋ ์ปดํฌ๋ํธ์๊ฒ ํจ์จ์ ์ผ๋ก ์๋ฆฌ๋ ๊ฒ์ ๋๋ค. ์ด ๊ตฌ๋ ๋ฉ์ปค๋์ฆ์ React์ ์ปดํฌ๋ํธ ๋ ๋๋ง ์ต์ ํ์ ์ํธ ์์ฉํฉ๋๋ค.
Recoil์์ atom ๋๋ selector์ ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด, Recoil์ ์ด ์ํ๋ฅผ ๊ตฌ๋ ํ๊ณ ์๋ ๋ชจ๋ ์ปดํฌ๋ํธ์๊ฒ ์๋ฆฝ๋๋ค. ์ํ๋ฅผ ๊ตฌ๋ ํ๋ ์ปดํฌ๋ํธ๋ ์ํ์ ๋ณ๊ฒฝ์ ๊ฐ์งํ๊ณ , ์ด์ ๋ฐ๋ผ ReRendering๋ฉ๋๋ค. ์ด๋ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค UI๊ฐ ์ต์ ์ํ๋ฅผ ๋ฐ์ํ๋๋ก ๋ณด์ฅํฉ๋๋ค. Recoil์ ํ์ํ ์ปดํฌ๋ํธ๋ง ์ ๋ฐ์ดํธ๋๋๋ก ์ต์ ํํ์ฌ, ๋ถํ์ํ Rendering์ ๋ฐฉ์งํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํน์ atom์ ๋ํ ๋ณ๊ฒฝ์ด ์ผ๋ถ ์ปดํฌ๋ํธ์๋ง ์ํฅ์ ๋ฏธ์น๋ค๋ฉด, Recoil์ ํด๋น ์ปดํฌ๋ํธ๋ง์ ReRenderingํฉ๋๋ค.
function TextInput() {
// textState atom์ ๊ตฌ๋
ํ๊ณ , ์ํ ๋ณ๊ฒฝ ์ ์ฌ๋ ๋๋ง๋ฉ๋๋ค.
const [text, setText] = useRecoilState(textState);
// ... ์ปดํฌ๋ํธ ๋ก์ง
}
์ ์ฝ๋์์ TextInput์ textState๋ฅผ ๊ตฌ๋ ํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์ธํฐํ์ด์ค๋ฅผ ํตํด textState๋ฅผ ๋ณ๊ฒฝํ๋ฉด, TextInput๋ ์๋ก์ด text ๊ฐ์ผ๋ก ์ฌ๋ ๋๋ง๋ฉ๋๋ค.
Recoil์์์ ๊ตฌ๋ ๊ฐ๋ ์ ์ํ ๊ด๋ฆฌ์ ํต์ฌ์ผ๋ก, ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋ ํ์ํ ๋ถ๋ถ๋ง์ ํจ์จ์ ์ผ๋ก ์ ๋ฐ์ดํธํ๋ ๋ฐ ์ค์ํ ์ญํ ์ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ๊ฐ๋ฐ์๋ ์ํ ๋ณํ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋ฐ์ํ๋ ๋ฐ์ํ UI๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
useRecoilState ํ ์ Recoil์ atom์ ์ ์ฅ๋ ์ํ๋ฅผ ์ฝ๊ณ ์ฐ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ React์ useState ํ ๊ณผ ์ ์ฌํ API๋ฅผ ๊ฐ์ง๋๋ค.
import { atom, useRecoilState } from "recoil";
// Atom ์ ์
const textState = atom({
key: "textState", // ๊ณ ์ ํ ํค
default: "", // ์ด๊ธฐ๊ฐ
});
function TextInput() {
const [text, setText] = useRecoilState(textState);
const onChange = (event) => {
setText(event.target.value);
};
return <input type="text" value={text} onChange={onChange} />;
}
useRecoilValue ํ ์ Recoil์ atom ๋๋ selector์ ๊ฐ์ ์ฝ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ํ ์ ์ํ๋ฅผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ์ฌ์ฉํ ๋ ์ ์ฉํฉ๋๋ค.
import { useRecoilValue } from "recoil";
function TextDisplay() {
const text = useRecoilValue(textState);
return <div>{text}</div>;
}
useSetRecoilState ํ ์ Recoil ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ ํจ์๋ง์ ์ ๊ณตํฉ๋๋ค. ์ด ํ ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ง๋ง, ํ์ฌ ์ํ ๊ฐ์ ์ฝ์ ์๋ ์์ต๋๋ค.
import { useSetRecoilState } from "recoil";
function TextUpdater() {
const setText = useSetRecoilState(textState);
const onClick = () => {
setText("Hello, Recoil!");
};
return <button onClick={onClick}>Update Text</button>;
}
useResetRecoilState ํ ์ Recoil์ atom ์ํ๋ฅผ ์ด๊ธฐ๊ฐ์ผ๋ก ์ฌ์ค์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
import { useResetRecoilState } from "recoil";
function ResetButton() {
const resetText = useResetRecoilState(textState);
return <button onClick={resetText}>Reset</button>;
}
useRecoilValueLoadable ํ ์ ๋น๋๊ธฐ selector์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ํ ์ ๋ฐ์ดํฐ์ ๋ก๋ฉ, ์๋ฌ, ์๋ฃ ์ํ๋ฅผ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ค๋๋ค.
import { selector, useRecoilValueLoadable } from "recoil";
// ๋น๋๊ธฐ Selector ์ ์
const asyncDataState = selector({
key: "asyncDataState",
get: async () => {
const response = await fetch("https://api.example.com/data");
return response.json();
},
});
function AsyncDataComponent() {
const loadable = useRecoilValueLoadable(asyncDataState);
switch (loadable.state) {
case "hasValue":
return <div>{loadable.contents}</div>;
case "loading":
return <div>Loading...</div>;
case "hasError":
return <div>Error: {loadable.contents.message}</div>;
}
}
"๊ต์ฐจํ๋ ์ฑ ๊ด์ฐฐ (Cross-App Observation)"์ Recoil์์ ์ ๊ณตํ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ์ผ๋ก ๊ธฐ๋ณธ์ ์ผ๋ก ์๋น์ค ๋ด๋ถ์ ์์ธํ ์ํ๋ณํ๋ฅผ ์ฒดํฌํด ๊ฐ๋ฉฐ ๋ชจ๋ ํ์ธํ ์ ์๋ ๊ด์ฐฐ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๋ฏํฉ๋๋ค.
Recoil์ ์ฌ์ฉํ๋ฉด, ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ชจ๋ ์ํ ๋ณํ๋ฅผ ์ค์๊ฐ์ผ๋ก ๊ด์ฐฐํ ์ ์์ต๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ชจ๋ ๋ถ๋ถ์์ ์ผ์ด๋๋ ์ํ ๋ณํ๋ฅผ ์ ํํ ํ์ ํ๊ณ , ํ์ํ ๋ฐ์์ ์ทจํ ์ ์๊ฒ ํด์ค๋๋ค. ์ํ ๋ณํ๋ฅผ ๊ด์ฐฐํจ์ผ๋ก์จ ๊ฐ๋ฐ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ง์์ฑ์ ๊ด๋ฆฌํ๊ฑฐ๋, ๋ผ์ฐํ ๋ก์ง์ ๊ตฌํํ๊ฑฐ๋, ๋ณต์กํ ๋๋ฒ๊น ๊ธฐ๋ฅ(์: ์๊ฐ ์ฌํ ๋๋ฒ๊น )์ ์์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
useRecoilTransactionObserver_UNSTABLE(({ snapshot }) => {
snapshot.getNodes_UNSTABLE({ isModified: true }).forEach((modifiedNode) => {
const atomLoadable = snapshot.getLoadable(modifiedNode);
if (atomLoadable.state === "hasValue") {
console.log(
`Atom ${modifiedNode.key}์ ์๋ก์ด ๊ฐ: `,
atomLoadable.contents
);
}
});
});
์ ์ฝ๋ ์์์์๋ recoil์์ ์ ๊ณตํ๋ hooks์ ๋๋ค. ์ด๋ Recoil์ ์ํ ๋ณํ๋ฅผ ์ค์๊ฐ์ผ๋ก ๊ฐ์งํ๊ณ , ์ฝ์์ ๋ก๊น ํ๋ ๋ฐฉ์์ ๋ณด์ฌ์ค๋๋ค. ์ด์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ๋ณํ๋ฅผ ๊ด์ฐฐํ๊ณ , ํ์ํ ๋ก์ง์ ๊ตฌํํ ์ ์์ต๋๋ค.
์ ๋ง ๊ฐ๋จํ๊ฒ Recoil์ ๋ํด์ ์ดํด๋ณด์์ต๋๋ค. ๊ฐ๋จํ๊ฒ ์ฐพ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ๊ทธ ์์ ๋ด๋ถ์ ์ธ ๋์์ด๋ ์ฅ๋จ์ ๋ํด์ ๋ชจ๋ ์ดํดํ์ง ๋ชปํ์ ์ด ๋ค์ ์์ฝ์ต๋๋ค๋ง, ์ฐ์ ์ ๋น์ฅ ํ๋ก์ ํธ์์ ์ฌ์ฉ๊ฐ๋ฅํ ์ํ๋ก ์ง์ ํ๋๊ฒ์ด ์ฐ์ ์ด๊ธฐ ๋๋ฌธ์ ๋ถ๊ฐํผํ๊ฒ ์ฌ๊ธฐ์ ํ์ต์ ์ ์ ๋ง๋ฌด๋ฆฌํ๋๊ฒ์ด ์ณ๋ค๊ณ ํ๋จํ์ต๋๋ค.
๊ฐ๋จํ๊ฒ ํ๋ก์ ํธ์์ ์ฌ์ฉํด๋ณด๋, ์๊ฐ์์ ์ธ๊ธํ๊ฒ๊ณผ ๊ฐ์ด ์ ๋ง ๊ฐ๋จํ๊ฒ react ํ๋ก์ ํธ์์ ์ฌ์ฉํ ์ ์๋๋ฏํฉ๋๋ค. ๋ํ Mobx์์์ ๋ค๋ฅด๊ฒ ๊ฐ์ฒด ์งํฅ์ ์ธ ๋๋๋ณด๋ค๋ react ์ ์ด์ธ๋ฆฌ๋๋ก ํจ์ํ๊ณผ hooks๋ฅผ ํตํ ๊ธฐ๋ฅ ๋ถ๋ฆฌ๋ฅผ ์งํฅํ๋๋ฏ ํฉ๋๋ค.
ํด๋น PR์์ ์ฝ๋๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.