Recent Posts
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
관리 메뉴

개발자 박가나

[241202 TIL] 본캠프 44일차 (Funnel 패턴) 본문

내일배움캠프

[241202 TIL] 본캠프 44일차 (Funnel 패턴)

gnchoco97 2024. 12. 2. 20:27

Funnel 패턴

Funnel은 깔대기를 의미한다. 즉, Funnel 패턴은 마치 깔대기 모양처럼 사용자가 단계를 거치면서 정보를 입력하는 UI 설계 방식을 말한다.

 

사용자가 여러 정보를 입력할 때, 모든 것을 한 번에 입력하는 것이 아니라 단계를 나눠서 하나씩 처리하기 때문에 깔대기처럼 점점 좁아지는 형식처럼 보인다.

 

기존 방식

각 단계별로 별도의 컴포넌트를 만들고 전역 상태를 사용해서 데이터를 관리한다. 페이지 간의 이동은 라우터로 처리하고, 최종 단계에서 모든 데이터를 수집해서 API를 호출한다.

  • 각 단계가 별도의 파일이나 컴포넌트로 분산되어 있어 흐름 파악이 어려움
  • 상태 변경이 여러 컴포넌트에서 이루어지기 때문에 데이터 흐름을 추적하기 어려움
  • 코드 수정 시 여러 파일을 수정해야하기 때문에 유지보수가 어려움
  • 라우터에 강하게 의존
import { useState } from 'react';
import { BrowserRouter as Router, Route, Switch, useHistory } from 'react-router-dom';

function Registration() {
  const [userData, setUserData] = useState({});
  const history = useHistory();

  return (
    <Router>
      <Switch>
        <Route path="/step1">
          <Step1
            onNext={(data) => {
              setUserData({ ...userData, ...data });
              history.push('/step2');
            }}
          />
        </Route>
        <Route path="/step2">
          <Step2
            onNext={(data) => {
              setUserData({ ...userData, ...data });
              history.push('/step3');
            }}
          />
        </Route>
        <Route path="/final">
          <FinalStep onSubmit={() => apiCall(userData)} />
        </Route>
      </Switch>
    </Router>
  );
}

 

 

Funnel 패턴 방식

Funnel 패턴을 적용하여 상태 관리와 페이지 흐름을 하나의 컴포넌트에서 관리함으로써 기존 방식의 문제점을 해결할 수 있다.

  • 상태 관리와 페이지 흐름을 하나의 컴포넌트에서 처리해서 코드가 간결해짐
  • 모든 상태 변경이 한 곳에서 이루어지므로 데이터 흐름 추적이 쉬움
  • 코드 수정이 쉬움
  • 라우팅 없이도 단계 전환 가능
import { useState } from 'react';

function Registration() {
  const [userData, setUserData] = useState({});
  const [step, setStep] = useState('가입방식');

  const handleNext = (data, nextStep) => {
    setUserData((prev) => ({ ...prev, ...data }));
    setStep(nextStep);
  };

  return (
    <div>
      {step === '가입방식' && (
        <SignUpMethod onNext={(data) => handleNext(data, '주민번호')} />
      )}
      {step === '주민번호' && (
        <ResidentNumber onNext={(data) => handleNext(data, '주소입력')} />
      )}
      {step === '주소입력' && (
        <AddressInput onNext={(data) => handleNext(data, '가입성공')} />
      )}
      {step === '가입성공' && <SuccessPage userData={userData} />}
    </div>
  );
}

 

 

useFunnel 생성

상태 관리와 페이지 전환 로직을 캡슐화하기 위해서 Custom Hook을 생성해서 사용한다.

import { useState } from 'react';

function useFunnel(initialStep) {
  const [currentStep, setCurrentStep] = useState(initialStep);

  const Step = ({ name, children }) => {
    return <>{children}</>;
  };

  const Funnel = ({ children }) => {
    const steps = React.Children.toArray(children).filter(
      (child) => child.type === Step
    );

    const activeStep = steps.find(
      (child) => child.props.name === currentStep
    );

    return activeStep || null;
  };

  const next = (nextStep) => {
    setCurrentStep(nextStep);
  };

  const prev = (prevStep) => {
    setCurrentStep(prevStep);
  };

  return { Funnel, Step, next, prev, currentStep };
}