VAC Debugger - VAC 패턴 설계

Park U-yeong·2022년 11월 30일
0

VAC Debugger

목록 보기
2/7
post-thumbnail

VAC 패턴

일반적으로 View는 JSX 렌더링과 View 로직을 관리합니다.
그러나 VAC 패턴은 JSX 렌더링과 View 로직을 격리해서 관리합니다.
이를 위해 View에서 JSX 부분만 View Asset Component(이하 VAC)로 분리하도록 설계합니다. 즉 렌더링 관심사에서 Business 로직 뿐만 아니라 View 로직도 분리합니다.

Business 로직 - 데이터(Model)를 관리하고 변형하는 처리
View 로직 - 렌더링에 필요한 상태값을 관리하고 변형하는 처리

따라서 VAC 패턴의 설계 목적에 맞도록 개발을 하려면 VAC는 JSX의 렌더링에만 집중하고, View의 상태값을 관리하는 로직과 격리가 되어야 합니다.

반대로 이야기하면 View에서 JSX 영역과 무관하게 View 로직을 처리할 수 있다면 VAC 패턴이 잘 적용되었다고 볼 수 있습니다.

이를 위해 VAC Debugger(이하 <VAC>)는 JSX가 없는 상황에서 View 로직을 테스트할 수 있도록 도와줍니다.

VAC 패턴은 React Hooks 패턴이나 Presentational 과 Container Component 패턴 등을 대체하는 설계가 아니라, 해당 디자인 패턴에 추가로 적용하여 사용할 수 있습니다.

컴포넌트 구조 잡기

먼저 View 컴포넌트에서 JSX 부분을 Props Object로 추상화 합니다. 이런 설계는 개발중인 앱의 전반에 일관되게 사용할 필요는 없고, 미리 정한 기준에 해당하는 컴포넌트에 대해서 적용하면 됩니다.

// View
function ViewComponent() {
  // JSX 영역을 추상화 한 Props Object
  const props = {
    // JSX 영역에 적용할 데이터나 callback 관리
  };
  
  // JSX 영역은 별도의 VAC로 구현
  return <ViewAssetComponent {...props} />;
}
// VAC
function ViewAssetComponent(props) {
  // JSX 렌더링 관리
  return <div>JSX</div>;
}

하나의 View 컴포넌트는 여러개의 VAC를 조합해서 사용할 수 있습니다.

function NoticeView() {
  const vTabProps = {};
  const vListProps = {};
  
  return (
    <div>
      <VTab {...vTabProps} />
      <VList {...vListProps} />
    </div>
  );
}

VAC Debugger 적용

JSX를 관리하는 VAC를 개발하기 전이라면 View 로직을 테스트하기 위해 <VAC>를 사용합니다.

import { VAC } from 'react-vac';

function ViewComponent() {
  // Props Object
  const props = {};
  
  // VAC 대신 <VAC>로 View 로직 테스트
  return <VAC name="View 테스트" data={props} />;
  
  // 실제 VAC
  // return <ViewAssetComponent {...props} />;
}

View 로직 테스트

<VAC>data 속성에 Props Object를 전달하면 View 로직을 테스트할 수 있는 UI가 구성됩니다.

import { useState } from 'react';
import { VAC } from 'react-vac';

// View
function SpinBox() {
  const [value, setValue] = useState(0);

  // SpinBox View 로직
  const vSpinBoxProps = {
    value,
    onIncrease: () => setValue(value + 1),
    onDecrease: () => setValue(value - 1)
  };

  // <VAC>를 이용해 View 로직 테스트
  return <VAC name="SpinBox 테스트" data={vSpinBoxProps} />;
  
  // JSX를 관리하는 VAC는 별도로 개발
  // return <VSpinBox {...vSpinBoxProps} />;
}
// VAC
function VSpinBox({value, onIncrease, onDecrease}) {
  return (
    <div>
      <button onClick={onDecrease}>감소</button>
      <input type="text" value={value} />
      <button onClick={onIncrease}>증가</button>
    </div>
  );
}

예제 보기

주의할 점

Props Object에서 이벤트에 바인딩 할 목적으로 사용하는 callback 함수는 이벤트에 직접 바인딩 하는 함수로 선언해야 합니다.

다음 예시에서 onClick 함수는 VAC 내부에서 적용할 이벤트에 직접 바인딩을 합니다. 그래서 onClick과 관련된 로직이 변경되어도 VAC에 영향이 없습니다.

// View
function ViewComponent() {
  const props = {
    // 클릭 처리를 View에서 관리
    onClick: (e) => console.log('클릭'),
  };

  return <ViewAssetComponent {...props} />
}
// VAC
function ViewAssetComponent({onClick}) {
  return <button onClick={onClick}>버튼</button>;
}

그러나 다음 예시의 handleClick 함수는 VAC 내부에서 적용할 때 함수를 직접 호출하여 파라미터를 전달해야 합니다.

// View
function ViewComponent() {
  const props = {
    handleClick: (value) => console.log(value)
  };

  return <ViewAssetComponent {...props} />
}
// VAC
function ViewAssetComponent({handleClick}) {
  // 클릭 처리를 VAC에서 관리
  return <button onClick={(e) => handleClick('클릭')}>버튼</button>;
}

때문에 JSX를 관리하는 VAC 내에서 handleClick 함수에 전달하는 value가 어떤 값인지 알아야 하며, 전달하는 방식이 바뀌거나 value의 대상이 달라지거나 할 경우 VAC 내에서도 수정이 필요합니다.

그래서 callback 함수가 event 객체가 아닌 임의의 파라미터를 받는 경우는 VAC가 로직에 관여하지 않도록 View 로직을 관리하는 컴포넌트에서 다음과 같이 처리해서 VAC에 전달해야 합니다.

function ViewComponent() {
  const handleClick = (value) => console.log(value);

  const props = {
    // 클릭 처리를 View에서 관리
    onClick: (e) => handleClick('클릭')
  };

  return <ViewAssetComponent {...props} />
}
// VAC
function ViewAssetComponent({onClick}) {
  return <button onClick={onClick}>버튼</button>;
}

마치며

다음편은 배열 처리에 대해서 설명합니다.

profile
What 12 9oing on?

0개의 댓글