주니어 개발자들이 읽으면 좋은 테크 아티클 모음
F-Lab : 상위 1% 개발자들의 멘토링
프론트엔드 개발을 하면서 선택한 컴포넌트 설계 방식(Headless Ui Component) 및 문서 작성 방식(Storybook)이다.
Storybook을 통해 공통 컴포넌트에 대한 설명 및 사용 예시를 만들었고 Headless Ui Component 설계 방식을 통해 어떤 디자인이든 대응 가능한 공통 컴포넌트를 만들었다.
이 과정에서 Ui framework는 일절 사용하지 않았다.
그 이유는 단지 커스텀할 때의 귀찮음과 빌드 용량이 커진다는 것 때문이었다. (요즘은 대부분 트리쉐이킹이 되지만..)
Headless Ui Component
프론트 개발자로 일한지 반년도 채 안돼서 어떤 의문이 생겨나기 시작했다.
그당시 난 vue를 사용했었고(지금도 vue를 사용중이다) Ui framework로 vuetify를 사용했었다.
하지만 vuetify ui 컴포넌트를 사용하던, 내가 직접 만든 컴포넌트를 사용하던, 디자이너가 버튼 아이콘 위치, 아이콘 수정 등 미묘하게 다르게 디자인해주면, 이에 맞게 화면 개발하기가 너무 어려웠다.
같은 버튼인데, 단지 아이콘만 다르고 또는 아이콘 위치만 다를 뿐인데, 이를 제어하기위해 props를 늘려가고 그에따라 스타일 적용해주고.. 나중엔 내가 어떤 props를 만들었었는지, 이 prop이 무슨 역할을 하는지도 모르겠는 상황이 발생했다. (props만 수십개가되는 컴포넌트도 생기기 시작했다)
그러면서 이렇게 컴포넌트를 설계하는게 맞나? 이럴거면 차라리 공통 컴포넌트 말고 그냥 페이지마다 마크업으로 넣는게 나을거같은데? 라는 생각이 머리에서 떠나질 않았다.
이 당시 내가 원하던 컴포넌트는 어떤 디자인이든 적용하기 쉬운 컴포넌트였다.
공통 컴포넌트로 버튼(CommonButton.vue) 하나만 만들어두면 이 버튼 컴포넌트로 어떤 디자인이든 대응 가능하게 하는 것이 내 목표였다. (props같은거 사용 안하고..)
이런 고민을 하던 와중에 Headless Ui Component 개념에 대해 알게됐다.
컴포넌트를 HTML 마크업 방식으로 적용하면서 스타일은 없고 컴포넌트 동작 로직만 담겨있는 설계 방식이다.
이 개념을 알게되었을 때 머리가 트이는 기분이었고 당장 적용해보고 싶단 생각에 구현 방식에 대해 고민했다.
내가 주로 사용하는 프론트 프레임워크는 vue이다.
일단 vue로 Headless Ui Component 방식으로 공통 컴포넌트를 만드는 방식을 고안했다.
그 과정에서 vue의 provide, inject 기능을 사용했고 이를 원칙으로 삼았다. (원칙. 중앙 상태관리는 절대 사용하지 않는다. 컴포넌트를 만들 때 해당 컴포넌트 동작 로직을 제어하기 위해 중앙 상태관리를 사용하는 경우도 있던데, 데이터가 아니라 고작 컴포넌트의 동작 제어를 위해 중앙 스토어까지 사용할 필요는 없다고 판단했다. 로직도 더 복잡해지고.. 해당 컴포넌트를 가져다 쓸때 스토어도 등록되었는지 확인까지해야되면.. 너무 불필요하다.)
여튼 셀렉트 박스 컴포넌트를 만든다면
CommonSelectArea.vue에 셀렉트리스크가 열리고 닫히는 로직이 다 들어있고
이 안에 slot으로 어떤 특정 컴포넌트가 들어온다면,
예를 들어 CommonSelectButton.vue 컴포넌트가 들어온다면, 해당 컴포넌트가 클릭됐을 때, CommonSelectList.vue 컴포넌트가 보이는 로직이 자동으로 주입된다.
즉 이런식으로 설계하면 컴포넌트를 가져다 쓸 때 아래와 같이 사용할 수 있다.
<CommonSelectArea>
<CommonSelectButton>버튼</CommonSelectButton>
<CommonSelectList></CommonSelectList>
</CommonSelectArea>
위와 같이 HTML 태그 형식으로 작성할 수 있게되면 디자인 자유도가 급상승한다.
어떤 디자인 변화도 모두 대응할 수 있다.
이런 방식으로 현재 수십개 공통 컴포넌트를 구현했다.
구현하면서 느낀점과 Storybook 사용 후기는 다음 글에 정리해보도록 하겠다.
다음 내용이 궁금하다면?
이미 회원이신가요?
2023년 12월 1일 오후 6:23
R
... 더 보기d
... 더 보기