뷰티 필터를 개발하며 얻은 새로운 경험
처음 만나는 React Query, 그리고...
🔖 Note
이 문서는 2022 5th Kurly Tech MeetUp: 뷰티 컬리를 만든 사람들의 웹 프론트엔드 개발 발표 세션의 내용을 각색하여 정리한 글입니다.
🤔 선크림을 사고 싶어!
평화로운 봄날 아침입니다. 이마 위로 내리쬐는 햇살이 따사롭습니다. 앗, 햇빛 바로 쬐면 피부에 안 좋댔는데… 생각이 난 김에 출근길에 선크림을 하나 살까 생각합니다. 그렇지만 오프라인 매장을 여기저기 돌아다니며 물건을 비교한다는 건 여간 귀찮은 일이 아닙니다. 이번엔 진짜 사야 하는데… 그런데 아무거나 사긴 싫은데… 불현듯 뇌리를 스친, 처음 만나는 뷰티 플랫폼 – 뷰티 컬리.
그래, 컬리가 있었지. 컬리에서는 합리적인 가격의, 지성 피부를 위한 선크림을 쉽고 빠르게 구매할 수 있을 것 같은 느낌이 듭니다. 노트북을 열고 컬리에서 “선크림”을 검색합니다.
검색 결과 161건. 뭐가 이렇게 많아? 당황하려던 순간, 아차, 필터를 적용하지 않았군요.
👻 필터를 적용한 동일한 상품 목록을 보고 싶으시다면 이 링크를 확인해 주세요!
먼저, 관련 상품만 보기 위해 카테고리를 "선케어"로 설정합니다.
다음으로 합리적인 가격의 물건을 사고 싶기 때문에, 가장 낮은 가격 구간대와 "할인상품"을 선택합니다.
마지막으로 피부 타입에 맞게 “지성 피부”를 선택하면,
짜잔! 무려 11건으로 상품 목록이 간단해 졌습니다.
선택지가 추려진 덕분에, 더욱 편리하고 합리적으로 구매 결정을 할 수 있게 되었습니다. 광고 영상 속 제니처럼 우아하게 이브닝 드레스를 입고 보랏빛 박스를 가지러 가진 않았지만, 뷰티 컬리와 필터 덕분에 다음 날 아침 출근 전까지 무사히 선크림을 받아 볼 수 있었습니다.
🔎 필터 프로젝트
목표: 필터 프로젝트를 왜 하는 걸까?
그럼 본격적으로 필터 프로젝트에 대해 이야기를 해보겠습니다. 필터 프로젝트는 다음과 같은 목표로부터 출발하였습니다.
1) 고객: 상품 탐색 경험의 개선
먼저, 고객 측면에서는 상품 탐색 경험의 개선을 목표로 시작했습니다. 이전에는 일부 운영 체제(안드로이드)에만 적용되어 있었던 필터를, PC와 모바일 웹에서 사용할 수 있도록 확장하여 플랫폼 별로 분산된 고객 경험을 통일하기 위함이었습니다.
2) 기술: 데이터 상태 관리 방법의 전환
이와 더불어 기술적인 측면에서는 데이터의 상태 관리 방법의 전환을 목표로 설정했습니다. 기존의 컬리몰에서는 한 화면을 오래 띄워두거나, 다른 페이지에 방문한 후 컬리몰에 재접속했을 때, 이전의 데이터를 보여주고 있었습니다. 따라서 고객은 구매 가능한 상태임을 보고 장바구니 담기를 시도했지만, 실시간 재고 변동 등으로 인해 품절로 상품을 구매하지 못하는 불편함이 종종 있었습니다.
과정: React Query의 도입
그동안 컬리몰은 redux를 통해 서버에서 가져온 데이터를 상태 관리하고 있었습니다. 필터 프로젝트를 진행하면서 이것을 React Query로 전환했습니다.
대부분의 개발 팀에서 이러한 전환은 쉽지 않은 결정일 것입니다. 저희는 커머스 웹 개발 팀의 ‘웹 개발 기술 선정 토론회’라는 문화 덕분에 이러한 의사결정을 할 수 있었습니다.
‘웹 개발 기술 선정 토론회’는 팀에서 민주적으로 기술 결정을 하기 위한 장치입니다. 팀원 전체에게 영향을 줄 수 있는 기술을 도입하고 싶을 때, 누구든 도입하려는 근거가 담긴 문서를 작성해 안건을 제기할 수 있습니다. 그 후 팀원들에게 공유해 관련된 지식 학습을 요청하여 비슷한 수준의 배경 지식과 이해를 가질 수 있도록 합니다. 일정 시간이 지난 후, 해당 기술의 도입에 대한 팀원들의 의견을 수렴하여 토론회에서 해당 기술과 관련된 토론을 진행합니다. 최종적으로 많은 팀원이 선호하는 기술 도입을 결정합니다.
지난 8월, 팀에서 사용하는 서버 상태 관리 라이브러리에 대한 기술 선정 토론회가 열렸습니다. 기존의 컬리몰에서는 API 응답으로 받은 서버의 데이터를 전역 상태 관리 라이브러리인 redux에 저장하고, 그 데이터를 리액트 어플리케이션 전역에서 관리하고 있었습니다. 데이터 중심의 상태 관리를 위해 서버 상태를 관리하는 라이브러리 사용에 대한 의견이 있어, 논의를 통해 React Query를 도입했습니다.
React Query에 대해서는 이 글을 읽고 계신 분들 중 알고 계시거나, 직접 사용해 본 경험이 있는 분들이 있을 것입니다. React Query 문서에 따르면 다음과 같이 정의되어 있습니다:
Hooks for fetching, caching, and updating asynchronous data in React
React Query는 리액트 어플리케이션에서 서버의 상태를 불러오고, 캐싱하고, 또 지속적으로 동기화 및 업데이트하는 작업을 도와주는 라이브러리입니다. 리액트 개발자라면 익숙하실 hook을 사용해 서버의 데이터를 사용할 수 있다는 특징이 있습니다.
React Query는 비동기 데이터 관리를 위한 전문 라이브러리입니다. 따라서 redux를 사용할 때보다 다양한 비즈니스 요구사항을 빠르게 달성할 수 있게 됩니다. 또한 redux에서는 API 요청을 위해 여러 개의 action과 reducer가 필요해 코드 복잡성이 올라가고 가독성이 떨어졌다면, React Query를 사용함으로써 유지보수가 용이해집니다. 뿐만 아니라 React Query에서 제공하는 옵션들을 활용하면 다양한 이벤트 발생 시, 서버 상태 동기화 시나리오를 충족할 수 있습니다.
고민: 쉽게 쓰여지지 않은 코드
이번 필터 프로젝트는 redux에서 React Query로 전환한 초석입니다. 따라서 의사 결정 후, 프로젝트 초반에 전역 설정부터 이루어져야 했습니다. 먼저 공통적으로 사용할 것들에 대해서만 팀에 사전 공유 후, 관련하여 설정을 진행했습니다. 이를 통해 병렬적으로 이루어지는 다른 프로젝트들에도 혼선이 없도록 방지했습니다. 또한 기존에 redux로 관리되던 데이터를 분리함에 따라, 상태의 유지 시기 등 기존과 다른 부분을 고민하면서 프로젝트를 진행해야 했습니다. 그러므로 시간 관리 측면 역시 주요한 고려 대상 중 하나였습니다. 역시 인생은 살기 어렵다는데, 코드가 쉽게 쓰여진다는 것은 부끄러운 것이라는 윤동주 시인의 말이 맞았습니다. (절대 제가 잘 못하는 것이 아닙니다!)
이점: 두근두근 기대 효과
React Query로 전환함에 따라 다음과 같은 장점을 기대할 수 있었습니다.
먼저, 고객 측면에서는 React Query에서 제공하는 옵션들을 활용하여 서버 상태를 동기화할 수 있고, 품절이나 가격 변동 이슈 등 실시간으로 고객이 정보를 제공 받을 수 있는 것을 기대했습니다.
또한 기술적으로도 서버에서 가져온 데이터를 효율적으로 상태 관리함으로써 불필요한 API 호출을 방지할 것을 기대했습니다. 물론 서버에서도 자체적으로 데이터의 캐싱 작업이 이루어지고 있습니다. 그러나 이러한 값을 가져오는 것 역시 일련의 통신 과정이 필요하다고 생각하여, 서버 캐싱 시간인 5분보다 stale time을 1분으로 짧게 설정하였습니다.
결과 및 의의
이렇게 필터 프로젝트를 통해 구체적으로 어떤 점이 좋아졌을까요?
1) 고객: 상품을 선택하는 위치의 변화
먼저, 고객 측면에서는 상품 탐색 과정에 대한 경험이 개선되었습니다. 위의 이미지에서 보시는 것과 같이, 데이터가 이를 뒷받침하고 있습니다. 아래 자료는 필터 배포 후 약 한 달 간 고객이 평균적으로 상품을 선택하는 위치를 컬리의 데이터 프로덕트 팀에서 분석해 주신 결과입니다. 고객이 원하는 상품을 찾기 위해 보통 32번째 상품까지 확인해야 했다면, 필터를 적용함으로써 평균 19번째 상품에서 구매 결정을 할 수 있도록 개선되었습니다. 다시 말해, 필터 도입으로 고객에게 필요한 상품을 더 상단에 보여줄 수 있도록 변화하였습니다.
2) 기술: 불필요한 API 호출 방지
뿐만 아니라 필터는 사용자가 쉽게 적용하고 해제할 수 있습니다. 이 과정에서 들어갔을 숱한 API 호출을 React Query를 사용함으로써 방지할 수 있었습니다. 또한 사용자가 다른 화면을 보고 컬리몰에 되돌아왔을 때에도, 서버에서 금방 새로운 데이터를 받아 볼 수 있게 개선되었습니다.
3) 팀: 함께 성장하는 문화
더 나아가, 팀 측면에서도 단순히 주어진 기획이나 디자인 가이드에 맞춰서만 개발하는 것이 아니라, 주도적으로 개발하고 함께 고쳐나가는 문화를 더욱 공고히 할 수 있었습니다. 다음의 두 사례로 설명 드릴 수 있을 것 같습니다.
눈썰미 있는 분이라면 앞서 선크림을 찾는 여정에서 제가 참조 드린 링크를 통해 눈치 채셨을 수 있을 것 같습니다. 바로 url에 필터 결과를 저장하는 것입니다. 이전의 컬리몰에서는 새로고침 시 페이지가 초기화되어 사용자가 정렬 값을 변경하거나 다른 페이지를 보고 이전 페이지로 돌아올 경우, 기존에 보고 있던 값을 확인할 수 없었습니다. 특히나 필터의 경우, 많은 값을 다시 선택해야 하기 때문에 이는 고객 경험을 해칠 수 있습니다. 필터 결과를 url에 저장함으로써 사용자가 보고 있는 상품 목록을 유지하고 또 공유할 수 있도록 변경했습니다.
또한, 어플리케이션과 다르게 모바일 웹에서 상품을 검색하면, 적확한 키워드에 대하여 하이라이트 처리가 되어 있습니다. 이 역시 비즈니스 요구사항은 아니었지만, 사용자 편의를 위하여 웹 팀에서 먼저 제안 및 개발한 기능입니다.
주도적으로 개선하는 분위기 뿐만 아니라, 함께 배우고 성장하는 팀 문화 역시 강화되었습니다. 보시는 이미지는 제가 올린 PR에 팀 분들이 남겨주신 코멘트입니다. 함께 로직에 대해 고민하고, 더 나은 코드를 위해 노력하는 과정을 통해 바쁜 개발 일정 속에서도 좋은 코드 품질을 유지할 수 있었습니다.
💜 What is Next?
컬리와 커머스 웹 개발 팀에서는 지금과 같이 지속적으로 고민하고 함께 성장하며 서비스를 개선하고 확장해 나갈 예정입니다. 이 글을 재미있게 읽으셨다면, 컬리의 서비스와 웹 개발 팀의 변화를 계속해서 기대하고 함께 지켜봐 주세요. 감사합니다.
컬리에서 함께 서비스를 만들어 가고 싶으시다면? 👉 커머스 플랫폼 개발자 채용 공고 바로가기