Solog
React에서 SOLID 원칙 LSP

React에서 SOLID 원칙 LSP

2023년 11월 21일

React
OOP

Liskov Substitution Principle

자식 클래스는 최소한 부모 클래스에서 가능한 행위를 수행할 수 있어야 한다.
자식 클래스는 부모 클래스로 대체될 수 있어야 한다.

interface Props { name?: string value?: string onChange?: (value: string) => void } function Input({ value, onChange, name }: Props) { return ( <input type='text' name={name} value={value} onChange={(e) => onChange(e.target.value)} className='design-input' /> ) } export default Input

위 컴포넌트는 디자인 시스템에 명시된 Input 컴포넌트 이다.

위 컴포넌트는 기존 html input 에 디자인 스타일만 입혀준 컴포넌트 이고,

이는 즉 이 컴포넌트의 부모 컴포넌트는 input 이라 볼 수 있다.

LSP 관점에서 몇 가지 문제점을 살펴보려한다.

type 대체 불가능

기존 input 은 type 을 text 뿐만 아니라 password, number 등 여러 가지로 선언이 가능하다.

하지만 이 컴포넌트는 type 을 내부에서 text 로 지정하고 외부에서 변경되는 것을 막아두었기 때문에 부모 컴포넌트인 inputtype 값을 대체할 수 없다.

onChange 대체 불가능

기존 input 은 onChange 함수에 value: string 를 인수로 넘기는 것이 아닌

e: React.ChangeEvent<HTMLInputElement> 을 인수로 넘긴다.

위 설계에 따라 value 값이 변하는 이벤트가 발생했을 때, 이벤트 객체에 접근이 불가능하기 때문에 부모 컴포넌트인 inputonChange 함수를 대체할 수 없다.

className 대체 불가능

기존 inputclassNamedesign-input 이 고정되어 있지 않다.

하지만 이 컴포넌트는 className 을 내부에서 design-input 으로 지정하고 외부에서 변경되는 것을 막아두었기 때문에 부모 컴포넌트인 inputclassName 을 대체할 수 없다.

선언되지 않은 Props 사용 불가능

만약 이 Input 컴포넌트에 id 값이 부여되어야 한다면? onFocus, onBlur 등 포커스 상태를 감지할 이벤트 함수가 필요하다면?

현재 설계된 컴포넌트의 모습에서는 사용할 수 없어 보인다.

즉 부모 컴포넌트인 input 을 대체할 수 없다.

interface Props extends React.DetailedHTMLProps< React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement > {} function Input({ className, ...props }: Props) { return <input className={classNames('design-input', className)} {...props} /> } export default Input

LSP 관점에서 문제가 있던 컴포넌트를 위와 같이 리팩토링 해보았다.

Input 컴포넌트의 Props 를 부모 컴포넌트인 inputProps 을 상속받아 설계하였다.

이에 따라 모든 Propinput 컴포넌트의 Prop 을 대체할 수 있다.

디자인 시스템에 필요한 classNameclassnames 라이브러리를 사용하여 기본적으로 사용할 className 과 prop 으로 전달되는 className 을 합쳐주면 될 것 같다.

이전 아티클

React에서 SOLID 원칙 OCP

다음 아티클

React에서 SOLID 원칙 ISP