개발 과정에는 SPRINT
단위가 존재한다. 팀이 일정량의 작업을 완료하는 시간을 정해두고 더 나은 소프트웨어를 제공하기 위해 발전, 업데이트 하는 단위라고 볼 수 있다.
이때, 특정 서비스의 품질을 높이기 위해 매 SPRINT마다 많은 변화
가 일어난다.
프론트엔드 역할의 특성 상 다음과 같은 요소들을 목적으로 한다.
사용자 경험
을 높이기 위한 최대의 노력과 중요하다고 생각하는 마인드 셋유지보수
가 가능하도록 코드를 작성하는 능력오너십
… 등등
📌 변화는 `니즈(Needs)`에 따라 발생하고 제품은 `고객`에 맞추어 성장한다위와 같은 목적을 달성하기 위해서는 변화에 대해 두려워해서는 안되지만, 우리의 코드나 프로젝트에 들어간 시간
과 노력
이 없이지는 것은 누구에게나 힘든 일이다.
“변화는 예측이 불가능하다!”
그렇다면
우리는 변화에 어떻게 대응
해야 하는가?
코드를 어떻게 작성해야 변화에 유연하게 대처
할 수 있을까?
무엇이 효과적이고 유연한 컴포넌트일까?
적당히~
’가 대체 뭘까요?제품(Product)
가 만들어지는 흐름은 다음과 같다.
작은 컴포넌트를 합치고 적당한 범위로 코드를 분리한다.
→ 이 과정에서 컴포넌트의 목적
과 코드의 직관성
을 잃는 경우가 존재한다.
Headless
기반의 추상화한 가지 역할
만 수행도메인 포함 여부
에 따른 분리const [state, setState] = useState(false);
//<button
onClick={() => {
setState(x => !x);
}}
//>
<button>
버튼 {state ? 'on' : 'off'}
</button>
“어떻게 보여줄 것인가?” 에 관한 부분은 (UI) 부분은
디자인
에 의존한다.
그러면 컴포넌트에서 데이터와 UI를 분리해보는 것은 어떨까?
📌 디자인에 의존하는 UI를 컴포넌트가 관리하는 데이터와 분리해보자!const { headers, body, view } = useCalendar()
달력을 사용하는데 필요한 계산을 useCalendar에 위임함으로서, UI를 자유롭게 수정해도 문제가 생기지 않는다. (데이터를 분리하여 자유로운 형태를 만든 것) ⇒ 데이터에만 집중하여 모듈화할 수 있다.오로지 데이터에만 집중하여 모듈화 할 수 있는 패턴을
Headless
라고 한다.
⇒ hooks로 모듈화 하는 방법!
이전에 구성했던 드롭다운 관련 내용과 비슷한 내용이 나와서 반가웠다.
isOpen
: 메뉴의 노출 상태 데이터
를 관리하는 DropdownTrigger
: 상태를 바꾸기 위한 상호작용
을 관리하는 Dropdown.TriggerMenu
: 옵션 영역의 열고 닫힌 상태를 통해 노출여부가 결정되므로, Dropdown.Menu를 따로 구성Item
: Menu를 구성하는 각각의 아이템은 상호작용
을 담당 → 분리한다.다루고 있는 데이터와 역할을 기준으로 분리하였다.
function Select({ label, trigger, value, onChange, options }: Props) {
return(
<Dropdown label={label} value={value} onChange={onChange}>
<Dropdown.Trigger as={trigger}>
<Dropdown.Menu>
{options.map(option => (
<Dropdown.Item>{option}</Dropdown.Item>
))}
</Dropdown.Menu>
<Dropdown>
);
}
위와 같이 구성하여 사용하는 경우, 각 컴포넌트들은 서로의 존재를 서로 알 수 없으므로, 변경이 유연해진다.
→ 다른 부분이 변경되더라도 Select 컴포넌트는 영향이 가지 않기 때문!
두 UI는 완전히 다른 것 같아 보이지만 다음과 같은 공통점을 뽑을 수 있다.
Select 에서 힌트를 얻어 새로운 UI를 구성할 수 있다.
위와 같이 살펴보았을 때, Select에서 구분한 기능과 데이터 컴포넌트를 통해 재사용이 가능하며, 전체적인 흐름을 보았을 때, Select와 구성요소가 크게 다르지 않음을 알 수 있다.
📌 데이터와 UI를 분리하고 한 가지 기능만 할 수 있도록 컴포넌트를 생성하는 것은 컴포넌트 변경에 `유연하게 대처`하고 `재사용성`을 늘릴 수 있는 방법이 된다!📌 언제 데이터를 주입받고, 언제 데이터를 스스로 가져올 것인가?“컴포넌트를 주입받은 것처럼 데이터도 주입받는 것은 어떨까?”
위 컴포넌트를 구성해야 한다고 할 때, 이전에 구성한 Select UI를 가져오기 힘든 이유가 무엇일까?
(현재 글에서는 빠졌지만 강의에서는 Framework라는 도메인을 넣었음!)
Framework라는 도메인을 분리하여 사용한다면 일반적인 이름으로 변경된다.
📌 컴포넌트는 일반적인 인터페이스로 표현해야 이해하기 쉽다.interface
의 Props
이름은 표준에 가까울수록 편리하다
ex) FrameworkSelect
⇒ MultiSelect
와 같은 형식으로 구성
의도
가 무엇인가?기능
은 무엇인가?표현
되어야 하는가?컴포넌트의 기능과 어떤 데이터를 관리하고 있는가? → 이것을 어떻게 표현할 것인가?
구현보다 중요한 문제!!!
더 좋은 코드를 구성하는 것은 복잡도를 낮추고
, 재사용이 가능
하며 변경에 유연
하게 다시 구성
할 수 있는 것
변화를 대응하고 대처하기 위한 컴포넌트를 구성하는 관점
따라볼 수 있는 Actions
“위에서 본 내용은 좋은 코드와 컴포넌트를 구성하기 위한 수많은 관점 중 하나다.”
우리가 가지고 있는 관점에 유의미한 관점을 추가하여 변경에 유연하게 대처할 수 있는 방향성에 대해 고민해보는 것이 중요하다.