← Back to Projects

CPE

피부미용 의원의 실제 업무 흐름을 반영해 상담·결제 프로세스를 시스템화한 운영 프로그램.

회사가이아랩스
역할프론트엔드
팀 구성프론트엔드 2 백엔드 3 디자인 1 QA 5
기간2025년 2월 - 현재
운영테이아 의원 실사용

CRM과 EMR의 성격을 함께 갖는 피부미용 의원 특화 마케팅·운영 프로그램입니다. 의료진과 백오피스 30~50명이 의원별로 동시 사용하며, 접수부터 상담·결제·시술까지 원내 주요 업무 전반을 지원합니다. 프론트엔드 2명 중 1명으로 참여했으며, 단일 지점 V1을 운영하며 확인한 문제를 바탕으로 멀티 지점 V2를 재설계했습니다. V1 운영과 V2 개발을 병행한 뒤 서비스 중단 없이 전환했습니다.

문제와 해결

문제

고객 정보와 이전 시술 구매 이력처럼 상담 중 함께 확인해야 하는 정보가 전부 다른 탭과 여러 레이어 하위에 있어, 상담사가 상담 중 여러 화면을 오가야 했습니다.

판단

기능을 추가하기 전에 의원을 직접 방문해 상담사들을 인터뷰했습니다. 그 결과 필요한 정보 자체가 부족한 것이 아니라, 이미 있는 정보가 상담 흐름에 맞게 배치되어 있지 않은 문제라고 판단했습니다.

상담사가 실제 상담에서 정보를 확인하는 순서에 맞춰 관련 정보를 한 화면에 모으는 방향으로 결정했습니다.

해결

고객 정보와 이전 시술 이력을 상담 화면 안에서 확인하고, 같은 화면에서 시술을 구입하고 할인을 적용할 수 있도록 상담실 화면을 재구성했습니다.

결과

상담 중 화면을 이동하지 않고 정보 확인부터 구매·할인 적용까지 한 화면에서 처리할 수 있게 되었고, 이 구조는 V2에도 승계되었습니다.

문제

로그인 이후에만 사용하는 운영 도구인데도 SSR을 전제로 한 Next.js App Router 위에서 동작하고 있었습니다. 대부분의 컴포넌트에 'use client'가 붙어 있어 서버 컴포넌트의 이점을 활용하지 못하면서 프레임워크의 제약은 그대로 받는 구조였습니다.

판단

V2 새 저장소를 시작하는 시점에 React + Vite로 전환할 것을 제안했습니다.

프레임워크를 바꾸는 데 따른 장단점과 기존 구조에서 잃고 얻는 것을 문서로 정리해 팀의 합의를 먼저 얻었습니다.

해결

폴더 구조에는 FSD를 도입해 도메인 경계를 파일 시스템에 명시적으로 드러냈습니다.

프론트엔드 2명이 같은 저장소에서 개발하는 상황에서 공용 코드와 도메인 기능의 경계를 명확히 하고, 디자인 시스템 → 공용 컴포넌트 → 도메인 기능 순으로 단계적으로 이관했습니다.

결과

V1 운영과 V2 개발을 3개월간 병행하면서 무중단으로 전환했습니다.

문제

항목 하나를 계산할 때는 드러나지 않았지만, 시술 패키지처럼 여러 항목이 묶이면 반올림 오차가 누적되어 화면마다 표시되는 금액이 달라지는 문제가 있었습니다.

판단

금액 계산의 기준을 최종 표시 금액으로 통일하고, 나머지 값을 역산하는 방향으로 정했습니다.

절사 방식과 할인·부가세 적용 순서는 프론트에서 임의로 정할 수 없어 백엔드와 계산 규칙을 명시적으로 합의했습니다.

해결

반올림 시점을 개별 항목에서 합계 단계로 이동하고, 표시 금액에서 공급가액을 역산한 뒤 부가세를 나머지 값으로 도출했습니다.

이를 통해 항목이 몇 개 묶이더라도 공급가액과 부가세의 합이 항상 최종 표시 금액과 일치하도록 만들었습니다.

결과

V1에서 금액이 어긋나는 경로를 제거했습니다.

다만 계산 로직이 프론트에 남아 있으면 같은 문제가 다른 화면에서 재발할 수 있어, V2에서는 금액 계산의 SSOT를 백엔드로 이동하고 프론트는 표시만 담당하도록 변경했습니다.

↗ 금액 처리에서 배운 것 (블로그)

문제

구매 항목을 회수·환불했을 때 거래·영수증 응답에서 일부 경로가 누락되고 있었습니다. 화면에서는 정상처럼 보이지만 실제 금액 데이터가 남는 결함이었습니다.

판단

단순히 수정을 요청하기보다, 어떤 데이터가 잘못되었고 어디까지 영향을 미치는지 먼저 확인했습니다.

환불 데이터가 정산 과정의 여러 곳에서 사용되고 있어, 특정 API만 수정했을 때 다른 화면에 영향을 주는지도 함께 확인해야 했습니다.

해결

3개 엔드포인트의 응답을 대조해 기준이 되는 데이터를 특정하고, 환자·거래·청구서·영수증 ID를 포함한 재현 케이스를 작성했습니다.

백엔드 요청은 결함·신규 API·필드 추가·응답 최적화 등 7개 범주로 나누고, 각 항목의 블로킹 여부를 상태로 표시해 전달했습니다.

결과

백엔드 수정이 필요한 항목 중 화면 개발을 막는 문제에는 우회 로직을 먼저 적용해, API 변경 전에도 개발을 이어갈 수 있도록 했습니다.

문제

V1에서는 명확한 디자인 시스템 없이 각자 페이지 단위로 작업하다 보니, 같은 역할의 컴포넌트가 페이지마다 따로 만들어지고 재활용되는 컴포넌트가 거의 없었습니다.

V2 새 저장소를 시작하면서 초기 구조를 어떻게 잡느냐가 이후 개발 속도와 일관성에 영향을 주는 상황이었습니다.

판단

초기 기능 개발보다 디자인 시스템과 공용 UI를 먼저 정립하는 방향으로 결정했습니다.

첫 2주 동안은 화면 개발 속도가 느려지더라도, 이후에는 동일한 UI를 다시 만들지 않고 기존 컴포넌트를 확장할 수 있도록 기반을 먼저 다듬었습니다.

해결

프리미티브 20여 개와 Storybook을 먼저 구축하고, 이후 팀 전체가 이를 기반으로 화면을 개발하도록 했습니다.

결과

팀 전체가 신규 컴포넌트를 매번 만드는 대신 기존 컴포넌트를 확장하는 방식으로 개발하게 되었고, 현재 컴포넌트의 90% 이상이 재사용되고 있습니다.

Tech Stack

V1Next.js 14 (App Router)V2React 19Vitereact-router v7TypeScript 5.9ZustandTanStack QueryTailwind 4StorybookVitestFSD