문제점
Input 공용 컴포넌트를 맡게 되었는데 처음에는 간단한 로직이었지만 추가 요구사항이 많아지면서 모든 상황에 다 맞춰야 하면서 동시에, 많은 props를 받아야하는 문제점이 생기고, 얼마나 더 많은 요구사항이 생길지 모르게 되었다.
해결
멘토님께 문제를 말씀 드렸더니 많은 해결법을 주셨는데, 그 중 합성 컴포넌트를 찾아보게 되었다.
합성 컴포넌트 패턴이란?
하나의 컴포넌트를 여러 가지 관심사로 분리하고 분리된 관심사는 사용되는 곳에서는 원하는 관심사만 조합을 하며 사용하는 패턴이다.
쉽게 말해서 html의 select를 생각하면 좋을 것 같다.
<select> <option value="1">Option 1</option> <option value="2">Option 2</option> <option value="3">Option 2</option> </select>
select 태그는 option에 대한 것들을 담고 있고, option은 각각의 value에 대한 것들을 담고 있다.
또한 value2를 사용하고 싶을 때는 value1, value3을 제외한 value2만 사용하면 된다.


실제 사용에서도 동일하게
select - InputContainer
option - Image, Tags, Text, TextArea
위와 같은 방식으로 넣었어서 작업을 진행하였다.
참고
InputContainer - 입력 요소들을 감싸는 컴포넌트 역할
InputImage - 이미지 입력을 다루는 파일
InputTags - 태그 입력을 다루는 파일
InputText - 텍스트 입력 다루는 파일
InputTextArea - 다중 행 텍스트 입력 다루는 파일
사용 방법
- InputText만 사용하고 싶을때
<InputCompound style={{ width: '300px' }}> <InputCompound.Text placeholder="이메일" value={email} onChange={(e) => setEmail(e.target.value)} ref={emailRef} onKeyUp={handleOnKeyUp} /> </InputCompound>
- InputText와 Tags를 동시에 사용하고 싶을때
<InputCompound style={{ width: '350px' }}> <InputCompound.Text placeholder="태그" }} /> <InputCompound.Tags tags={tags} setTags={(arg) => setTags(arg)} /> </InputCompound>
장점
- 많은 props를 컨트롤 할 수 있다.
- 단순 Input 컴포넌트를 만들때는 props를 일일이 제어해야하고 복잡했는데, 합성 컴포넌트를 활용하면서 관심사별로 props를 각각 넣을 수 있는 장점이 있었다.
- 계층 구조가 한눈에 드러나서 직관적으로 확인 할 수 있다.
- UI 변경에 강하다.
- props drilling에 대한 대처가 이전보다 더 완화할 수 있다.
단점
- 간단한 input인데도 코드가 더 길어질 때가 있어서 가독성이 떨어질때가 있다.
추가
- 데이터 컨트롤은 안이 아닌 밖에서 핸들링을 하게 하여 여러 페이지에서 사용할 수 있도록 하였다.
- input 컴포넌트의 여러 옵션에 대해서 InputHTMLAttributes<HTMLInputElement>를 오버라이드 해서 사용하여 축약할 수 있었다.