공통 컴포넌트 설계, 개발 및 적용

이전 리액트 공통 컴포넌트 글에서 공통 컴포넌트에 대한 생각을 정리한 적이 있습니다. 그 후 몇 개월이 지나서 실무에서 공통 컴포넌트를 만들고, 프로덕트에 적용할 기회가 생겼습니다. 그 경험을 정리하고자 합니다.

느낀점

느낀점 부터 말씀드리자면, 잘 설계된 공통 컴포넌트는 높은 생산성을 가져다 주었다는 겁니다. 같은 프로젝트에 참여한 팀원은 컴포넌트의 UI에 신경쓸 부분이 줄어들고 프론트 엔드 로직을 짜는데 집중을 할 수 있었습니다. 실제로 같은 수준의 화면의 UI를 잡는데 2, 3일 걸렸던 것이 반나절 만에 완성되기도 했습니다. (물론, 손에 익어서 더 빨라졌다 든지 같은 다른 요인도 있었을 겁니다.)

그 반대로 잘못 설계된 공통 컴포넌트는 오히려 손이 많이 가게 만드는 요인이 되기도 했습니다. 변경 사항이 올바르게 반영되었는지 확인하기 위해 이 공통 컴포넌트가 이미 적용된 곳을 하나씩 확인해야 했기 때문이었죠. 또한, 다른 프로젝트에서 느꼈 듯이 공통 컴포넌트가 너무 복잡하게 만들어지면, 사용하기 꺼려집니다. 너무 한정적으로 사용할 수 밖에 없어 활용도가 낮아지기 때문이지요.

다음 번에 공통 컴포넌트를 만드는 업무가 주어지면, 삽질을 덜 할 수 있다는 자신감을 심을 수 있었습니다.

공통 컴포넌트 추출 작업

제가 작업했던 공통 컴포넌트는 크게 2가지 유형으로 나누는데, 대충 이름을 베이직(Basic)과 어드밴스드(Advanced)라고 하겠습니다.

UI 라이브러리를 React로 감싸는 수준의 컴포넌트들이 베이직에 속합니다. 이미 회사에서 사용하는 UI 라이브러리가 있어서 이를 React로 모두 감싸는 작업을 진행했죠. UI 라이브러리가 Semantic UI를 참고해서 만들어진 것이라, React를 감싸는 작업을 할때, React Semantic UI를 많이 참고했습니다.

어드밴스드 유형은 만드려는 프로덕트 내에서 반복되는 UI 패턴을 공통 컴포넌트로 추출한 것들 입니다. 파일 업로드 버튼이나, 폼 필드, 에디터 등이 이에 속하겠네요. 이런 유형의 컴포넌트들은 대부분 베이직에 속하는 공통 컴포넌트들의 조합으로 만들어 집니다.

베이직 공통 컴포넌트 장/단점

아무래도 작은 단위의 컴포넌트다 보니 유연하게 사용할 수 있고, 스타일을 덜 신경쓰면서 뚝딱뚝딱 만들어도 되는 장점이 있습니다. 실제로 인풋, 버튼 같은 각각의 엘리먼트에 스타일을 입힌 수준이니까요.

반면에 작은 단위의 컴포넌트를 만들어야 하다보니, 시간이 많이 든다는 장점이 있습니다만, 장점이 단점을 어느 정도 상쇄시켜 주는 것 같습니다.

어드밴스드 공통 컴포넌트 장/단점

덩치가 큰 녀석들을 다루다 보니, 유연하게 사용할 수가 없습니다. 조금이라도 다른 요소가 필요해지면, props를 추가하고, if를 떡칠해가며 땜빵을 해야합니다. 이게 과해지면 결국엔 활용성이 떨어져 공통 컴포넌트로 쓰기가 꺼려지게 됩니다.

그래도 잘 만들어 두면, 생산성이 확 올라가더군요. 이거 하나만 보고 만드나 봅니다.

어드밴스드 공통 컴포넌트 시행착오

기획서만 보고 섣불리 공통 컴포넌트로 뽑아내지 말자. 저는 능력도 경험도 부족했습니다. 섣불리 만들어 놓은 것들은 대대적인 수정 작업이 필요했고, 이미 적용해놓은 곳마다 하나하나 확인하는 작업이 커졌습니다.

우선 어떤 식으로 공통 컴포넌트를 뽑아낼 것인지 감을 잡아야 하는데 일단 저는 비슷하게 생긴 것들을 두 세개 개별적으로 만들어 보면서 감을 잡았습니다. 이런 식으로 작업하면서 공통 컴포넌트 2, 3개 정도 만들어 두었는데 굉장히 잘 쓰고 있습니다.

도움이 되었던 것

  • React Semantic UI: 베이직 공통 컴포넌트는 모두 이것을 참조하여 만들었습니다. 이벤트 핸들러에서 lodashinvoke를 사용하여 함수를 호출하는 것과 함수의 기타 파라미터로 자신의 props를 넘겨주는 것을 유용하게 써먹을 수 있었습니다.
  • Handling React Form With MobX Observables: Form Field을 공통으로 추출할때 많이 참조하였습니다. 기본적인 아이디어는 name을 key로 사용하여 모델을 변경하게 만든다는 건데 굉장히 편합니다. 아마 Form 관련 라이브러리도 이런 원리로 실행되지 않을까 생각합니다.