퍼널(Funnel) 패턴에 대하여

에구마·2024년 3월 20일

퍼널 (Funnel), 깔대기란 뜻이다!

웹(앱) 화면에서 생각하자면, 다음 단계-다음 단계를 거쳐 결과로 도달하는 화면 패턴을 말한다.
회원가입을 생각하면 쉽다. 본인인증 -> 핸드폰 번호 인증 -> 닉네임 설정 -> 취향 선택 등의 과정이 되겠다!

일반적인 방법은?

본인인증.tsx, 핸드폰인증.tsx 등 화면을 각각 만들어두고 이를 navigate 등을 통해 다음으로 이동한다면?
문제점 1. 흐름을 파악하기 어렵다! 각 화면에서 다음이 어디 페이지인지를 일일이 확인해야하니까
문제점 2. 최종 결과로 보낼 상태들이 흩어져있다. 각 페이지에서의 상태들을 전역으로 들고 있어야한다.

어떻게 해결할까?

상단 페이지에서 최종 결과가 될 상태와 현재 단계에 대한 상태를 가진다.
그리고 각 상태에 따라 해당하는 페이지를 로드 하면된다.

적용해보기✨


기본 플로우는

  • '메인페이지'에서 특정 게임방 선택 -> '게임페이지'로 이동한다. 화면은 참여자를 기다리는 대기실 UI이다. -> 참여자가 다 모여서 게임이 시작되면 선택된 모드의 게임화면이 시작된다
  • 게임 중에 이탈을 하게 되면 '메인페이지'로 나가야한다.

GameWaitingRoom에서 선택한 모드에 따라 navigate('/sentence'), navigate('/code') 등 각 모드의 게임화면으로 이동을 구상했다.

하지만!
url을 도메인/game/{게임방id}/sentence , 도메인/game/{게임방id}/code 이런식에서 도메인/game 으로 단축시켰다. 두가지 이유가 있는데, 1.url조작으로 인한 버그를 막기 위해서, 2.클라이언트단에서 관리할 수 있는 상태를 굳이 url에 표기하지 않기 위해서 였다.

그래서 다음과 같이 작성하였다.

switch-case ?

 switch (gameMode) {
    case 'waiting':
      return (
        'roomId' in gameRoomInfo && (
          <GameWaitingRoom gameRoomInfo={gameRoomInfo} />
        )
      );
    case 'sentence':
      return <GameSentence />;
    case 'code':
      return <GameCode />;
    case 'word':
      return <GameWord />;
    case 'finish':
      return <GameFinish />;
    default:
      return <GameWaitingRoom />;
  }

switch-case를 사용해서 화면 전환을 했었다.

가독성에 개선점을 느꼈다. switch-case는 직관적이면서도 무언가 길게 느껴진다.

삼항연산자 ?

삼항연산자를 사용했다.

 return (
    <>
      {'roomId' in gameRoomInfo ? (
        gameMode === 'waiting' ? (
          <GameWaitingRoom gameRoomInfo={gameRoomInfo} />
        ) : gameMode === 'sentence' ? (
          <GameSentence />
        ) : gameMode === 'code' ? (
          <GameCode />
        ) : gameMode === 'word' ? (
          <GameWord />
        ) : (
          <GameFinish />
        )
      ) : (
        <div>소켓오류</div>
      )}
    </>
  );

본인은 삼항연산자를 자주 쓰는 편이(라는걸 알게되었)다.
하나씩 걸러진다는 것이 좋게 느껴졌는데, 코드리뷰를 통해 가독성이 좋지 않다는 평도 얻어서 개선해보았다.

완성!

        {gameMode === 'SENTENCE' && <GameSentence/>}
        {gameMode === 'CODE' && <GameCode/>}
        {gameMode === 'WORD' && <GameWord/>}
        {gameMode === 'FINISH' && <GameFinish/>}

아-주 깔끔하다...!
gameMode는 하나의 상태를 가지기 때문에 어짜피 하나의 컴포넌트만 보여지게 된다..!


적용하고 보니, 이부분에서는 퍼널 패턴이라기에 애매한 부분이 있다. 거치는 단계가 깊지 않고, 모든 단계에 걸쳐서 관리하고 최종에 도달하게 할 데이터가 있는 것도 아니어서..
게임모드의 상태관리(zustand 등), 다음 단계로 이동 및 이탈 처리에 대해 코드를 더 빌드한 후에 다시 수정해봐야겠다!
퍼널패턴의 쓰임을 알았고, 깨달은걸 바탕으로 프로젝트에서 개선할 수 있었다는 점에 의의가 있었다!




앞으로 도전!
토스 Tech에서 만든 useFunnel 훅 라이브러리가 있다!
적용해보기 + 내가 만들어보기 해야지


참고 : https://toss.tech/article/engineering-note-1

profile
코딩하는 고구마 🍠 Life begins at the end of your comfort zone

0개의 댓글