← Back to Projects

DERMA:CODE

상담사의 감각에 의존하던 피부 상담을 데이터로 구조화한 상담 플랫폼.

회사가이아랩스
역할프론트엔드 초기 디자인·브랜딩
팀 구성프론트엔드 1 백엔드 1 디자인 1
기간2024년 11월 - 현재
운영테이아 강남·명동 실사용

3D 스캐너로 얼굴을 촬영하여 AI 피부 분석을 진행하고, 분석 결과를 기반으로 추천 시술 조합과 시술 후 예상 결과까지 시뮬레이션하는 상담 도구입니다. 상담사는 해당 소프트웨어를 기반으로 고객에게 상담을 진행합니다. 프론트엔드 전 영역과 V1까지의 디자인·브랜딩을 맡았습니다. 시뮬레이션이 정식 기능이 된 뒤에는 엔진 고도화에 집중하기 위해 V2 제품 설계와 요구사항 명세를 먼저 정리하고 디자이너를 합류시켰습니다. 테이아 강남점에서 실사용되다가 2026년 7월 명동점까지 확장되었습니다.

문제와 해결

문제

개원 이래 누적된 피부 분석 통계를 스크립트로 직접 조회하고 연령대·성별로 분리해 검증하니, 대부분 환자의 점수 결과가 좁은 구간에 몰려 있었습니다.

판단

절대 점수만으로는 환자 간 차이를 설명하기 어려워 코호트 내 상대적 위치를 보여주는 방식으로 전환했습니다.

Q1/Q3 사분위 기반 산식을 운영진에게 제안했습니다. 보정식을 적용해 통계를 다시 산출하고, 점수 쏠림이 완화된 것을 확인한 뒤 최종 계산식에 반영했습니다.

해결

평균 기준 정규화로는 대다수가 좁은 구간에 몰려 차이가 드러나지 않았습니다. p10~p90 마커 사이를 선형 보간해 코호트 내 위치를 산출하고, 25/50/75 사분위 컷오프로 심각도를 4단계로 분류했습니다. 표본이 부족한 연령대는 상위 코호트로, 성별 미상은 통합 코호트로 폴백했습니다.

정규화는 제품 내 표시를 위한 임시 보정이고, 근본 원인은 모델 성능 문제로 판단했습니다. 이 분석 결과를 공유해 회사 차원의 모델 문제 정의로 연결했습니다.

결과

현재 DERMA:CODE 모델을 재학습하고 있으며, 학습 데이터를 만드는 어노테이션 툴(human-in-the-loop) 개발에 참여하고 있습니다.

문제

VoC에서 "시술 결과를 미리 보고 싶다"라는 코멘트가 반복적으로 접수되었습니다. 필요한 기능임이 분명했지만, 3D 얼굴을 시술별로 변형해 보여주는 것이 실제로 가능한지는 확인되지 않아 기능 추가를 제시하기 조심스러웠습니다.

판단

요청을 바로 기능으로 제안하기보다, 구현 가능성과 비용을 먼저 확인했습니다.

첫날에는 3D 파일을 어느 정도까지 변형할 수 있는지 확인해 구현 범위를 가늠했습니다. 이후 2주 동안 3D 얼굴 메시를 시술별로 변형하는 프로토타입을 만들고, 실제 화면에서 원하는 결과를 만들 수 있는지 검증했습니다.

해결

시술 효과를 약 6개의 변형 파라미터로 모델링하고, 시술별 파라미터 값은 별도의 설정 페이지에서 관리할 수 있도록 백엔드 데이터로 분리했습니다.

이를 통해 엔진 로직과 시술 정의를 분리하고, 새로운 시술을 추가할 때 메인 3D 처리 엔진을 수정하지 않아도 되는 구조를 만들었습니다.

결과

동작하는 프로토타입을 근거로 정식 기능 승격을 제안했고, 실제 제품 기능으로 채택되었습니다. 현재 Derma:Mirror라는 이름으로 제품 내에서 사용되고 있으며, 마케팅 콘텐츠와 투자 실사 데모에도 활용되었습니다.

문제

V1에는 GNB가 5개로 운용되고 있었고, 새로운 기능이 추가되면서 GNB 구조를 다시 조정할 필요가 있었습니다. 상담사가 실제 상담 과정에서 어느 기능을 활용하는지, 어떤 화면을 중심으로 상담을 진행하는지는 확인되지 않은 상태였습니다.

판단
두 달간 탭 사용률%
메인 탭84
업셀링 탭4.5
2개월간 이벤트 데이터로 탭 사용률을 계산하고, Hotjar Heatmap으로 실제 상담 흐름을 교차 확인했습니다.

이벤트 데이터로 탭별 사용률을 계산하고, Hotjar Heatmap으로 실제 상담 흐름을 확인했습니다.

두 달간 측정한 결과, 메인 기능을 담당하는 탭 사용률은 84%인 반면 업셀링을 위해 분리한 탭은 4.5%에 그쳤습니다. Heatmap에서도 상담사가 별도 업셀링 탭으로 이동하기보다 솔루션 추천 흐름 안에서 상담을 이어가는 패턴을 확인했습니다.

해결

업셀링 탭을 GNB에서 제거하고, 신규 기능을 새 탭으로 추가하는 대신, 솔루션 추천 과정에서 시너지 솔루션을 함께 노출하는 구조를 제안했습니다.

