Interface 설계
interface: 서로 다른 무언가를 연결하는 구멍
익숙한 인터페이스로 설계하기
- 어떻게 인터페이스를 정의해야 이 컴포넌트의 동작이 이해가 될까라는 고민이 필요
- 최대한 html과 비슷하게 설계하는 것이 좋다. 예측하기 쉽기 때문.
- 창의적이기 보다는 모두가 이해할 수 있는 일반적인 방향
// useState와 비슷한 인터페이스로 이해하기 쉬움
const [view, setView] = useView();
인터페이스 먼저 설계하기
- props는 자기가 호출되는 곳에서 알아야 될 맥락만 알아야함
- 자기가 호출되는 맥락에 관심을 갖게 되면 재사용성 떨어짐
- 컴포넌트의 내부에만 관심을 갖는 것이 좋다
- 도메인 컨텍스트를 많이 가지고 있는 컴포넌트는 표현력이 떨어짐
// 이와 같은 인터페이스는 단번에 동작을 파악하기 어려움
// floors를 왜 넘기고 있지?에 대한 의문을 갖게 함
<FilterPanel
values={values}
floors={floors}
validationError={validationError}
onChange={handleFilterChange}
/>
// 따라서 직관적이고, 이해하기 쉬운 인터페이스가 필요하다
<FilterPanel
value={value}
onChange={onChange}
/>
- 컴포넌트를 만들면서 props를 추가하다보면 위처럼 직관적으로 컴포넌트를 파악하기 어려운 props를 많이 넘기게 된다. (
floors,validationError) - 이를 지양하기 위해서는 인터페이스 먼저 설계하는 전략이 도움이 된다
value,onChange
<section>
<label>
<span>이메일</span>
<Input/>
</label>
<label>
<span>비밀번호</span>
<Input/>
</label>
</section>
- 컴포넌트 외에도 요구사항 파악 후 위처럼 인터페이스 위주로 먼저 Pseudocode를 작성하면 구현하면서 흐름을 잃지 않을 수 있음
인터페이스의 네이밍
// setDate의 중복
<Date setDate={setDate} />
// 이상적인 Props
<Date onChange={setDate} />
- 컴포넌트의 이름과 props 이름은 항상 붙어다니기 때문에 반복해서 적지 않아도 되고, 맥락상으로도 반복되는 것이 불필요하다
setDate->setDate매핑 처럼
setDate란 input 값이 바뀌었을 때 호출이 되는 것인데 값이 바뀌었을 때setDate외에도 다른 작업을 하고 싶을 수 있음setDate라는 용어보다는 컴포넌트 내부 동작에 집중한onChange가 좋다
<FilterPanel
value={value}
onChange={handleChange}
/>
onChange->handleChange와 같은 매핑 및 네이밍 좋지 않음handleCancel이 정확히 무슨 동작을 하는지 알 수 없음-handle과 같은 네이밍보다 실제로 함수가 하는 일, 실제 동작 나타내기
Props 너무 많아지고 있을 때
<FilterPanel
values={values}
floors={floors}
validationError={validationError}
setMessage={setMessage}
equipment={equipment}
onClick={handleFilterClick}
onChange={handleFilterChange}
/>
props가 너무 많다는 것은 좋지 않은 신호
- 단일 책임 원칙 위반의 신호
- 재사용의 어려움
- 테스트 복잡도 증가
- props rilling의 징조
- 자식 컴포넌트로 많은 데이터를 내려보내면서 중간 컴포넌트에 불필요한 props가 쌓이는 경우일 수 있음
- 컴포넌트 책임 오염: Child는 사용하지 않는 props에 대한 고민 필요
- 연쇄적 변경: 건드릴 이유가 없는 컴포넌트를 건드려야 함
- 변경에 취약: Props 하나가 바뀌면 그걸 넘겨주는 모든 부모 컴포넌트도 수정
- 재사용 어려움
- 불필요한 리렌더링 야기
출처
토스 Frontend Fundamental 모의고사 2차