클린 코드로 작성하기 굉장히 번거로웠지만, 모든 기능을 만족하는 Group과 Block 컴포넌트를 구현했다 🥰
📎 관련 이슈
closes #47
💡 논의해볼 사항
패키지간 의존성 최소화
어떻게 보면 당황스러울 수도 있다. ui에서 일어나는 Group에서의 prop drilling이 깊어보일 수 있기 때문이다.
실제로도 GroupWrapper 부터 시작하는 이 컴포넌트의 로직은 다음과 같다.
GroupWrapper -> GroupMemberList -> Member(Factory) -> Block or Group -> {{ Group && GroupWrapper -> ... }}
그렇지만, 이렇게 prop을 내려주기 위함은 다음과 같은 고민이 있었기 때문이다.
전역 상태 관리를 적용하면, 추후 의존성 관리에 있어 리스크가 있지 않을까?
실제로도 프론트엔드는 현재 jotai라는 전억상태관리를 이용하고 있다.
그런데 만약에 redux로 바꾼다면? 여기서 유지보수가 발생할 것이고, 패키지 변경 유지보수에 따른 사이드 이펙트가 발생하지 않으리란 보장이 없다.
즉, 하나의 전역상태 관리 패키지 유지보수가 일어나면, 핸들링할 부분이 약 4개의 컴포넌트가 추가된다.
이는 추후 원인 파악에 있어서도 상당히 귀찮고, 이러한 컴포넌트가 약 1000개 정도가 화면 상에서 컨트롤해야 한다면 분명 더 헷갈릴 것이다.
따라서 전역상태 관리 메서드를 약 컴포넌트 4곳에 prop drilling하는 방식이 전역상태관리를 일일이 달아주는 것보다 유지보수가 훨씬 쉬울 것이라 생각하여 이렇게 적용했다.
Member - Factory Method Pattern 차용
MemberFactory의 경우 어찌보면 당황스러울 수 있다. 그냥 조건부로 해서 Block으로 내려주던, Group으로 내려주던 한다.
하지만 이렇게 책임을 분리하는 것이 분명 깔끔하게 코드를 단일 책임으로 가져가기 용이하다고 생각했다.
지금은 단순히 type으로만 분리했지만, 추후 이 로직이 더 복잡해질 수도 있다고 생각하기 때문이다.
따라서 그냥 상/하위 컴포넌트는 각각의 props에 맞게 UI 렌더링을 한다는 책임을 갖고, 결과적으로 이 Member 컨테이너 컴포넌트는 단지 멤버의 타입과 특징에 따라서 적절한 컴포넌트로 내뱉을 수 있도록 하는 패턴을 적용했다.
비제어 컴포넌트 방식의 편집 기능
div엘리먼트로 Title을 관리하고 있었기 때문에 이를 contenteditable로 추가적인 input 컴포넌트 조건부 없이 만들고 싶었다.
이렇게 하는 것이 분명 코드도 분기처리 없이 한 컴포넌트 내에서 더욱 직관적으로 만들 수 있다는 느낌이 들어서다.
(어차피 contenteditable이 담겨있는 순간 이 컴포넌트가 input할 수 있다는 건 알 수 있으니)
다만 여기서 React는, 원래 Form에 있어서 제어 컴포넌트 방식으로 관리한다는 점에서 로직이 동작하지 않았다.
따라서 필연적으로 useRef와 useEffect를 사용해야 했다.
물론 이것이 로직상 더 부담이 일어날 수는 있겠으나...(10000개의 컴포넌트가 렌더링된다면...?)
이에 대한 최적화는 문제가 정말 생겼을 때 나중에 하기로 했다.
설사 위험하다 싶다면... react-window 등을 쓰지 뭐...
💌 설명
클린 코드로 작성하기 굉장히 번거로웠지만, 모든 기능을 만족하는 Group과 Block 컴포넌트를 구현했다 🥰
📎 관련 이슈
closes #47
💡 논의해볼 사항
패키지간 의존성 최소화
어떻게 보면 당황스러울 수도 있다.
ui
에서 일어나는Group
에서의prop drilling
이 깊어보일 수 있기 때문이다. 실제로도GroupWrapper
부터 시작하는 이 컴포넌트의 로직은 다음과 같다.GroupWrapper
->GroupMemberList
->Member(Factory)
->Block
orGroup
->{{ Group && GroupWrapper -> ... }}
그렇지만, 이렇게 prop을 내려주기 위함은 다음과 같은 고민이 있었기 때문이다.
실제로도 프론트엔드는 현재
jotai
라는 전억상태관리를 이용하고 있다. 그런데 만약에redux
로 바꾼다면? 여기서 유지보수가 발생할 것이고, 패키지 변경 유지보수에 따른 사이드 이펙트가 발생하지 않으리란 보장이 없다.이는 추후 원인 파악에 있어서도 상당히 귀찮고, 이러한 컴포넌트가 약 1000개 정도가 화면 상에서 컨트롤해야 한다면 분명 더 헷갈릴 것이다. 따라서 전역상태 관리 메서드를 약 컴포넌트 4곳에 prop drilling하는 방식이 전역상태관리를 일일이 달아주는 것보다 유지보수가 훨씬 쉬울 것이라 생각하여 이렇게 적용했다.
Member - Factory Method Pattern 차용
MemberFactory
의 경우 어찌보면 당황스러울 수 있다. 그냥 조건부로 해서 Block으로 내려주던, Group으로 내려주던 한다. 하지만 이렇게 책임을 분리하는 것이 분명 깔끔하게 코드를 단일 책임으로 가져가기 용이하다고 생각했다. 지금은 단순히type
으로만 분리했지만, 추후 이 로직이 더 복잡해질 수도 있다고 생각하기 때문이다.따라서 그냥 상/하위 컴포넌트는 각각의 props에 맞게 UI 렌더링을 한다는 책임을 갖고, 결과적으로 이
Member
컨테이너 컴포넌트는 단지 멤버의 타입과 특징에 따라서 적절한 컴포넌트로 내뱉을 수 있도록 하는 패턴을 적용했다.비제어 컴포넌트 방식의 편집 기능
div
엘리먼트로 Title을 관리하고 있었기 때문에 이를contenteditable
로 추가적인input
컴포넌트 조건부 없이 만들고 싶었다. 이렇게 하는 것이 분명 코드도 분기처리 없이 한 컴포넌트 내에서 더욱 직관적으로 만들 수 있다는 느낌이 들어서다. (어차피contenteditable
이 담겨있는 순간 이 컴포넌트가input
할 수 있다는 건 알 수 있으니)다만 여기서
React
는, 원래Form
에 있어서 제어 컴포넌트 방식으로 관리한다는 점에서 로직이 동작하지 않았다. 따라서 필연적으로useRef
와useEffect
를 사용해야 했다.물론 이것이 로직상 더 부담이 일어날 수는 있겠으나...(10000개의 컴포넌트가 렌더링된다면...?) 이에 대한 최적화는 문제가 정말 생겼을 때 나중에 하기로 했다. 설사 위험하다 싶다면...
react-window
등을 쓰지 뭐...📝 참고자료
⚠️ 잠깐! 한 번 체크해주세요.