상담 흐름을 별도 탭으로 분리하지 않고, 기존 추천 과정 안에서 추가 솔루션까지 이어서 확인할 수 있도록 V2 GNB와 화면 구조를 재편했습니다.

결과

V2에서 업셀링 전용 탭을 제거하고 추가 기능을 중심으로 탭 구조를 재편했습니다.

문제

시술 시뮬레이션의 모공·주름·홍조 보정이 Canvas 2D 위에서 4096×2048, 약 8M 픽셀을 CPU 한 스레드로 처리하고 있어, 파라미터를 하나만 변경해도 화면이 멈추는 수준으로 UX가 저하되고 있었습니다.

판단
같은 효과, 두 구현ms
Canvas 2D (CPU 픽셀 루프)1,117
WebGL (GPU 셰이더)50
동일한 4096×2048 입력 텍스처와 효과를 내부 비교 페이지에서 각각 구현해 측정했습니다.
효과 하나의 GPU 처리 243ms, 어디에 쓰였나ms
upload 5.5draw 0.3readback 218.7
합계 243 · 나머지 18.5는 기타
GPU로 이관한 실제 효과 하나의 처리 구간을 upload·draw·readback으로 나눠 계측했습니다.

먼저 동일한 효과를 Canvas 2D와 GPU로 각각 구현해 처리 시간을 비교했습니다. Canvas 2D는 1117ms, GPU는 50ms로 약 22배 차이가 났고, 결과의 동일성도 확인해 GPU 이관을 결정했습니다.

이후 실제 효과 하나를 GPU로 이관한 뒤 구간별 처리 시간을 다시 측정했습니다. 전체 243ms 중 GPU 연산은 0.3ms에 불과한 반면, CPU readback이 218.7ms를 차지했습니다. GPU의 계산 성능보다 GPU에서 CPU로 데이터를 되돌려 받는 과정이 실제 병목이었습니다.

해결

효과를 하나씩 GPU로 처리하고 매번 readback하는 대신, 여러 효과를 GPU에서 연속 처리한 뒤 마지막에 한 번만 readback하도록 구조를 변경했습니다.

또한 계측 과정에서 applyRednessCorrection()에 vertexUVs 인자가 누락되어 얼굴 영역이 아닌 전체 영역을 처리하고 있던 CPU 버그를 발견했습니다. 이를 수정해 해당 처리 시간을 17.4초에서 5.1초로 단축했습니다.

결과
보정 한 번의 처리 시간초 · 낮을수록 좋음
  1. –이관 전22.3
  2. 1효과 일부 GPU 이관17.4
  3. 2CPU 버그 한 줄 수정vertexUVs 누락5.1
  4. 3GPU 체인, readback 1회3.2
최초단계최종

GPU 처리 구조와 CPU 처리 로직을 함께 개선해 시뮬레이션 전체 처리 시간을 22.3초에서 3.2초로 단축했습니다.

문제

스캐너가 내보내는 .dwb 3D 메시와 텍스처를 브라우저에서 파싱하고 렌더링하는 상담 화면의 LCP가 16.7초까지 발생했습니다. Lighthouse와 DevTools로 렌더링 과정을 확인한 결과, 진단 API 응답을 기다리는 렌더 게이트, 임계 경로에 포함된 미사용 폰트, 3D 리소스 로딩이 초기 화면을 지연시키고 있었습니다.

판단

한 번에 여러 요소를 변경하지 않고 원인별로 나눠 단계적으로 계측했습니다. 각 변경이 LCP에 미치는 영향을 확인한 뒤 다음 최적화를 진행했습니다.

해결
단계별 LCP초 · 낮을수록 좋음
  1. –최초 측정16.7
  2. 1렌더 게이트 제거14.2
  3. 2미사용 폰트 제거2,827ms 요청 제거 · LCP 변화 없음14.2
  4. 3로딩 화면 추가23.7롤백
  5. 42D 우선 렌더 + 3D 지연 로딩7.9
  6. 5서버 리사이즈 + WebP3,506KB → 123KB5.7
최초단계최종악화 · 롤백
동일 상담 화면을 Lighthouse와 Chrome DevTools로 확인하며 변경 단계별 LCP를 기록했습니다.

1. 렌더 게이트 제거 → LCP 14.2초

2. 2,827ms가 걸리던 미사용 Geist 폰트 요청 제거 → 다른 리소스와 병렬로 로드되고 있어 LCP는 14.2초로 유지

3. 로딩 화면 추가 → LCP가 23.7초로 악화. 오버레이가 LCP 요소를 가리고 있음을 계측으로 확인하고 롤백

4. 2D 콘텐츠 우선 렌더링 + 3D 리소스 지연 로딩 → 7.9초

5. 서버에서 Sharp로 이미지 리사이즈 및 WebP 변환 → 리소스 3,506KB → 123KB, 최종 5.7초

결과
16.7s→5.7s−66%

LCP를 16.7초에서 5.7초로 약 66% 단축했습니다. 각 단계의 측정 결과와 실패한 로딩 화면의 롤백 과정까지, 전체 과정을 블로그에 공개했습니다.

↗ 5단계 측정 로그 (블로그)

Tech Stack

Next.js 15React 19TypeScriptReact Three Fiberthree.jsMediaPipeTensorFlow.jsKonvaTanStack QueryZustandreact-i18nextTailwind 4