왔썹(WhatSsub)은 서브웨이 주문 시 재료를 선택해서 음식을 주문하는 방식에 익숙하지 않은 사람들을 위한 재료 조합 생성 및 제공하는 서비스다.
배포: https://what-ssub.vercel.app/
github: https://github.com/harseille/WhatSsub
프로젝트를 진행하며 느낀 경험을 4L(4Ls) 방식으로 회고하고자 한다.
매주 스터디를 하며 먹기 깔끔한 서브웨이를 자주 배달시켜 먹었는데 그때마다 꿀조합을 검색하기도 하고 선택 자체에 시간이 오래 걸리기도 했다.
실제로 주변 지인들 중에 서브웨이의 주문 시 어려움을 겪어 서브웨이 자체를 이용하지 않는 경우도 더러 있었다.
위의 불편함을 해결하고자 왔썹(WhatSssub) 프로젝트를 시작하게 되었다.
왔썹은 있어 보이기 위한 아이디어로 시작한 프로젝트가 아닌 스터디를 하며 실제로 겪은 불편함을 해결하고자 필요한 아이디어를 바탕으로 시작한 프로젝트여서 더욱 애착이 가고 즐겁게 개발을 진행했다.
좋았던 점이자 가장 아쉬운 부분이 아닐까 생각한다.
이전 프로젝트의 기술 스택은 대체로 현재 사용할 줄 아는 기술이라는 이유로 프로젝트의 규모나 기술 스택 자체의 장단점은 자체는 고려하지 않고 프로젝트를 진행했다.
하지만 이번 프로젝트에서는 기획의도, 규모, 기능에 대한 부분을 고민하며 나름대로의 이유를 가지고 기술 스택을 도입했다.
구현 기능이 캐주얼하고 짧은 시간 내 완성을 목표로 함
기술 변화가 빠른 프론트엔드 환경을 고려하여 최신 버전의 제품에 대응할 수 있는 역량을 갖추고자 함
- react-router-dom@6.4 - 새로 추가된 loader, action, errorElement 등 기능을 활용해 컴포넌트 구현부의 코드를 clean하게 하고자 함
- Recoil - React 자체 라이브러리로 상태를 외부에서 처리하지 않는 점, 비동기 처리를 위한 추가적인 라이브러리도 필요 없음
- Emotion - styled-component 대비 가볍고 작은 번들 사이즈
- Firebase - 프론트엔드로만 이루어진 프로젝트였기에 serverless 서비스 사용, OAuth 및 정적 파일 저장소 제공
테오의 스프린트를 진행하며 BDD, SDD를 방식을 사용해 효율적으로 함께 설계를 했던 좋은 경험이 있었다.
이전의 긍정적인 경험을 얘기하며 설계에 대한 아이디어를 낼 수 있었고 BDD, SDD를 통해 서비스 기능에 대한 공통된 이해를 할 수 있었다.
다른 개발자분께 공유 받은 지식과 경험을 통해 팀원들에게 전파하고 활용할 수 있어 뿌듯했다.
Toss에서 적용 중인 세종대왕 컨벤션을 참고하여 한글 컨벤션이 코드 가독성과 유지 보수에 이점이 있는지 확인하고자 도입을 했다.
Toss에서는 예시로 국가지방자치단체공공단체금융사여부 같은 어려운 도메인 용어나 비즈니스 로직에 한글 컨벤션을 적용했다.
왔썹 프로젝트의 경우 사실 영어로 표현하기 어려운 단어 자체는 없었지만 서비스의 핵심인 "꿀조합"이라는 한국만의 밈을 살리고자 했다.
그렇게 Toss의 세종대왕 컨벤션을 베이스로 집현전 프로젝트라는 우리만의 컨벤션을 만들었다.
한글 컨벤션을 사용하다 보니 어디까지 한글 컨벤션을 적용하는 것이 옳은가를 많이 고민했다.
익숙하지 않아 어색하게 보이기도 했고 밈을 살리기 위해 쓰기엔 굳이 꿀조합 하나를 위해 한글을? 이라는 의문도 많이 생겼던 것 같다.
비즈니스 로직만 하자니 각자가 생각하는 비즈니스 로직의 기준이 달라 컨벤션이 지켜지지 않는 경우도 많았다.
대표적으로 로그인과 유저정보, 댓글 등 타 프로젝트에도 대부분 들어가는 비즈니스 로직의 경우가 애매했다.
핵심 비즈니스 로직이냐라고 하기엔 아니라고 대답할 수 있고 비즈니스 로직이 아니냐라는 질문엔 그건 또 아니었기 때문이다.
이런 이슈로 주기적으로 회의를 하고 라이브쉐어로 코드를 살펴보고 조율하는 시간을 가지며 컨벤션을 통일했다.
처음 도입한 이유인 코드 가독성과 유지 보수의 이점을 생각해 본다면 많은 아쉬움이 남는다.
도입 시 무분별한 한글 사용으로 보일까를 걱정했는데 다른 개발자의 시각에서 본다면 적절한 한글 사용으로 이점을 잘 가져갔다라기보단 굳이 왜 한글을 했을까라는 의문이 더 클 것 같다.
하지만 한글 컨벤션을 사용함으로써 보다 나은 추상화를 위해 식별자 명을 더 고민할 수 있었고 통일을 하는 과정에서 팀원의 코드에도 함께 집중할 수 있는 뜻깊은 경험이였다.
꿀조합 Pick 페이지에서 선택한 속성으로 필터링 된 꿀조합을 제공해 주는 기능이 이번 프로젝트의 핵심 기능이었다.
최대 7개의 속성까지 들어가는 경우가 있어 and 조건의 필터링이 필요했는데 FireSotre에서 해당 기능이 제공되지 않았다.
array-contain 사용 시 쿼리당 최대 하나의 array-contain 절을 사용할 수 있어 해당 문제를 해결할 수 없었다.
not in(!=) 을 사용하여 선택 속성 외의 속성으로 필터링도 시도를 해봤지만 최대 10개의 같지않는 경우만 제공되고 있어 여러 번의 요청이 필요해 해결이 어려웠다.
최종적으로 해당 이슈를 해결하지 못함으로써 모든 꿀조합을 받아온 후 client에서 필터링하여 제공하게 되어 아쉽다.
recoil을 상태관리 라이브러리로 사용을 했다. recoil의 atom의 경우 리얼 전역적인 상태, 즉 어떤 페이지든 알아야 하는 상태를 기준으로 사용을 했다.
그렇다 보니 왔썹 프로젝트의 경우 로그인 여부, 유저정보를 제외하곤 전역적으로 가지고 있을 필요가 없었다.
꿀조합 리스트를 불러오는 페이지들은 많았지만 페이지마다 필터링이 되거나 정렬 기준이 달랐기 때문에 지역 상태로 관리를 했다.
이로 인한 props drilling이 발생하긴 했지만 컴포넌트 depth가 깊지 않아 나쁘지 않았다.
하지만 프로젝트를 진행하다 보니 위의 아쉬운 점이었던 firebase의 and Filter에 대한 기능이 제공되지 않아 전체 꿀조합을 불러온 뒤 로컬에서 가공하는 케이스가 존재하게 됐다.
그렇다 보니 전체 꿀조합을 불러오는 경우에는 atom에 할당하여 전역 상태로 가지고 있고 나머지 꿀조합 요청 시에도 꿀조합에 대한 변경사항이 없는 경우 서버에 요청하지 않고 atom에 저장된 꿀조합을 가공하여 사용할까도 고민을 했지만 실제 애플리케이션이라 생각을 했을 때 애초에 모든 데이터를 불러오는 케이스가 없기 때문에 불필요한 최적화라 생각되어 수정하지 않았다.
최적화를 고려해 atom으로 관리하는 게 맞는가? 전역상태의 본질을 유지하는게 맞는가?
정말 어려운 문제인 것 같다.
정답은 없겠지만 상황에 따라 최적화를 고려해 전역 상태로 관리 하는게 맞는지 아닌지 판단할 수 있는 경험치가 필요함을 많이 느꼈다.
CRA를 사용하지 않고 Webpack을 구성하며 CRA의 편리함을 느꼈다.
Webpack 세팅을 하며 CRA를 사용할 땐 당연하게 생각했던 부분들이 직접 설정을 해줘야 하는 경우가 많았다.
env 파일을 위해 dotenv-webpack 플러그인도 필요했고 dynamic-import를 위해 @babel/plugin-syntax-dynamic-import 바벨 플러그인을 추가하기도 했다.
그 외에도 alias로 절대 경로를 지정해 사용하기도 하고 splitChunks로 파일을 분리해 최적화를 하는 경험도 했다.
처음엔 마냥 어렵게만 느껴졌는데 필요한 설정을 하나하나 추가를 해가며 퍼즐 맞추는 느낌이 들기도 하고 흥미로웠다.
접근성 향상을 위해 WAI-ARIA의 aria-label로 이미지만 있는 버튼의 내용을 명시해다.
Pick 페이지와 Custom 페이지의 경우 버튼에서 색상대비율 개선이 필요한 경우도 있었지만 디자인을 고려해 타협한 경우도 있었다.
퍼포먼스 향상을 위해 splitChunks로 react와 firebase 관련 파일을 Code Splitting하기도 하고 React.lazy를 활용해 route 단위 Dynamic Imports를 하기도 했다.
(react-router-dom V6.4에 새로 추가된 data APIs에서 lazy가 작동하지 않는 이슈로 기존의 router를 사용했다. )
SEO를 위해 description, OG 등의 meta 태그를 추가하며 meta 태그에 대해서도 배울 수 있었다.
가장 큰 깨달음은 개념조차 몰랐던 Tree Shaking 이었다.
(이 부분은 따로 정리를 했기에 링크도 대체한다.)
lighthouse와 webpack-bundle-analyze로 최적화 체크
recoil을 사용했지만 atom을 제외하곤 사용되지 않았다.
로그인 여부, 유저 정보, 유저가 좋아요한 꿀조합 정보는 selector를 활용해 좀 더 recoil의 장점을 살릴 수 있지 않을까 생각된다.
공통적인 컴포넌트의 경우 다른 프로젝트에서도 사용 가능 하도록 개발해 생산성을 높이는 것이 중요하다고 생각했다.
이번 프로젝트에서도 나름 공통적인 컴포넌트를 나누긴 했지만 그 외에도 분리해 재사용 가능한 부분이 있음을 깨달으며 부족함을 느꼈다.
잘 읽고갑니다