건강검진 결과 스파이더 그래프
1. 스파이더 그래프(Radar Chart) 배경
건강검진 데이터는 혈압, 혈당, 간수치, BMI 등 여러 지표를 동시에 확인해야 전반적인 건강 상태를 파악할 수 있다. 이를 위해 레이더 차트(Radar Chart)를 도입한다. 레이더 차트는 여러 항목을 한 화면에 묶어 보여주므로 다음과 같은 이점이 있다.
- 사용자가 자신의 취약 항목을 한눈에 파악할 수 있다.
- 과거 데이터와 현재 데이터를 겹쳐서 비교하기 용이하다.
1-1. 라이브러리 선택 기준
우리 서비스는 모바일 웹 환경이며, 의료/민감 정보를 다루고, 초기 진입 시 데이터 로딩이 많다는 특징이 있어서 다음 기준을 고려했다.

- 기능 지원: 레이더 차트를 기본으로 제공하는가? 축 라벨, 툴팁, 영역 채우기 등 커스터마이징이 가능한가?
- UX & 퍼포먼스: 모바일 터치 반응성, 작은 화면에서의 가독성, 렌더링 성능 최적화 여부.
- React 호환성: React 컴포넌트 방식(선언형)으로 사용하기 쉬운가? SSR 환경 호환성.
- 생산성: 앱잼 MVP 기간 내에 빠르게 구현 가능한가? 문서와 예제가 풍부한가?
1-2. 후보 라이브러리 비교
① Recharts
React에서 쓰기 쉬운 선언형 차트 컴포넌트 라이브러리이며, React + D3 조합이고 SVG 기반으로 동작한다.
레이더 구현 관점의 핵심 포인트
- RadarChart 컴포넌트를 공식 API로 제공한다. 데이터 포맷/중심 좌표/반응형 배치 같은 기본 요소를 “컴포넌트 조합”으로 해결한다.
- 의료 서비스의 요약 화면처럼 “축 개수 5~8개, 데이터 포인트 적음”인 경우 SVG DOM 수가 폭발하지 않아 운영 부담이 비교적 작다. (데이터가 많아질수록 SVG는 DOM 노드가 늘어 무거워질 수 있다.)
장점
- 개발 속도: React 컴포넌트 조합으로 POC → 적용이 빠르다.
- 스타일링 일관성: SVG 기반이라 CSS/디자인 시스템과 맞추기 쉽고, “우리 UI 톤”을 유지하기 편하다.
- 레포 내 확장: 레이더뿐 아니라 라인/바 등 다양한 차트를 같은 패턴으로 추가하기 쉬워 “차트 스택 통일”에 유리하다.
단점
- “축 모양 자체를 크게 바꾸기”, “텍스트 배치를 완전히 새로 설계하기” 같은 극단적 커스텀 디자인에는 한계가 생길 수 있다.
- 줌/드래그/브러싱 같은 고급 인터랙션이 핵심이면 다른 선택이 더 적합할 수 있다.
우리 서비스 적합도
- 스파이더 그래프가 정밀 분석 도구가 아니라 요약 시각화라면 Recharts가 가장 비용 대비 효율이 좋다.
② Chart.js (+ react-chartjs-2)
Chart.js는 차트를 HTML5 Canvas로 렌더링하는 범용 라이브러리다.
React에서 보통 react-chartjs-2를 통해 컴포넌트 형태로 감싸서 사용한다.
레이더 구현 관점의 핵심 포인트
- Radar chart를 공식 문서에서 type: 'radar'로 지원한다.
- 반응형 옵션도 공식적으로 제공한다.
장점
- Canvas 기반 성능: 데이터 포인트/애니메이션이 많아질수록 SVG보다 Canvas가 유리한 상황이 많다. (DOM 노드 증가가 없기 때문이다.)
- 옵션/플러그인 중심 확장: 설정 객체로 표현을 폭넓게 바꾸는 데 강점이 있다. 문서에서도 “플러그인, 트리 셰이킹” 같은 개념을 주요 요소로 안내한다.
단점
- React에서 JSX로 조립 느낌이라기보다, 옵션 객체,등록해야 하는 요소들,래퍼 규칙을 익혀야 해서 초기에 코드가 무거워질 수 있다.
- Canvas는 스타일을 CSS로 만지는 감각이 SVG보다 떨어지고, 접근성/테스트 측면에서 추가 고려가 필요해질 수 있다. (캔버스는 그 자체가 하나의 노드이기 때문이다.)
우리 서비스 적합도
- “레이더 차트는 표준 형태로 두되, 옵션/플러그인으로 디테일을 계속 만질 가능성”이 크면 후보가 된다.
- 다만 MVP 속도 + React 개발 경험의 자연스러움에서는 Recharts가 보통 더 편하다.
③ Apache ECharts (+ echarts-for-react)
ECharts는 기능/표현력이 강한 시각화 라이브러리이며, Canvas와 SVG 렌더러를 전환할 수 있고 대규모 데이터 렌더링까지 고려한 엔진을 강조한다.
장점
- 차트 종류/컴포넌트가 매우 많고, 대시보드형 확장에서 강하다.
- Canvas/SVG 선택이 가능해 상황에 따라 성능/품질 트레이드오프를 조절할 수 있다.
단점
- MVP 기준으로는 설정이 크고 무거워질 가능성이 높다. “우리가 필요한 것”보다 “가능한 것”이 훨씬 많아서 도입 비용이 커지기 쉽다.
우리 서비스 적합도
- 지금 단계에서는 오버엔지니어링일 확률이 높다. 추후 “분석 기능이 핵심”으로 커지면 재검토 가치가 있다.
④ Visx (React + D3)
Visx는 Recharts처럼 차트를 완성된 형태로 제공하는 라이브러리가 아니라, React에서 그래프를 직접 만들어볼 수 있게 해주는 재료(도구) 모음에 가깝다. D3에서 쓰는 아이디어를 React 방식으로 쓰기 쉽게 묶어둔 느낌이다.
장점
- 디자인 자유도가 매우 높다. “우리만의 차트 UI”를 만들기 좋다.
- 필요한 패키지만 골라 쓰는 방식이라 구조적으로는 슬림하게 운영할 수 있다.
단점
- 레이더 차트 같은 것을 “바로 쓰는 컴포넌트”로 얻기보다, 직접 조합해서 만들어야 하는 영역이 커져 구현 시간이 늘어난다.
우리 서비스 적합도
- 차트 디자인이 서비스의 핵심 경쟁력이고, MVP에서도 차트에 많은 시간을 쓸 계획이라면 고려 대상이다. 지금은 비용이 크다.
1-3. 최종 결론 및 선정 근거
- 1순위: Recharts
- 2순위: Chart.js
[선정 근거] Recharts는 React 컴포넌트 기반이라 우리 개발 환경에서 빠르게 구현하고 유지보수하기 좋다. 반면 Chart.js는 Canvas 기반의 범용 엔진으로 세밀한 커스터마이징에 강점이 있다. 현재 기획된 레이더 차트는 요약 시각화 용도이며 데이터 포인트가 적다. 무엇보다 MVP 구현 속도가 중요하므로, 초기 리스크가 낮은 Recharts를 우선 적용한다.
- 우리 레이더 차트의 목적은 요약 시각화다
정밀 분석 툴이 아니라, 여러 지표를 한 화면에서 빠르게 비교시키는 것이 목적이다. 이 경우 “고급 인터랙션/플러그인 생태계”보다 빠른 구현과 예측 가능한 UI가 더 중요하다. - Recharts는 React 컴포넌트 조합으로 레이더를 바로 낼 수 있다
RadarChart를 공식 제공하고, 축/툴팁/영역 겹치기 같은 핵심 요소가 컴포넌트 구성으로 해결된다.
즉, MVP에서 가장 위험한 구간인 차트 첫 도입의 리스크가 낮다. - SVG 기반은 우리 UI 시스템과 잘 맞는다
Recharts는 SVG 기반이며 React + D3로 설계되어 있다.
모바일 요약 화면에서 데이터 포인트가 적다면, SVG의 “스타일 맞추기 쉬움”이 장점으로 크게 작동한다. - Chart.js는 Canvas 기반이라 확장/성능에 강점이 있지만, 초기 복잡도가 올라간다
Chart.js는 Canvas 렌더링을 공식적으로 명시한다.
React에서는 보통 react-chartjs-2 래퍼를 쓰는 형태다.
추후 데이터가 많아지거나 플러그인이 필요하면 강점이 되지만, MVP에서 중요한 “빠른 구현/유지보수 단순성” 관점에서는 Recharts가 더 유리하다.
1-4. 스파이더 그래프 설계 핵심: 정규화 (Normalization)
건강검진 데이터는 혈당(mg/dL), BMI(kg/m²), 혈압(mmHg) 등으로 단위가 각각 다르다. 이를 그대로 차트에 넣으면 그래프 형태가 망가진다. 따라서 각 항목을 0~100점 척도로 변환, 즉 정규화하여 매핑한다.
- 변환 예시:
- 정상 범위: 70~100점 구간 매핑
- 경계: 40~70점 구간 매핑
- 위험: 0~40점 구간 매핑 (정확한 점수 산정 기준은 기획 회의를 통해 확정한다)
2. 가로 직선형 그래프 (Linear Scale Indicator)

