2026-09-26 PulseUp 작업일지입니다. 오늘은 7건의 작업을 진행했습니다.
리모컨 기본 탭 — 화면 구성·심박 전용 화면 겹침 정리, 상단 탭 대비 강화 (web-app)
현상/기능
- 심박화면켜짐 버튼이 들어가면서 화면 구성과 심박전용화면 버튼이 정리되지 않고 깨져 보이는 현상
- 상단의 기본/선택보기/심박 탭 구분이 명확하게 보이지 않는 현상
작업
- 화면 구성·심박 전용 화면을 고정 높이 묶음으로 분리, 3/5분할 버튼이 남은 높이를 모두 차지하면서 심박 버튼이 인트로/운동 시작 위로 겹치던 배치를 없앰
- 상단 탭을 어두운 바 + 파란 선택 상태로 바꿔 기본/선택보기/심박 구분이 바로 보이게 함
심박 전용 보드(30칸) 순위·슬롯 카드 스타일을 요청 이미지 형태로 변경 (electron-app)
현상/기능
- 맨 위 순위표와 각 슬롯의 표현이 요청한 이미지 형태와 다른 현상(슬롯 배경은 그라디에이션 형태로 요구됨)
- Electron renderer heart-rate-modules/ 수정
- 순위 칸: 1등 금색 SVG 왕관으로 변경(이모지 대신), 존 색 얇은 링(2~4px) 안 흰 순위 숫자, 오른쪽에 이름·큰 흰 BPM·존 색으로 채운 ZONE n 배지 추가, 3자리 BPM 글자 크기를 칸 안에 맞춤
- 24칸 배경을 슬롯 랜덤색 세로 그라디에이션에서 진남색(#0d1f5c)→존 색 대각(115deg) 그라디에이션으로 변경, 흰 반투명 테두리 추가, 순위·이름·큰 흰 BPM·가운데 왼쪽 ECG 라인·가운데 존 색 ZONE n 배지 구성, 존 없음(Z1 미만)이면 회색으로 이어지고 배지 생략
- renderZoneBadge·CROWN_ICON·SLOT_BASE_COLOR 추가, renderEcg에 위치 인자 추가, 헤더 요약 갱신
- 테스트 에 순위 링·배지·왕관 확인, 24칸 그라디에이션·존 없음 배지 생략 테스트 2건 추가
- 보드 모델의 슬롯 랜덤색(HeartRateBoardCard.color, rememberBoardColor)은 화면에 더 이상 쓰지 않지만 모델 자체는 유지함
ANT+ 심박계 연동 지연 — USB 워치독 오탐 재시작 루프 제거·재초기화 쿨다운 단축 (electron-app)
현상/기능
- 심박계가 하나도 켜져 있지 않아 스캔 모드 USB가 무수신인 정상 상태를 워치독이 동글 고장으로 판정해 66초마다(60초 무수신 + 5초 쿨다운 + 재초기화 약 6초 먹통) 동글을 재시작하는 현상
- 수업 시작 전 심박계를 켜는 시점이 이 공백 구간에 걸리면 연결이 그만큼 지연되는 현상
- 연속 재시작 백오프 카운터가 재초기화 핸드셰이크 read로 인해 0으로 되돌아가 한 번도 동작하지 않는 현상
- 스캔(연속 RX 스캔 모드)·메인→화면 브로드캐스트(동기)·화면 갱신 경로는 이미 즉시 처리되고 있는 상황, 서버 저장은 공통코드 SAMPLE_SECONDS/FLUSH_SECONDS 기준 2~3초 뒤 도달하는 설계값인 상황(변경 대상 아님)
- Electron main heart-rate-modules/ 신규 작성 — 워치독 판정을 순수 모듈로 분리, 동글 세션에서 심박계 패킷을 받은 뒤 트래픽이 끊긴 경우에만 트립하도록 함, 재초기화 뒤 세션은 패킷을 다시 받기 전까지 트립하지 않도록 하여 무한 재시작을 방지함, 동작하지 않던 백오프 카운터를 제거함, LINKHIIT_ANT_USB_WATCHDOG_MS 해석(resolveAntUsbWatchdogMs) 로직을 이동함
- Electron main — 워치독 필드·getUsbWatchdogMs·checkUsbReadWatchdog 내부를 AntUsbReadWatchdog 사용으로 교체함, 스캐너 패킷마다 noteSensorPacket을 호출하도록 추가함, AUTO_RESTART_COOLDOWN_MS를 5초에서 1초로 단축함, 트립 로그에 마지막 심박계 패킷 시각을 추가함, 헤더 요약을 갱신함
- 테스트 신규 작성(6건) — 패킷 없는 세션 무트립, 패킷 뒤 무수신 1회 트립, 재초기화 후 핸드셰이크만 있는 세션 무트립, 비활성값 확인
심박 존 Z1~Z5 전체 적용 — 저장·Electron·앱 내 심박존·웹 잔여 코드 (api-server, electron-app, web-app, mobile-app)
현상/기능
- 과거 데이터는 그대로 두고 이번에 추가한 ZONE 기준으로 프로그램 전체와 앱에 적용해야 하는 상황
- 관련 저장 구조를 조정함
- API — 60초 캐시 getCachedHeartRateZones(실패 시 이전 값/기본값), clearHeartRateZoneCache 추가함
- API — 단건·배치 저장 zone을 요청값 대신 심박으로 판정(z1~z5/none)하도록 변경함, 참가자 요약 current_zone과 운동 심박 원본 조회 zone도 심박으로 판정하도록 변경함
- API schemas/ — zone에 새 값과 예전 값 모두 허용하도록 변경함(구버전 Electron 호환)
- API — /heart-rate-settings 응답에 zones를 추가함, GET /heart-rate-zones를 신규 추가함(인증), HEART_RATE 코드 등록·수정 시 존 캐시를 비우도록 함
- API 테스트 tests/(저장 zone 판정·current_zone·스키마), tests/ 신규 추가함
- Electron common/ — Z1~Z5/none 판정, 창별 현재 기준(setActiveHeartRateZones), 이름·색·번호 로직을 추가함, 테스트 신규 추가함
- Electron main (존 반영·heart-rate-zones-updated 전송·get-heart-rate-zones IPC), (onZones), (연결만) 수정함
- Electron IPC — , , , types/, (모든 창 전달) 수정함
- Electron renderer — (창 시작 시 존 받기·갱신), (4구간 → Z1~Z5 + 회색), (순위 존을 공통 존으로 변경, 존 없음 회색), ·(Rest/Fat Burn 등 문구를 Z1~Z5 / '-'로 변경) 수정함
- 웹 lib/ — 운동기록용 모듈을 공용 위치로 이동함, classifyHeartRateZone·HEART_RATE_ZONE_HEX를 추가함, 운동기록 컴포넌트 import 경로를 변경함
- 웹 미사용 코드 정리 — hooks/(+테스트), components/HeartRate/, store/slices/, types/, types/ 주석 정리함
- 웹 — 존 사용처·과거 기록 미변경 안내 문구를 추가함
- 앱 api/·screens/profile/ 신규 작성 — 센터 공통 존 조회 기능 추가함
- 앱 , , , — 220-나이 기준 50~90% 안내를 센터 공통 Z1~Z5 구간 안내로 변경함, 의 resolvePersonalMaxHr·DEFAULT_MAX_HR을 제거함
심박 존 Z1~Z5 DB 저장·웹/앱 운동기록 적용 (api-server, web-app, mobile-app)
현상/기능
- 존 구간이 Z1(90~107bpm)~Z5(162~180bpm)로 정의되어 DB에 저장되고 다른 곳에서 사용되어야 하는 상황
- 웹·앱 운동기록에 존 이름·분포만 적용되어야 하는 요구사항, 90 미만은 존 없음(회색) 180 초과는 Z5로 처리되어야 하는 요구사항
- 관련 저장 구조를 조정함
- api-server/src/services/ 신규 작성 — 공통코드 ZONE1~5 값('최소-최대') 해석(잘못된 값은 기본 구간), BPM → z1~z5/none 판정 로직을 추가함
- api-server/src/services/ 신규 작성 — 해석·판정·경계값 테스트 7개 통과함
- 운동일별 개요에 avg_heart_rate_zone, heart_rate_zones를 추가함, 심박 상세 측정값 zone을 공통코드 구간으로 판정(z1~z5/none)하도록 변경함, zone_counts를 같은 기준으로 변경함, heart_rate_zones를 추가함, 조회에서 zone 컬럼을 제외함
- 웹 WorkoutRecords/components/ 신규 작성 — 존 이름·색·구간 문구 정의함
- 웹 — Z1~Z5(+존 없음) 분포와 bpm 구간을 표시하도록 변경함, HeartRateReadingsTable, heartRateChartShared, MemberWorkoutHeartRateDetail, types/를 연결함, memberWorkoutRecordsUtils의 옛 존 이름 함수를 제거함
- 앱 — 최대심박% 계산 대신 서버 존·공통코드 구간을 사용하도록 변경함, 프로필용 resolvePersonalMaxHr는 유지함
- 앱 useWorkoutRecords, WorkoutRecordsScreen, ClassRecordPanel, ClassRecordCard(기준 문구 "센터 공통 심박 존 기준"), MonthlyRecordPanel(평균 존 색), workoutRecordsUtils(avgHeartRateZone), HeartRateDetailScreen, HeartRatePreview, api/ 수정함
- 웹 — HEART_RATE.ZONE1~ZONE5 안내 문구를 추가함
- 범위 밖으로 변경하지 않음: Electron 심박 보드·운동 패널 존, 앱 프로필 내 존 안내(나이 기준), 웹 실시간 심박 차트
심박 전용 모니터 30칸 레이아웃
현상/기능
- 기존 24칸 레이아웃에서 맨 위 한 줄이 비어 있는 현상
- 전체를 30칸으로 맞추고 첫 줄에 1~5등 순위와 마지막 칸에 pulse box 로고·접속 수/전체 슬롯 수(예: 14/24)·여러 사람 아이콘을 표시해야 하는 요구사항
- 화면 전체를 6열×5줄 30칸 격자로 변경함, 첫 줄은 테두리 없는 순위 1~5칸(5명 미만이어도 빈 칸 유지)으로 구성함, 마지막 칸에 assets/logo.png와 빨간 테두리 상자(여러 사람 아이콘, 접속 수 빨강 / 24)를 추가함, 2~5줄은 기존 24칸 그대로 유지함, 순위 글자·원 크기를 모니터 폭에 맞춰 조절함
- 접속 수 칸에는 숫자만 넣도록 수정함
- 신규 작성 — 30칸 격자, 첫 줄 5칸 유지를 확인함, 보드 관련 테스트 6개 통과함
심박 전용 모니터 상단 순위 스타일
현상/기능
- 현재 만들어진 상단 순위 스타일이 요청한 이미지 스타일과 다른 현상
- 상단 순위를 이름·왕관·두꺼운 원·존 색 BPM·ZONE 문구로 변경함, 오른쪽에 PULSE 문구와 테두리 안 발바닥·인원(n / 24) 표시로 변경함
- 상단 순위 존만 최대심박 190의 50~90%로 계산(ZONE 1~5)하도록 변경함, 24칸 색·저장 zone·운동 패널 색은 그대로 유지함