Refactor/#247: GNB와 SideDrawer의 HTML구조, 컨벤션, 접근성 리팩토링#187
Conversation
- LoginSection 컴포넌트를 제거하고 해당 코드를 MenuGroups 컴포넌트 내부로 이동 - div 중첩을 줄이고 의미에 더 적합한 태그들로 변경 (로고에 사용된 h1 제거) - 가독성을 위한 개행 적용 - 레이아웃을 더 명확하게 잡기 위해서 비효율적으로 작성된 css 수정
- useSideDrawerStore를 통해 상태 관리가 이루어지도록 변경 - SideDrawer 컴포넌트의 선언 위치를 레이아웃 최상위(main태그 바깥)로 변경 - 햄버거 메뉴 jsx 호출 위치를 MenuGroups 컴포넌트 내부로 이동
✅ Deploy Preview for we-write ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
…factor/#247-gnb-sidedrawer
hoxey2Front
left a comment
There was a problem hiding this comment.
고생하셨습니다~! 디자인 상으로는 많이 안바뀐거 같은데 코드상에는 엄청 많이 바뀌었네요 🙌
|
|
||
| useEffect(() => { | ||
| const onKeyDown = (e: KeyboardEvent) => { | ||
| if (e.key === 'Escape' && isDrawerOpen) { |
There was a problem hiding this comment.
Escape는 처음 보는데 혹시 esc키 인가요?
There was a problem hiding this comment.
네 맞습니다 esc 입력을 통해 Drawer가 닫힐 수 있게 하는 이벤트입니다.
SwimmingRiver
left a comment
There was a problem hiding this comment.
고생하셨습니다~
브랜치 단위를 더 작게 해도 좋을 거 같아요!
어떤 방식으로 리팩토링이 필요한 부분을 찾아서 진행하시나요?
| import { useAuth } from '@/providers/auth-provider/AuthProvider.client'; | ||
| import useReferer from '@/hooks/useReferer'; | ||
| import UserProfileDropdown from '@/components/layout/GNB/UserProfileDropdown'; | ||
| import { Hamburger } from '@public/assets/icons'; |
There was a problem hiding this comment.
lucide 아이콘으로 통일하는건 어떨까요?
There was a problem hiding this comment.
저도 lucide 아이콘으로 변경할지 생각해보았는데 아직 기존에 사용된 SVGR을 lucide로 대체해자는 논의가 나오지 않은 상황에서 lucide 로 변경하는건 리팩토링보단 취향적인 부분이 될 것 같아서 이번 작업에는 제외됐습니다.
lucide 로 대체 가능한 svg는 lucide로 변경하는 것도 괜찮고, 이미 프로젝트에 사용된 svgr은 변경하지 않는 방법도 있을 것 같아서 위클리 스크럼 때 논의해볼까요?
| useEffect(() => { | ||
| if (isDropdownOpen) { | ||
| setFocusedIndex(0); | ||
| setTimeout(() => { | ||
| menuItemRef.current[0]?.focus(); | ||
| }, 0); | ||
| } | ||
| }, [isDropdownOpen]); | ||
|
|
||
| useEffect(() => { | ||
| const handleKeyDown = (e: KeyboardEvent) => { | ||
| if (e.key === 'Escape' && isDropdownOpen) { | ||
| closeDropdown(); | ||
| } | ||
| }; | ||
| document.addEventListener('keydown', handleKeyDown); | ||
| return () => document.removeEventListener('keydown', handleKeyDown); | ||
| }, [isDropdownOpen]); |
There was a problem hiding this comment.
같은 의존성 배열을 갖는데 따로 분리된 이유가 있을까요?
구상하신 구조의 순서 때문일까요?
There was a problem hiding this comment.
첫 번째는 관심사를 분리(하나는 포커스 제어, 하나는 리스너 관리)하기 위함이고,
두 번째는 코드 가독성의 향상, 세 번째는 유지보수의 용이함 때문입니다.
두 로직의 연관 관계가 생기거나, 성능 개선의 필요가 생긴다면 useEffect 통합을 고민해볼 수 있을 것 같습니다
| } | ||
| }; | ||
|
|
||
| const handleMenuKeyDown = (e: React.KeyboardEvent<HTMLUListElement>) => { |
There was a problem hiding this comment.
이부분 좋은거 같네요
접근성을 위해서 전역적으로 설정할 필요도 있을까요?
There was a problem hiding this comment.
WCAG 기준에 따르면 Arrow Up / Down 키보드 조작은 "선택 가능한 UI 구성요소"에서 필수적으로 지원해야 한다고 합니다.
페이지내 모든 인터렉션까진 아니더라도 li태그나, role='menuitem' 등에는 공통적으로 적용되어도 좋을 것 같습니다.
There was a problem hiding this comment.
리팩토링에서 zustand 추가까지 넘어가게된 아이디어가 궁금합니다!
There was a problem hiding this comment.
PR 설명에 적혀져 있는 부분을 첨부하겠습니다!
혹시 아래의 설명에 더해서 추가적으로 궁금하신 점이 있으시다면 질문주세요!
SideDrawer가 호출되는 위치가 기존GNB컴포넌트 내부에서 전역 layout의main외부로 변경하였습니다.
- 레이아웃 계층상 header -> GNB -> SideDrawer 로 이어지는 구조보다는, 다른 header, main 요소들에 종속되지 않도록 SideDrawer를 위치시키는 것이 더 적절하기에 이와 같이 리팩토링 진행하였습니다.
SideDrawer의 호출 상태를 관리하는 상태를useSideDrawerStore로 변경했습니다.
SideDrawer를 여는 버튼은 GNB 내부에, SideDrawer가 호출되는 위치는 GNB 외부에 있기 때문에 props로 상태를 전달하기엔 어렵고, 전역으로SideDrawer의 상태를 관리할 필요가 있다고 느껴져useSideDrawerStore을 통해 관리하도록 변경하였습니다.- Context와 비교하면 Context는 단 하나의 상태 관리만을 위해서 Provider를 선언해야 하고, 상태 변경 시 관련된 모든 컴포넌트가 리렌더링된다는 점에서 zustand store를 사용하는 방식이 더 직관적이고 적합하다고 판단하였습니다.
변경 사항
여러 종류의 리팩토링을 진행한만큼
코드 변경 사항을 확인해주실 때, files changed보다는 commit이력을 따라가면서 확인해주시면 어떠한 목적으로 변경한 코드인지
확인하기에 용이할 것 같습니다.
GNB를 서버 컴포넌트로 변경하고, 내부의 jsx를 자식 컴포넌트들에서 그리도록 변경하였습니다.GNB를 서버 컴포넌트로 관리함으로써 얻는 이점을 기대하기 보다는GNB상위 컴포넌트의 jsx를 관심사에 따라 분리함으로써 컴포넌트의 책임을 명확하게 하고 가독성을 높이기 위한 목적으로 변경하였습니다.SideDrawer가 호출되는 위치가 기존GNB컴포넌트 내부에서 전역 layout의main외부로 변경하였습니다.SideDrawer의 호출 상태를 관리하는 상태를useSideDrawerStore로 변경했습니다.SideDrawer를 여는 버튼은 GNB 내부에, SideDrawer가 호출되는 위치는 GNB 외부에 있기 때문에 props로 상태를 전달하기엔 어렵고, 전역으로SideDrawer의 상태를 관리할 필요가 있다고 느껴져useSideDrawerStore을 통해 관리하도록 변경하였습니다.h1을 제거, 리스트가 필요한 경우nav,ul,li를 도입하는 등 전반적인 구조를 점검하였습니다.DropDown공통 컴포넌트로 변경하였습니다.tabIndex를 적용하고,esc나↑(Arrow up),↓(Arrow down)방향키 조작을 지원하는 등 키보드 접근성을 향상시켰습니다.