BMI, 허리둘레 등의 상태를 보여주는 가로형 바 그래프의 구현 방식을 검토했다.
2-1. 구현 방식 비교
- 커스텀 컴포넌트 (추천):
- 형태가 단순하므로 직접 구현 시 가장 가볍고 디자인을 정확히 맞출 수 있다.
- min, max, thresholds(경계값), value를 받아 점의 위치를 %로 계산하여 렌더링한다.
- 모바일 성능 부담이 거의 없다.
- Radix UI / shadcn/ui Slider:
- 접근성과 터치 UX가 이미 구현되어 있다.
- readOnly 속성을 사용하여 값 표시용으로 활용 가능하다.
- 단, 눈금이나 구간 라벨(정상/주의 등)을 표시하려면 추가 마크업이 필요하다.
- 차트 라이브러리 (Recharts 등):
- ReferenceLine과 Scatter 조합으로 구현 가능하나, 단순 UI를 위해 차트 라이브러리를 쓰는 것은 비효율적이다.
2-2. 결론
커스텀 컴포넌트로 구현하는 것을 1순위로 한다. 디자인 요구사항을 가장 깔끔하게 반영할 수 있고 재사용성이 높기 때문이다. 차선책으로는 shadcn/ui Slider를 활용한다.
3. 도넛 진행률(progress ring)
건강 점수를 나타내는 도넛 차트는 SVG를 활용하여 가볍게 구현한다.

