개요
JSX와 Style를 관리하여 UI와 비즈니스 로직을 분리하는데, 목적을 둔 컴포넌트 설계 방법론이다.
Normal Pattern 특징
Business Logic과 UI 처리를 바인딩 하여 개발을 하게 된다.
jsx, view logic, business logic 이 혼합(같이)하여 사용
FE 데이터 작업 과정에서 단순한 props 나 state 를 수정함에 있어서도, JSX 영역에 대한 수정이 필요하다. 이때, UI 처리와 바인딩 부분이 같은 페이지였을 경우, 영역 겹침으로 인한 코드 충돌이 발생한다.
VAC Pattern 특징
view logic과 JSX 와 컴포넌트로 분리에 대한 가이드를 제공하는 디자인 패턴.
- 반복, 조건부 노출 등 스타일 제어 렌더링에 관련된 처리만 수행
- props 를 통해서만 제어되며, 스스로의 상태를 관리하지 않는 stateless 컴포넌트
- 이벤트에 함수를 바인딩 할 때 추가 처리 없이 적용
예제
Normal Pattern
spinBox.jsx 컴포넌트 영역에 모든 구성 요소들이 다 같이 있는 가장 일반적인 구성 요소이다.
// **Normal Pattern Logic**
const SpinBox = () => {
const [value, setValue] = useState(0);
<!--------------------- props Object ----------------------->
const onDecreas = () => setValue(value - 1);
const onIncrease = () => setValue(value + 1);
<!--------------------- props Object ----------------------->
return (
<!--------------------- view 영역 ----------------------->
<div>
<button onClick={onDecreas}>-</button>
<span>{value}</span>
<button onClick={onIncrease}>+</button>
</div>
<!--------------------- view 영역 ----------------------->
);
};
VAC PAttern
SpinBoxView.jsx VAC 영역을 만들어, Business Logic 영역과 분리 한다. (VAC 생성)
// **VAC PAttern Logic
//** SpinBoxView.jsx
// 데이터 바인딩부분은 SpinBox 가 담당하기에 styles 영역에 관한 부분만 신경쓴다.
const SpinBoxView = ({ value, onIncrease, onDecrease }) => (
<div>
<button style={{bacgkround:red}} onClick={onDecrease}>-</button>
<span>{value}</span>
<button onClick={onIncrease}>+</button>
</div>
);
// **Business Logic**
// SpinBox.jsx
const SpinBox = () => {
const [value, setValue] = useState(0);
// Props Object <- 여기에다 추가
const props = {
value,
onDecrease: () => setValue(value - 1),
onIncrease: () => setValue(value + 1),
};
// rendering 부분은 VAC 가 담당하기에 props 부분만 작업 하고 신경쓴다.
return return <SpinBoxView {...props} />;
};
VAC PAttern <TS 적용>
Props 가 가져야 할 값을 interface로 구현하여 View에 조금 더 직관적인 props 들을 넘길 수 있다.
또한, 내려온 props 만 보고 UI를 설계하고 작업 할 수 있다는 장점까지 생긴다.
Business Logic - BusinessComponent.tsx
import {ChangeEvent, FormEvent} from "react";
import useInput from "../../../hooks/useInput";
import {ViewComponent} from './viewComponent'
export interface VAC<T> {
onChange: (e: ChangeEvent<HTMLInputElement>) => void,
onSubmitHandler: (event: FormEvent<HTMLFormElement>) => void
Email: T,
Password: T,
Name: T,
ConfirmPassword: T
}
export const BusinessComponent = () => {
const {onChange, inputs} = useInput({Email: '', Password: '', Name: '', ConfirmPassword: ''});
const {Email, Password, Name, ConfirmPassword} = inputs;
const onSubmitHandler = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
}
const props = {
onSubmitHandler,
onChange,
Email, Password, Name, ConfirmPassword
}
// rendering 부분은 VAC 가 담당하기에 props 부분만 작업 하고 신경쓴다.
return <ViewComponent {...props} />
};
VAC PAttern Logic - ViewComponent.tsx
// 데이터 바인딩부분은 SpinBox 가 담당하기에 styles 영역에 관한 부분만 신경쓴다.
import React from "react";
import {VAC} from "./businessComponent";
export const ViewComponent = ({onSubmitHandler, onChange, Email, Password, Name, ConfirmPassword}: VAC<string>) => (
<div className={'wrap'}>
<form onSubmit={onSubmitHandler} className={'login-form'}>
<label htmlFor="{'input-email'}">Email</label>
<input type="email" name={'Email'} id={'input-email'}
defaultValue={Email} onChange={onChange}/>
<label htmlFor="{'input-name'}">Name</label>
<input type="text" name={'Name'} id={'input-name'}
defaultValue={Name} onChange={onChange}/>
<label htmlFor="{'input-password'}">Password</label>
<input type="password" name={'Password'} id={'input-password'}
defaultValue={Password} onChange={onChange}/>
<label htmlFor="{'input-ConfirmPassword'}">Confirm Password</label>
<input type="password" name={'ConfirmPassword'} id={'input-ConfirmPassword'}
defaultValue={ConfirmPassword} onChange={onChange}/>
<button type={'submit'}>
Login
</button>
</form>
</div>
);
장점
TypeScript의 직관적 사용
Storybook을 통한 독립적인 UI 테스트에 유리
비지니스 로직 변경에 유리
단점
Props가 많이 질 수 있음
[참고자료]
728x90
'STUDY > CS' 카테고리의 다른 글
클라이언트 사이드 렌더링(CSR, Client Side Rendering) (0) | 2022.12.28 |
---|---|
서버 사이드 렌더링(SSR, Server Side Rendering) (0) | 2022.12.28 |
검색 엔진 최적화 (SEO, Search Engine Optimization) (0) | 2022.12.28 |
아토믹 디자인 (Atomic Design) (0) | 2022.12.27 |
[CS] Proxy Server (프록시 서버) (0) | 2022.12.26 |
댓글