Case로 보는 좋은 컴포넌트
좋은 컴포넌트 분리
Case 1) 추상화와 추출을 구분하기
// before
<section>
<h1>회의실 예약</h1>
<section>
<label>
<span>선호 층</span>
<select>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
</label>
<label>
<span>필요 장비</span>
<div>
<button>스피커</button>
<button>마우스</button>
<button>마이크</button>
</div>
</label>
</section>
</section>
// after
<section>
<h1>회의실 예약</h1>
<FilterPanel/>
</section>
before -> after로 개선했다고 가정했을 때 어떤 점이 좋지 않을까?
- 페이지 컴포넌트를 깔끔하게 유지하려는 의도이지만
- 필터 관련 로직이 하나의 컴포넌트로 합쳐지며 UI상 1:1 대응이 되지 않음
- 필터 관련 로직이 1000줄이 넘어간다면 이와 같은 개선도 필요할 수 있겠으나
- 이것은 추상화가 아니라 추출일 뿐이다.
<section>
<h1>회의실 예약</h1>
<section>
<label>
<span>선호 층</span>
<NumberSelect />
</label>
<label>
<span>필요 장비</span>
<ToggleGroup />
</label>
</section>
</section>
- 이와 같은 추상화가 좋다
- UI와 영역별 1:1 매칭이 된다
- 페이지 컴포넌트에 불필요한 관심사는 분리되고 적합한 추상화
관련 블로그 글:추출이 아닌, 추상화
Case 2) 좋은 추상화는 맥락을 가지지 않는다
// bad
fucntion FloorSelect () {
return (
<select>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
)
}
- 1,2,3과 같은 숫자는 어떤 맥락을 가지는지 알 수 없다
- 좋은 추상화는 추상화 한 컴포넌트 내부에 자세한 맥락을 가지지 않는다(floor)
- 자세한 맥락이 없는 것이 재사용하기 더 좋음
// good
export function NumberSelect({ value, onChange, options, ariaLabel, label, placeholder = '전체' }: Props) {
return (
<Select
value={value ?? ''}
onChange={e => {
const val = e.target.value;
onChange(val === '' ? null : Number(val));
}}
aria-label={ariaLabel}
>
<option value="">{placeholder}</option>
{options.map(opt => (
<option key={opt} value={opt}>
{opt}
{label}
</option>
))}
</Select>
);
}
- 완전히 층의 맥락을 제거함 (floor->number)
- 만약 4층을 F로 표현해야 한다면 그 때는
NumberSelect가 아닌 맥락을 포함한FloorSelect가 필요할 수 있다.
Case 3) 컴포넌트와 Props의 연결성
// bad
<MyReservationList setMessage={setMessage} />
-
이와 같은 컴포넌트가 있을 때 props로는 스타일링 정도가 충분하다
-
setMessage같은 동작은 컴포넌트 안에서 처리하는 게 좋다- (나의 추론) 코드를 읽는 입장에서 나의 예약 목록 컴포넌트에 메시지를 변경할 필요가 뭐가 있지? 라는 생각이 들기 때문인듯
-
도메인 맥락이 많이 들어간 컴포넌트는 표현력이 떨어짐
-
컴포넌트와 props의 연결성이 맥락을 모르는 사람이 봤을 때도 파악 가능해야 함
-
컴포넌트를 API에 종속되지 않게 하려고 list를 props로 가져오려고 하는 경우
- 충분히 컴포넌트 스스로 list를 가져올 수 있음
- 컴포넌트가 순수하길 원했다면 모든 API 페칭을 내놓거나, 모두 넣거나 해야함
- UI만 있는 컴포넌트를 만들기 어렵고, 재사용도 잘 되지 않음
출처
토스 frontend fundamentals 모의고사 2회차 해설