새로운 컬리몰 NX를 소개합니다.

새로운 컬리몰을 만드는 과정을 소개합니다.

Intro

헤어질 결심: Decision to Leave GODO

기존 컬리몰은 고도몰 소스위에 구현된 서비스였습니다. 더 많은 상품을 판매하고 싶고 성장하고 싶은 컬리몰은 소위 '탈고도'라 불리는, 기존 레거시 시스템을 벗어나고자 하는 시도를 해왔습니다. 컬리 커머스 웹프론트 팀은 탈고도의 일환으로 NX라 이름지은 Nextjs 라이브러리 기반의 프로젝트를 2021년부터 시작했으며, 2021년 12월 당시엔 컬리몰의 일부 서비스인 비밀번호 찾기, 찜하기 모바일 페이지가 NX로 이관되어 있는 상태였습니다.

탈고도를 넘어 뷰티컬리로!

2022년 들어 기존 상품, 주문, 회원 시스템을 완전히 새로 만드는 프로젝트가 전사적으로 진행되었고 큐레이티드 마켓플레이스(3P), 뷰티컬리 등의 새로운 컬리몰 스펙 또한 구현이 필요했습니다.
웹 프론트팀은 각 프로젝트의 비즈니스 요구사항을 구현하는 한편 레거시 시스템을 NX로 전환하는 작업을 진행했습니다. 그 결과 2022년 8월, 컬리 자체의 php 서비스로 구현된 페이지 일부를 제외한 모든 서비스를 NX로 전환하게 되었습니다. 이 글에선 웹프론트팀이 레거시 시스템을 걷어내면서 적용했던 Practice들과 그 성과를 소개합니다.

유저가 겪는 기분좋은 변화

상품상세를 보는데 걸리는 시간. 1.5초

최근 컬리몰 웹 서비스를 써보신 분들은 기존보다 훨씬 쾌적하다는 것을 느끼셨을 겁니다. 레거시 상품상세 페이지는 React, Vue 및 바닐라 자바스크립트로 파편화 되어 개발 및 유지보수 되었지만 NX에서 SSR로 구현하여 성능향상을 이끌어냈습니다. 페이지 성능을 가늠하는 주요 메트릭인 LCP 점수를 3.4초 → 1.5초 로 줄였고 그에 따라 사용자가 느끼는 체감성능을 향상시켰습니다. 상품 상세는 PC, 모바일 뿐만 아니라 웹뷰로 안드로이드, 아이폰 앱에도 제공하는 페이지이기 때문에 컬리몰을 사용하는 모든 사용자에게 보다 빠른 서비스를 제공하고 있습니다.

Before

NX 이전

After

NX 이후

유저에게 통일성 있는 화면을 제공해요

레거시의 경우 공통된 UI가 정의되지 않아 페이지마다 다른 인터렉션 UI를 제공하곤 했습니다. NX로 전환된 페이지에선 일관된 인터랙션 UI를 제공합니다.

Before

NX 이전

After

NX 이후

한눈에 들어오는 URL

레거시 소스에서 제공하는 URL은 길고 이쁘지 않았습니다. NX로 전환하면서 간략하고 기억하기 쉬운 URL을 제공할 수 있게 되었습니다.

페이지 NX 레거시
상품상세 https://www.kurly.com/goods/51483 https://www.kurly.com/shop/goods/goods_view.php?&goodsno=51483
메인 https://www.kurly.com/main https://www.kurly.com/shop/main/index.php
장바구니 https://www.kurly.com/cart https://www.kurly.com/shop/goods/goods_cart.php
고객센터 https://www.kurly.com/board/notice https://www.kurly.com/shop/board/list.php?id=notice

하나의 URL로 PC/MOBILE 둘 다.

레거시 시스템에서의 URL은 PC/MOBILE 별도 URL을 사용했습니다. 하지만 NX는 하나의 URL에서 처리가 가능합니다. 또한 보다 짧아진 URL을 제공합니다.

페이지 NX 레거시
메인 https://www.kurly.com/main PC: https://www.kurly.com/shop/main/index.php
MOBILE: https://www.kurly.com/m2/index.php

지난 7개월간의 여정

레거시는 코드만 레거시가 아니더라..

레거시 시스템은 레거시 코드만 가지고 있는 것이 아니었습니다. 스펙의 히스토리가 적절히 관리되지 않았으며 그 내용 또한 일관성이 부족했습니다. 웹프론트 팀은 기존 코드를 읽으며 스펙을 파악하는 한편 기획팀에 기획서 정리를 요청드렸습니다. 이 과정에서 많은 도움 주셨던 기획팀 분들께 감사의 말을 전합니다.

상품 상세 뒤엎기

상품 상세엔 다양한 구현방법으로 각종 UI가 구현되어 있었습니다. 구현방법도 제각각이었습니다.

  1. 코드에 상품번호로 분기 처리. 아래와 같은 코드가 나열되어있다고 보시면 됩니다.
    if (productNo === '1234') {
      // 상품상세 구현 블라블라
    }
    
  2. 백오피스툴에 구현방법 정의 1번과 비슷하지만 구현이 백오피스툴에 정의되어 있고, API로 해당 스크립트를 로드해 실행하는 방식이었습니다. 이 구현은 옮겨오는 것이 정말 힘들었는데, 상품마다 구현에 사용된 라이브러리가 제각각이었기 때문입니다.

    백오피스툴에 구현된 코드 예시

    백오피스툴에 구현된 코드 예시