3-1. 원형 링이 점수에 따라 돌아가는원리
SVG <circle>의 테두리 속성을 조절하여 구현한다.
- 둘레 길이(circumference): 2 * π * r
- 진행률(progress): 점수 / 100
- 보이는 길이: circumference * progress
이를 CSS 속성으로 제어한다.
- stroke-dasharray: 전체 둘레 길이로 설정한다.
- stroke-dashoffset: circumference * (1 - progress) 만큼 밀어내어 점수만큼만 색이 차오르게 한다.
3-2. 시작 위치
와이어 프레임에서는 3시 방향(오른쪽)에서 시작하는 걸로 표시되어있는데 만약 12시 방향(위) 부터 시작하고 싶으면 원을 -90도 회전시키면 시작점이 위로 간다.
<circle style="transform: rotate(-90deg); transform-origin: 50% 50%;" />
3-3. C자 형태 (빈 틈이 있는 원) 구현
온전한 원이 아니라 하단이 비어있는 C자 형태라면 아래와 같이 계산한다.
- 사용 비율(arcRatio): 300 / 360 = 0.8333
- 최대 길이(maxArcLen): circumference * arcRatio
- 점수 반영 길이: maxArcLen * progress
- 속성 적용: stroke-dasharray를 [그릴 구간, 비워둘 구간]으로 설정하고, 회전을 통해 빈 공간(Gap)의 위치를 하단으로 잡는다.
4. 가로 신장/체중/허리둘레/BMI 변화 그래프 (Trend Graph)

특정 지표(몸무게, BMI, 혈당 등)의
변화 추이를 보여주는 선 그래프이다.
4-1. 구현 전략: Recharts 통일
이 그래프는 서비스 내에서 반복적으로 사용된다. 앞서 레이더 차트를 위해 Recharts를 도입할 가능성이 높으므로, 변화 그래프 역시 Recharts의 LineChart를 사용하는 것이 효율적이다.
[Recharts 선정 이유]
- 이미 라이브러리 의존성이 추가되어 있어 부담이 없다.
- LineChart는 기본 제공 기능이며 구현 속도가 빠르다.
- 툴팁, 점 스타일 커스텀, 축 라벨링, 반응형 대응이 모두 가능하다.
- 컴포넌트 재사용이 용이하다.
4-2. 구현 체크 포인트
- X축: 날짜 표시
- Y축
- 점(Dot): 회색의 큰 원 형태로 커스터마이징.
- 선(Line): 검정색, 적절한 굵기 적용.
- 라벨: LabelList 혹은 커스텀 라벨을 사용하여 점 바로 위에 수치 텍스트를 표시한다.
디자인이 정형화되어 있고 1~2곳에서만 쓰인다면 SVG 직접 구현도 고려해볼 수 있으나, 축 처리와 반응형 등을 고려할 때 MVP 단계에서는 Recharts가 훨씬 유리하다고 생각한다.
5. 최종 정리
- 스파이더(레이더) 그래프: Recharts (빠른 구현, React 친화적)
- 변화 추이 그래프: Recharts (라이브러리 통일, 유지보수 용이)
- 척도 인디케이터(직선형): 커스텀 컴포넌트 (가벼움, 디자인 최적화)
- 건강점수 도넛: SVG 커스텀 (간단한 원리는 라이브러리 없이 구현)
'FE' 카테고리의 다른 글
| 의료 서비스 - 보안 강화 방법 (0) | 2026.01.03 |
|---|---|
| React Suspense + Error Boundary로 안정적인 로딩/에러 핸들링 (1) | 2026.01.03 |
| PDF 업로드가 느린 이유와 런칭을 위한 성능 최적화 (0) | 2025.12.30 |
| TanStack Query 낙관적 업데이트: onMutate + Rollback을 찜 해제에 적용 (0) | 2025.12.19 |
| [멋사] 2025 4호선톤 회고 (0) | 2025.11.17 |