본문 바로가기
React TIL

[React] Day_56 데일리 정리

by 림졍 2024. 12. 6.

 

눼.

 

..TIL 파일 날라가서...

결국 나중에서야 다시 정리한 me의 TIL..

작성.. 해야겠지?

가보자고.

 

 

챌린지반 강의정리 - 퍼널(Funnel) 패턴 알아보기

깔끔한 UX 설계하기 (like 토스!)

 

뭔가 뻘쭘해서 토스 로고 가져오기~ [출처 : 토스 리소스 센터]

 

 

퍼널 패턴(Funnel Pattern)

퍼널(Funnel) = 깔대기

사용자가 단계를 거쳐 정보를 입력하도록 설계한 UI 패턴

각 단계에서 하나의 정보를 입력 후, 다음 단계로 자연스럽게 이동하는 구조

UI/UX와 코드 품질 모두를 향상시킬 수 있는 강력한 설계 방식

 

 

- 특징

  • 단계별 UI 분리: 한 번에 하나의 정보만 입력
  • 시각적인 단순함: 간결한 화면으로 사용자 스트레스 감소
  • 유연한 데이터 관리: 각 단계의 데이터를 독립적으로 처리

 

- 기존 방식(다단계 폼)의 문제점

  • 흩어진 페이지 흐름: 각 단계가 별도의 컴포넌트에 분산되어 흐름 파악 어려움
  • 분산된 상태 관리: 여러 컴포넌트에서 상태를 관리하여 복잡한 데이터 흐름을 보임
  • 유지보수성 저하: 새로운 단계 추가 시 많은 파일 수정 필요
  • 라우터 의존성: 복잡한 라우팅 로직 필요

 

- 예시코드

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>
  );
}

 

 

토스 퍼널 패턴 접근 방식

 

상태 관리와 페이지 흐름을 한 곳에서 처리 → 코드 응집도 및 유지보수성 향상

 

- 주요 특징

  • 단계별 흐름, 단일 컴포넌트에서 관리 → 응집도 향상
  • 상태 변경이 일원화되어 데이터 흐름을 쉽게 추적
  • 라우터 의존성 제거: 라우터 없이 단계 전환 관리
  • 가독성 증가 : 코드가 간결하고 이해하기 쉬움
  • 유지보수성 및 재사용성 강화 : 단계 추가 및 수정 용이 + 여러 프로젝트에서 활용 가능

 

- 개선 코드 예시

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>
  );
}

 

 

코드 개선: 재사용성과 가독성 향상

 

1. Step 컴포넌트 도입

- Step 컴포넌트를 활용, 조건부 렌더링 간결하게 처리

 

function Step({ name, currentStep, children }) {
  return name === currentStep ? <>{children}</> : null;
}

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

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

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

 

2. 커스텀 훅 useFunnel 생성

- 단계 상태 관리 및 페이지 전환 로직 캡슐화

 

import { useState } from "react";

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

  const Step = ({ name, children }) => {
    return name === currentStep ? <>{children}</> : null;
  };

  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 };
}

 

 

- useFunnel 적용한 최종 코드

function Registration() {
  const { Funnel, Step, next, prev, currentStep } = useFunnel("가입방식");
  const [userData, setUserData] = useState({});

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

  return (
    <Funnel>
      <Step name="가입방식">
        <SignUpMethod onNext={(data) => handleNext(data, "주민번호")} />
      </Step>
      <Step name="주민번호">
        <ResidentNumber onNext={(data) => handleNext(data, "주소입력")} onPrev={() => prev("가입방식")} />
      </Step>
      <Step name="주소입력">
        <AddressInput onNext={(data) => handleNext(data, "가입성공")} onPrev={() => prev("주민번호")} />
      </Step>
      <Step name="가입성공">
        <SuccessPage userData={userData} />
      </Step>
    </Funnel>
  );
}

 

 

추가 고려 사항

 

1. URL 동기화

- URL을 단계 상태와 동기화하여 새로고침이나 뒤로 가기 버튼을 눌러도 현재 단계를 유지합니다.

 

2. 애니메이션 효과

- react-transition-group를 활용하여 단계 전환 시 부드러운 애니메이션을 적용합니다.

 

 

 

 

마무리 - 주말엔 풀코딩.

 

집콕...하기 싫어 ㅠㅡㅠ

 

오래간만에 쭉 편히 자고

하루는 좀 놀다가

SPA 프로젝트 하고~ 그래야겠다..

그럼 20000.

 

 

 

오늘의 KPT 회고

 

Keep: 그래도 나름.. 다 했다..

Problem: 다음 거.. 잘 따라갈 수 있을까?

Try: 일단 리액트 빠2

 

THE_END

 

728x90
반응형