โ ๏ธ ์ ์๊ถ ๋ณดํธ๋ฅผ ์ํด ์๋ฃ ๋ฐ ์์๊ฐ ๋์ฒด๋์์ต๋๋ค. ์์ ์ฝ๋๋ Reactโ๏ธ๋ก ์์ฑ๋์์ต๋๋ค.
๐ซจ ํต์ ์ฌ ๊ฐ์ ์ ํ๊ธฐ ์ํด์ ์๋์ ๊ฐ์ด ๊ธด ํผ๊ณผ ์ฝ์ ์ด ํฌํจ๋ ํ์ด์ง๋ฅผ ๋ง์ฃผ์น๊ฒ ๋ ๋๊ฐ ์๋ค.
์ด๋ ๊ฒ ๋ง์ ํ์ด์ง๋ค์ ๋๋๋๋ ํ๋ฆ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด ๋ญ๊น?
์ด๋ฒ๊ธ์์๋ ํ ์ค SLASH23์์ ๋ค๋ฃฌ ํผ๋์ ํตํ ๋ถ๊ธฐ์ ์ํ ๊ด๋ฆฌ์ ๋ํด ์ดํด๋ณด์.
์๋น์ค๋ฅผ ๊ฐ๋ฐํ ๋ ๋ํ์ ์ธ ํ๋ก ํธ์๋ ํจํด๋ค
1. ์์
๋ชฉ๋ก ํ์ด์ง -> ์์ธ ํ์ด์ง ๊ตฌ์กฐ๋ก ์ด๋ฃจ์ด์ ธ ์๊ณ , ๋ธ๋ก๊ทธ๋ ๋ด์ค, To-do ๋ฆฌ์คํธ๋ ์ด ์ ํ์ ํด๋น๋๋ค.
2. ๋จ์ผ ํ์ด์ง
ํ์ด์ง ์ด๋ ์์ด ํ ํ๋ฉด ๋ด์์ ์ํธ์์ฉํ ์ ์๊ณ , ์ง๋๋ ๋ฉ์ ์ ์ฑ์ด ์ด ์ ํ์ ํด๋น๋๋ค.
3. ์ค๋ฌธ์กฐ์ฌ
์ฌ๋ฌ ํ์ด์ง๋ค์ ํตํด ์ํ๋ฅผ ์์ง -> ๊ฒฐ๊ณผ ํ์ด์ง๋ก ์ด๋ฃจ์ด์ง ํํ, ํ์๊ฐ์ mbti ๊ฒ์ฌ, ๊ฒฐ์ ์ ์ฒญ์ ๋ฑ์ด ์ด ์ ํ์ ํด๋น๋๋ค. ์ค๋ ํต์ฌ์ ์ผ๋ก ๋ค๋ฃฐ ํจํด์ "์ค๋ฌธ์กฐ์ฌ ํจํด"์ด๊ณ , ํ ์ค์์๋ ์ด๋ฅผ 'ํผ๋(funnel)'ํจํด์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
funnel์ '๊น๋๊ธฐ'๋ฅผ ๋ปํ๋ค. ๊น๋๊ธฐ์ ๋ชจ๋๋ฅผ ๋ถ์ผ๋ฉด ๊ณ ์ ์ ์๋ ํต๊ณผํ๊ณ ๊ตต์ ์ ์๋ ํํฐ ๋๋ฏ์ด,
๋ค์ํ ์ ์ ๋ค์ด ์๋น์ค์ ์ฒ์ ๋ค์ด๊ฐ๋ฉด์๋ถํฐ ์ต์ข ๋ชฉํ์ ๋๋ฌํ๊ธฐ๊น์ง ์กฐ๊ธ์ฉ ํํฐ ๋๋ค.
ํผ๋ ํจํด ๊ตฌํ ๋ฐฉ์
๐ ํผ๋ ๊ตฌ์กฐ๋ก ํ์ด์ง๋ฅผ ๋์ด๊ฐ๋ฉด์ ์ ๋ณด๋ฅผ ์์งํ๋ ํ๋ฆ์ ์ ์ฌํ์ฌ SKT USIM ์จ๋ผ์ธ ๊ฐํตํ์ด์ง๋ฅผ ๊ฐ๋ตํํ ์์๋ก ๋์ฒดํ์ต๋๋ค.
์ ๋ฐ์ ์ธ ๋์์ธ ์๊ตฌ์ฌํญ ํ๋ฆ์ ๋ค์๊ณผ ๊ฐ๋ค.
๋จ๊ณ๋ณ๋ก ์ดํด๋ณด์๋ฉด,
์ ๊ท ๊ฐ์ ์ ์ ํํ๊ณ ๋ค์์ผ๋ก ์ง์ ํ๊ฒ ๋๋ฉด
1 ๋จ๊ณ : ํต์ ์ ํ์ ๋ํ ์ ๋ณด๋ฅผ stepSeq=1์์ ์์งํ๊ณ ,
2 ๋จ๊ณ : ์๊ธ์ ์ ํ์ ๋ํ ์ ๋ณด๋ฅผ stepSeq2 ๋จ๊ณ์์ ์์งํ๋ค.
3 ๋จ๊ณ : ์ ํํ ์๊ธ์ ์ ๋ฐ๋ผ ์ง๋ถํด์ผ ํ๋ ์๊ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๊ณ ,
4 ๋จ๊ณ : ์ ํํ ์๊ธ์ ์ ๋ฐ๋ฅธ ํํ ์ ํ ์ ๋ณด๋ฅผ stepSeq=4์์ ์์งํ๋ค.
5 ๋จ๊ณ: ์ ์ ์ ๊ฐ์ธ ์ ๋ณด๋ฅผ stepSeq=5์์ ์์งํ๊ณ ,
๊ฐ์ API๋ฅผ ํธ์ถํ์ฌ 1~5์์ ์์งํ ๋ฐ์ดํฐ (ํต์ ์ ํ/์๊ธ์ ์ ํ/ ํํ ์ ํ/ ๊ฐ์ธ ์ ๋ณด)๋ฅผ
๋๊ธฐ๋ฉด ๊ฐ์ ์๋ฃ๐ฅณ
๐ค ์ด๋ค ๋ฐฉ์์ผ๋ก ํด๋น ํ๋ฆ์ ๊ตฌํํ ์ ์์๊น?
๊ธฐ๋ณธ ๊ตฌ์กฐ๋ก ์ค๊ณ
๋จผ์ ํ์ด์ง ๋ณ๋ก ํ์ผ์ ๊ตฌ์ฑํด ๋ณด๋ ๋ฐฉ๋ฒ์ด ์๋ค.
๐๏ธ USIM ์ ๊ท ๊ฐ์ (/buyproc)
ใด ๐ ํต์ ์ ํ.tsx (/net-typ?stepSeq=1)
ใด ๐ ์๊ธ์ .tsx (/charge?stepSeq=2)
ใด ๐ ์๊ธํ์ธ.tsx (/condition?stepSeq=3)
ใด ๐ ํํ.tsx (/benf?stepSeq=4)
ใด ๐ ๊ฐ์ธ์ ๋ณด.tsx (/self-auth?stepSeq=5)
ใด ๐ ๊ฐ์ ์๋ฃ.tsx
๊ฐ ํ์ด์ง์ ํด๋น๋๋ ํ์ผ๋ค์ ๋ง๋ค๊ณ , router.push('/${๋ค์ํ์ด์ง ์ฃผ์}')๋ก ๋ค์ ํ์ด์ง๋ก ์ด๋์ํจ๋ค.
๊ฐ ํ์ด์ง์ ํ์ํ ์ํ๊ฐ ๋๋ ์ ธ ์๊ธฐ ๋๋ฌธ์ ์ ์ญ ์ํ const [registerData, updateRegisterData] = useGlobalState(registerData)๋ก ์ํ๋ฅผ ์ ์งํ ์ ์๋ค.
๋์๋ ์ ๋๋ ๊ด์ฐฎ์ ์ค๊ณ์ง๋ง, ์ ์ง๋ณด์์ ์ธก๋ฉด์์๋ ๊ฐ์ ํ ๋ถ๋ถ์ด ๋ณด์ธ๋ค.
( 1 ) ํ์ด์ง ํ๋ฆ์ด ์ง๊ด์ ์ด์ง ์๋ค.
- ํต์ ์ ํ.tsx, ์๊ธ์ .tsx, ์๊ธํ์ธ.tsx, ํํ.tsx, ๊ฐ์ธ์ ๋ณด.tsx, ๊ฐ์ ์๋ฃ.tsx ์ด ํ์ด์ง๋ค์ ํ๋ฆ์ ํ์ ํ๊ธฐ ์ํด์๋ router.push('/${๋ค์ํ์ด์ง ์ฃผ์}')์ ํ๊ณ ๊ฐ๋ฉด์ 5๊ฐ์ ํ์ด์ง๋ค์ ๋ค์ด๊ฐ์ ๋ด์ผ ํ์ ์ด ๊ฐ๋ฅํ๋ค.
(2) ์ํ๊ฐ ์ฌ๊ธฐ์ ๊ธฐ ํฉ์ด์ ธ ์์ด์ ๋๋ฒ๊น ์ด ์ด๋ ค์์ง๊ณ api์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ธฐ๊ฐ ๊น๋ค๋กญ๋ค.
- ๊ฐ์ ์ ์ํ ์ ๋ณด๋ค์ ์ ์ญ ์ํ๋ก ๊ฐ ํ์ด์ง์์ ์์งํ์ง๋ง, api ์ ์ก์ ์ํด ์ ์ญ์ํ์ ์ฌ์ฉ๋๋ ๊ณณ์ ๊ฐ์ธ์ ๋ณด.tsx๋ค.
- ๋๋ฒ๊น ์ ์ํด ๊ฐ์ธ์ ๋ณด.tsx ๋ฟ๋ง ์๋๋ผ ์ ์ฒด๋ฅผ ๋์์ผ๋ก ๋ฐ์ดํฐ ํ๋ฆ์ ์ถ์ ํด์ผ ํ๋ ๋ฌธ์ ๊ฐ ์๊ธด๋ค.
์ด๋ฐ ๋ฌธ์ ๋ค์ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์๊น?
ํผ๋ ํจํด ์ฝ๋ ๊ฐ์ ๋ฐฉ๋ฒ 3๊ฐ์ง
ํผ๋ ํจํด ์ฝ๋๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํ ์ ๊ทผ ๋ฐฉ๋ฒ์ผ๋ก๋ ๊ธฐ์ด์ ์ธ ๋ถ๋ถ์์ ๋จผ์ ์ดํด๋ณธ๋ค.
1. ์์ง๋
2. ์ถ์ํ
3. ์๊ฐํ
๐ฉ๐ป๐ง ๊ฐ์ ๋ฐฉํฅ 1: ์ฐ๊ด๋ ์ฝ๋๋ ๊ฐ๊น์ด ๊ณณ์ ๋ฐฐ์นํ์ฌ ํฉ์ด์ ธ ์๋ ์ํ์ ํ์ด์ง๋ค์ ํ ๊ณณ์ผ๋ก ๋ชจ์ผ๊ธฐ! โก๏ธ ์์ง๋ ๋์ด๊ธฐ
const [registerData, updateRegisterData] =useGlobalState(registerData) ์ง์ญ ์ํ ๋ง๋ค๊ณ , step ์ํ์ ๋ฐ๋ผ UI ์ปดํฌ๋ํธ๋ฅผ ์กฐ๊ฑด๋ถ ๋ ๋๋งํ๋ค.
๊ฐ ๋จ๊ณ์์ ๋ค์ ๋ฒํผ์ ํด๋ฆญํ๋ฉด step ์ํ๋ฅผ ์ํ๋ UI๋ก ์ ๋ฐ์ดํธํ์ฌ,
UI ์ธ๋ถ ์ฌํญ์ ํ์ ์ปดํฌ๋ํธ์์ ๊ด๋ฆฌํ๊ณ , step์ ์ด๋์ ์์์์ ๊ด๋ฆฌํ์ฌ ํ ๊ณณ์์ ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์๊ฒ ๋์๋ค.
api ํธ์ถ์ ํ์ํ ์ํ๋ ์์์์ ๊ด๋ฆฌํด์ฃผ๋ฌด๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ด ์ถ๊ฐํด ์ค ๊ฒฝ์ฐ, ์ด๋ค UI์์ ์ ๋ณด๊ฐ ์์ง๋๋์ง
ํ์ด์ง๋ฅผ ํ๊ณ ๊ฐ ํ์ ์์ด ๋ฐ๋ก ์ ์ ์๋ค.
๋๋ ๋ค์๊ณผ ๊ฐ์ด ๋ค๋ฅธ api๋ฅผ ์ถ๊ฐํ๋๋ผ๋ ์์ฝ๊ฒ ๋์ ์ด ๊ฐ๋ฅํ๋ค.
๐ฉ๐ป๐ง ๊ฐ์ ๋ฐฉํฅ 2: ๋ค๋ฅธ ํผ๋์์๋ ์ด ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ณ ์ถ๋ค โก๏ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ถ์ํํ๊ธฐ
const [registerData, updateRegisterData] = useState();
const [step, setStep] = useState<
| "ํต์ ์ ํ"
| "์๊ธ์ "
| "์๊ธํ์ธ"
| "ํํ"
| "๊ฐ์ธ์ ๋ณด"
| "ํํ์์ ์ฌ๋ถ"
| "๊ฐ์
์๋ฃ"
>("ํต์ ์ ํ"); // step ๊ด๋ จ ๋ก์ง
return (
<main>
// step ๊ด๋ จ ๋ก์ง๋ค
{step === "ํต์ ์ ํ" && <ํต์ ์ ํ onNext={(data) => setStep("์๊ธ์ ")} />}
{step === "์๊ธ์ " && <์๊ธ์ onNext={(data) => setStep("์๊ธํ์ธ")} />}
{step === "์๊ธํ์ธ" && <์๊ธํ์ธ onNext={(data) => setStep("ํํ")} />}
{step === "ํํ" && <ํํ onNext={(data) => setStep("๊ฐ์ธ์ ๋ณด")} />}
{step === "๊ฐ์ธ์ ๋ณด" && <๊ฐ์ธ์ ๋ณด onNext={() => setStep("ํํ์์ ์ฌ๋ถ")} />}
{step === "ํํ์์ ์ฌ๋ถ" && (
<ํํ์์ ์ฌ๋ถ
onNext={async () => {
await fetch("/api/register", { data });
setStep("๊ฐ์
์๋ฃ");
}}/>
)}
{step === "๊ฐ์
์๋ฃ" && <๊ฐ์
์๋ฃ />}
</main>
);
์์์ ์์ฑํ๋ ์ฝ๋์์ step์ ์กฐ๊ฑด์ ๋ฐ๋ผ์ ๋ ๋๋ง์ ํ๋ค๋ ๊ณตํต ๋ก์ง์ ์ถ์ํํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์๋ค.
// ์ฌ์ฉ
<Step if={step === "ํต์ ์ ํ"}>
<ํต์ ์ ํ onNext={() => setStep("์๊ธ์ ")}/>
</Step>
// ๊ตฌํ
function Step({ if, children }){
if(if === true){
return children
}
return null
}
๊ทธ๋ผ ์ ์ฒด ์ฝ๋๋ ์๋์ ๊ฐ์ด ๊ฐ์ ํ ์ ์๋ค.
const [registerData, updateRegisterData] = useState();
const [step, setStep] = useState<
| "ํต์ ์ ํ"
| "์๊ธ์ "
| "์๊ธํ์ธ"
| "ํํ"
| "๊ฐ์ธ์ ๋ณด"
| "ํํ์์ ์ฌ๋ถ"
| "๊ฐ์
์๋ฃ"
>("ํต์ ์ ํ");
return (
<main>
<Step if={step === "ํต์ ์ ํ"}>
<ํต์ ์ ํ onNext={(data) => setStep("์๊ธ์ ")} />
</Step>
<Step if={step === "์๊ธ์ "}>
<์๊ธ์ onNext={(data) => setStep("์๊ธํ์ธ")} />
</Step>
<Step if={step === "์๊ธํ์ธ"}>
<์๊ธํ์ธ onNext={(data) => setStep("ํํ")} />
</Step>
<Step if={step === "ํํ"}>
<ํํ onNext={(data) => setStep("๊ฐ์ธ์ ๋ณด")} />
</Step>
<Step if={step === "๊ฐ์ธ์ ๋ณด"}>
<๊ฐ์ธ์ ๋ณด onNext={() => setStep("ํํ์์ ์ฌ๋ถ")} />
</Step>
<Step if={step === "ํํ์์ ์ฌ๋ถ"}>
<ํํ์์ ์ฌ๋ถ
onNext={async () => {
await fetch("/api/register", { data });
setStep("๊ฐ์
์๋ฃ");
}}
/>
</Step>
<Step if={step === "๊ฐ์
์๋ฃ"}>
<๊ฐ์
์๋ฃ />
</Step>
</main>
);
๊ณตํต์ผ๋ก ๋ํ๋๋ if = {step === ""} ์กฐ๊ฑด๋ฌธ์ ์ ๊ฑฐํ๊ณ step์ ์ด๋ฆ์ ๋ฐ๋ผ ํ์ ์ปดํฌ๋ํธ์์ ๋ก์ง์ ์ฒ๋ฆฌํ๋๋ก name๋ง ๋จ๊ฒจ๋๊ณ ,
<Step name="ํต์ ์ ํ">
<ํต์ ์ ํ onNext={() => setStep("์๊ธ์ ")}/>
</Step>
step์ ์ํ๋ฅผ ๋ด์ ์ปค์คํ ํ ์ ๋ง๋ค์ด ์ค๋ค.
// ์ปค์คํ
ํ
function useFunnel(){
const [step, setStep] = useState(); // step ์ํ๋ฅผ ๋ด๋ถ๋ก ์ฎ๊น
const Step = (props) => {
return <>{props.children}</>
}
const Funnel = ({children}) => {
// name๊ณผ ํ์ฌ step์ด ๋์ผํ Step๋ง ๋ ๋๋ง
const targetStep = children.find(childStep => childStep.props.name === step);
return Object.assign(targetStep, {Step});
}
return [Funnel, setStep];
}
// ์ฌ์ฉ
const [Funnel, setStep] = useFunnel<"ํต์ ์ ํ"
| "์๊ธ์ "
| "์๊ธํ์ธ"
| "ํํ"
| "๊ฐ์ธ์ ๋ณด"
| "ํํ์์ ์ฌ๋ถ"
| "๊ฐ์
์๋ฃ"
>("ํต์ ์ ํ");
return (
<Funnel>
<Funnel.Step name="์๊ธ์ ">
<์๊ธ์ onNext={() => setStep("์๊ธํ์ธ")}/>
</Funnel.Step>
<Funnel.Step name="์๊ธํ์ธ">
<์๊ธํ์ธ onNext={() => setStep("ํํ")}/>
</Funnel.Step>
// ...
</Funnel>
)
useFunnel ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด์๋ https://www.slash.page/ko/libraries/react/use-funnel/README.i18n Slash ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฌธ์์ ๋ํด์ ๋ ์์ธํ ์ดํด๋ณผ ์ ์๋ค.
๐ฉ๐ป๐ง ๊ฐ์ ๋ฐฉํฅ 3: ๋ค๋ฅธ ํผ๋์์๋ ์ด ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ณ ์ถ๋ค โก๏ธ ์๊ฐํ
๊ด๋ จ ์๋ ์ฝ๋๋ฅผ ํ ๊ณณ์ผ๋ก ๋ชจ์ ์์ง๋๋ฅผ ๋์ด๊ณ , ๋ฐ๋ณต๋ ์ฝ๋๋ฅผ ์ถ์ํํด์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๋ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ๊ฐ์ ํด ๋ดค๋ค.
๋ง์ง๋ง์ผ๋ก ์ดํด๋ณผ ๊ฒ์ ์๊ฐํ๋ฅผ ํตํด ๊ฐ๋ฐ์์ ๊ฒฝํ(DX)์ ๊ฐ์ ํด ๋ณด๋ ๊ฒ์ด๋ค.
ํ์ด์ง๊ฐ์ ์ฎ๊ฒจ ๋ค๋๋ฉด์ ํ๋ฆ์ ํ์ ํ์ง ์์๋ ๋๋ ๋ฐฉํฅ์ผ๋ก ์ฝ๋๋ฅผ ๊ฐ์ ํ์ง๋ง, ๋ณด์๋ง์ ๊ณง๋ฐ๋ก ํ์ด์ง ํ๋ฆ์ ํ์ ํ๊ธฐ๋ ์ด๋ ต๋ค. ๊ฒฐ๊ตญ ์ ์ฒด ํ๋ฆ์ ์๊ณ ์ถ๋ค๋ฉด setStep์ ์ถ์ ํด ๊ฐ๋ฉด์ ๋ด์ผ ํ๋ค๋ ์ ์ด ์์ง๋ ๋จ์์๊ธฐ ๋๋ฌธ์ด๋ค.
์๋์ ๊ฐ์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ถ๊ธฐ๊ฐ ๋ ๋ฐ์ํ๊ฒ ๋๋ฉด ์ถ์ ํ๋๋ฐ ๋ ๋์ ํฌ๊ฒ ๋จ๊ณ ๋ด์ผํ๋ค ๐ (ํผ๋ก๋์ ์ ๋ค)
<Funnel>
<Funnel.Step name="์๊ธ์ ">
<์๊ธ์ onNext={() => {
if(clicked==='5G'){
setStep("5G์๊ธํ์ธ");
}else {
setStep("์ผ๋ฐ์๊ธํ์ธ");
}
}}/>
</Funnel.Step>
<Funnel.Step name="์ผ๋ฐ์๊ธํ์ธ">
<์ผ๋ฐ์๊ธํ์ธ on={() => setStep("5Gํํ")}/>
</Funnel.Step>
<Funnel.Step name="5G์๊ธํ์ธ">
<5G์๊ธํ์ธ on={() => setStep("์ผ๋ฐํํ")}/>
</Funnel.Step>
// ...
</Funnel>
์ด์ SKT USIM ์จ๋ผ์ธ ๊ฐํตํ์ด์ง ์์์ ์ดํด๋ดค๋ฏ์ด URL ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ ๊ฐ์ด ๋ณ๊ฒฝํด์ค์ผ ํ๋ ๋๋ฒ๊น ์ด ๊น๋ค๋ก์์ง๋ค.
ํ ์ค์์๋ ๊ฐ๋ฐ์๋ค์ด ํผ๋ ํ๋ฆ์ ์๊ฐํํ๋ ๊ฐ๋ฐ์ ๋๊ตฌ์ธ Funnel Debugger๋ฅผ ๋ง๋ค์๋ค.
useFunnel ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ฐ๋ฐ์ ๋๊ตฌ ์ต์ ์ ๋๊ธฐ๋ฉด ํ๋ฉด ์ฐ์ธก ํ๋จ์ ๋๊ทธ๋ ๋ฒํผ์ด ์๋ค.
์ด ๋ฒํผ์ ํด๋ฆญํ๋ฉด useFunnel์ ์๊ฐํํ ๋ค์ด์ด๊ทธ๋จ์ ๋ณผ ์ ์๋ค.
Funnel Debugger๋ฅผ ํ์ฉํ๋ฉด ๊ฐ๋ฐ/ ๋๋ฒ๊น ์๋๋ฅผ ๋์ผ ์ ์๊ณ ,
ํผ๋์ ์๋ํ ํ๋ฆ๋๋ก ๊ตฌํํ๋์ง ์ ๋ฐ์ดํธ๊ฐ ์ฆ๊ฐ์ ์ผ๋ก ๋ฐ์๋ผ์ ์ฒดํฌ๊ฐ ํธ๋ฆฌํ๋ค.
๋ํ ๊ฐ๋ฐ์์ ๋น๊ฐ๋ฐ์ ๋ชจ๋์๊ฒ ์ง๊ด์ ์ผ๋ก ํ์ด์ง ํ๋ฆ์ ๊ณต์ ํ ์ ์๋ค.
๊ทธ๋ผ Funnel Debugger๋ ์ด๋ป๊ฒ ๋ง๋ค์ด์ก์๊น?
๋ค์ด์ด๊ทธ๋จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ : Mermaid ๐งโ๏ธ
mermaid๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ค์ด์ด๊ทธ๋จ์ ๋ง๋ค์ด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.
mermaid์ ๋ฌธ๋ฒ์ผ๋ก ์์ฑํด ์ค ์ฝ๋๋ฅผ mermaid.render(id, text)๋ฅผ ํตํด ๋ ๋ ํ๋ฉด ์๋์ ๊ฐ์ ๊ทธ๋ํ๋ก ๋ง๋ค์ด์ค ์ ์๋ค.
์์์ ์ดํด๋ดค์๋ SKT USIM ์จ๋ผ์ธ ์ ๊ท๊ฐ์ ์ ์์๋ฅผ mermaid ๋ฌธ๋ฒ์ผ๋ก ๋ฐ๊พธ๊ณ
mermaid๋ก ํ๋ก์ฐ ๊ทธ๋ ค๋ณด์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๋ชจ์์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์ฆ, ๊ฐ ๋จ๊ณ๋ฅผ ๊ฐ์ ๋ฐฉ์[๊ฐ์ ๋ฐฉ์] -->|on์ ๊ท๊ฐ์ ํด๋ฆญ| ํต์ ์ ํ[ํต์ ์ ํ] ํํ๋ก ํ์ฑ ํด์ฃผ๋ฉด ๋๊ณ , ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์๋ค.
function getGraph(step: string, children: ReactElement[]) {
const result: string[] = ['graph TD'];
children.map(stepElement => {
const stepName = stepElement.props.name;
const children = stepElement.props.children;
const childrenProps = children?.props as [string, unknown];
Object.entries(childrenProps).map(el => {
const [functionName, value] = el;
if (typeof value === 'function') {
value.toString().match(/setStep\(.+\)/g)
?.map(matchedSetStep => {
const matchedStepName = matchedSetStep.match(/setStep\((?:'|")(.+)(?:'|")\)/)?.[1];
const graphNode =
`${stepName}[${stepName}] -->|${functionName}| ${matchedStepName}[${matchedStepName}]`;
result.push(graphNode);
});
}
});
});
return result.join('\n');
}
๐ค ๋ง์น๋ฉด์
funnel ํจํด์ผ๋ก ํ๋์ ๊ฑฐ๋ํ ํ์ด์ง์ ํผ ํ์์
์ฝ๋์ ์ผ๋ก ์์ง๋์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ณ (use-funnel), ์๊ฐํ (Funnel Debugger)ํ๋ ๋ฐฉ์์ ๋ํด ์ดํด๋ดค๋ค.
์์ฌ์ด ์ ์ useFunnel ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉ (์ด ๊ธ ์์ฑ์ผ ๊ธฐ์ค 2024.07.05)์ ํด๋ณด๋ ค๊ณ ํ์ง๋ง ์ด๋ ค์(?)์ด ์ข ์์๋ค.
์ผ๋จ react(next X)์์ useFunnel์ ์ฌ์ฉํด๋ณด๋ ค๊ณ ํ๋๋ฐ ์ผ๋จ next์์๋ง ์ฌ์ฉ๊ฐ๋ฅํ ๋ฏํ๋ค.
next์์ ์ฌ์ฉํด๋ณด๋ ค๊ณ ํ๋๋ฐ next/router๊ฐ next14๋ถํฐ๋ ๋ณธ๊ฒฉ์ ์ผ๋ก app ๋ผ์ฐํฐ๋ฅผ ์ฌ์ฉํ์ง๋ง ํจํค์ง๋ ์์ง
next12 ๊ธฐ์ค์ด๋ผ์ ๊ทธ๋ฐ์ง ๋ฒ์ ์ ๋ฎ์ถฐ์ ์ฌ์ฉํด์ผ ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์๋ ๋ฏํ๋ค.
์ด ๊ธฐํ์ ๋๋ง์ useFunnel์ ์๊ฐ์ด ๋๋ฉด ์กฐ๊ธ์ฉ ๊ตฌํํด ๋ณด๋ ๊ฒ๋ ์ฌ๋ฏธ์์ ๊ฑฐ ๊ฐ๋ค.
์ฝ๋๋ฅผ ๋ฆฌํฉํฐ๋ง ํ๋ ๋ฐฉ๋ฒ, ์ฝ๋๋ฟ๋ง ์๋๋ผ ๋ง๋๋ ์ฌ๋๋ค์ ๊ฒฝํ์ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ๋ค์ ๋ํด ์๊ฒ ๋์ด์ ์ข์๋ค. ๐
๐ References
https://www.youtube.com/watch?v=NwLWX2RNVcw
https://toss.tech/article/how-platform-designer-make-effectiveness
https://www.slash.page/libraries/react/use-funnel/readme.i18n/
'๐ฉ๐ปโ๐ป dev' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋์์ธ ์์คํ 101 : ๋์์ธ ์์คํ ์ด๋? (0) | 2024.07.11 |
---|---|
ํจํค์ง ๋งค๋์ ( ft. ํจํค์ง ๋งค๋์ ์ ๊ณผ๊ฑฐ, ํ ์ค์ ์ ํ, ๊ทธ๋ฆฌ๊ณ ๋ฏธ๋) (0) | 2024.07.08 |
๋ชจ๋ ์์คํ (0) | 2024.06.26 |
โ๏ธ Error boundary (0) | 2024.06.19 |
โ๏ธ <Suspense> ํ์ฉ (0) | 2024.06.16 |