하나하나가 컬리의 상품들을 빛내주는 구현이었지만 N만개의 상품 각각에 따로 적용될 수 있는 구현 스펙을 정리하지 않고는 새로운 구현에서도 복잡한 코드를 제거할 방법은 없어 보였습니다. 모든 상품에 공통적으로 적용될 수 있는 스펙을 구현하는 대신 특정 소수의 상품에만 적용되는 UI의 스펙아웃을 해달라는 의사 결정을 요청드렸고, 리더십이 이를 받아들여주신 덕에 레거시 스펙을 제거하고 상품상세 페이지 본연의 기능 구현에 집중할 수 있었습니다.

코드 품질을 높이기 위한 노력

레거시 시스템을 걷어내고 NX에 시스템을 옮겨왔지만, 작성한 코드는 다시 레거시가 되기 때문에, 최대한 일관성있고 관리되는 코드를 작성하기 위해 노력했습니다.

Lint룰 추가

상품상세, 장바구니, 주문서등 많은 코드가 NX로 옮겨올 예정이어서 우선 Lint rule부터 추가했습니다. 작성된 코드에 Lint를 추가하고 강제하는건… 정말 어려우니까요. 우선 lint-stage를 추가해서 commit전에 변경된 파일의 정적 분석이 실행되도록 했습니다. lint-staged

또한 React & Typescript를 사용한다면 반드시 error로 지정해서 써야하는 3대장을 추가했습니다. lint-rules

하지만 3대장의 옵션을 error로 바로 적용할순 없었습니다. 왜냐하면 error로 바꿀 경우 수정해야 하는 코드가 790개 이상이었기 때문입니다. 790_errors

이외에도 팀에서 합의된 컨벤션은 Lint 룰에 등록했습니다. 그 결과 스타일 준수여부에 대한 상호 피드백을 대폭 줄인, 좀더 빠르고 의미있는 코드리뷰를 정착시킬 수 있었습니다. 이미 작성된 코드중 수정이 필요한 코드를 3월엔 한 주에 100개씩만 줄이자는 목표를 가지고, 4월 즈음엔 360개까지 꾸준히 줄여나갔던 것 같습니다. 그리고 반복적으로 발견되는 안티패턴을 공유했습니다. 그 결과 구현된 서비스는 훨씬 많지만 정적분석 결함은 비교적 낮은 상태를 유지할 수 있었습니다.

- LOC 정적결함 수 정적결함 / LOC
2022년 01월 44,699 790 1.76%
2022년 08월 163,304 211 0.12%

공식문서는 항상 가까이

개인적으로 라이브러리 공식문서를 시간이 날때마다 읽는 것을 중요하게 생각합니다. 그러다보면 성능 개선 포인트들을 찾거나 더 좋은 코드를 만들 수 있는 팁을 얻게 되거든요. 빌드시간에 대한 고민을 하던 중 node_module 외에 nextjs 빌드 결과물까지 cache하면 빌드 소요시간이 단축될 수 있다는 문서를 보고 프로젝트에 적용했습니다. Advanced Features: CI Build Caching-Nextjs

그 결과 9분 걸리던 빌드가 6-7분 걸리도록 개선되어 약 20%의 속도향상 효과를 볼 수 있었습니다.

페이지 성능도 측정하고 있어요

NX는 성능테스트를 매 PR마다 수행합니다. 아직 모든 페이지가 대상은 아니고, 성능에 가장 민감한 상품상세 페이지를 대상으로 합니다. 지표에 빨간불이 있을 경우, 상세한 벤치마크를 보여줍니다. 아직은 점수가 낮아도 merge blocking을 하지 않지만, 추후 점수가 낮게 측정되면 아예 코드베이스에 반영되지 않도록 강제할 예정입니다. lighthouse

Outro

웹팀은 드림팀은 아니지만.. 좋은 팀입니다.

레거시 시스템에 구현된 컬리몰 스펙을 이해하고 있는 개발자가 팀내에 단 한분이 계셨습니다. 빠른 서비스 성장에 따른 요구사항이 물밀듯 들어왔지만 그 한분만큼 빠르게 처리할 수 있는 사람이 없어 한분께 일이 몰리는 상황이었습니다. 하지만 이젠 도메인 별 전문가가 팀내에 존재하게 되어 각 도메인의 요구사항을 보다 빠르게 처리할 수 있는 준비가 되었습니다.

컬리몰 웹프론트팀을 응원해주세요

7개월간 커머스 개발 웹개발2팀은 열심히 달려왔습니다. 목표한만큼의 성과를 이뤄냈다고 생각하지만 버그제보가 올라오는 걸 보면 가슴이 아프고, 빨리 수정해서 더 좋은 서비스를 만들고 싶습니다. Lighthouse 점수가 100점이 되지 않은 부분이 마음에 걸리고 더 욕심이 납니다. 앞으로도 사용자 중심의 컬리몰 서비스를 만들기 위해 달려보겠습니다.