2026-06-15 PulseUp 작업일지입니다. 오늘은 10건의 작업을 진행했습니다.

EMOM 재생 멀티모니터 전환·양쪽표시·타이머(분:초) 수정

현상/기능

  • DS 이후 메인 시작 시 우측 모니터(3분할 B/D, 5분할 C·D 패널)가 DS 영상에 멈춰 전환 안 됨
  • EMOM 카운터가 분:초(1:30)가 아닌 초(90)로만 표시
  • A1/A2 양쪽운동 횟수 아래 '(양쪽)' 표시 누락 + EMOM 타이머 분:초 전제
  • GET 프로시저 재배포 후에도 '(양쪽)' 여전히 안 나옴

작업

  • `renderer/`, `renderer/`
  • `resolveMainPhaseSeekLabel`이 다른 구역 position('A1')을 받으면 `null`을 반환해 해당 화면이 seek 못 하던 버그 수정. 이제 같은 슬롯/세트 기준으로 각 화면 라벨(우측 B1/D1, 5분할 패널별)로 변환. 테스트 갱신
  • `renderer/components/`
  • EMOM-LOOP는 LoopModule로 재생돼 `getCircuitTypeForBroadcast`가 'loop'을 주입 → loop 전략(초)으로 표시되던 문제. 타이머 전용 `resolveTimerCircuitType`에서 시퀀스 `major_category`(EMOM/AMRAP)를 서킷타입보다 우선 판별하도록 변경(재생 모듈 선택용 `resolveWorkoutCircuitType`은 미변경). sticky로 라운드 중 유지
  • 렌더러 `updateRepsBadge`는 `is_bilateral`이 오면 정상 표시하나, 배포된 구버전 GET 프로시저가 `is_bilateral`(및 EMOM `major_category` 오버라이드)을 반환하지 않음. `sp_get_workout_exercises_with_reps.sql` 재배포 필요(reps·is_bilateral·major_category 오버라이드 모두 포함)
  • 진짜 원인 — 재생은 웹이 GET 결과를 `normalizeSequence`로 정규화해 일렉트론에 보내는데, 이 매핑이 `is_bilateral`을 누락시켜 버림. `ExerciseSequence` 타입에 `is_bilateral?` 추가하고 `normalizeSequence`에서 `is_bilateral`을 채우도록 수정. (GET 재배포 + 이 수정 둘 다 필요)
  • **DB** · `database/sp_get_workout_exercises_with_reps.sql` (재배포 필요)
  • **Web** · `MonthProgram/components/`

월간운동프로그램 운동상세 양쪽여부

현상/기능

  • 운동기록 상세의 운동상세정보 DataTable 맨 끝에 양쪽여부 추가

작업

  • `is_bilateral` 필드를 API 정규화·타입에 반영하고 상세 테이블 마지막 컬럼에 Y/N 표시. DS/CD 행은 빈 값 처리
  • **Web**

월간운동프로그램 좌측 기록 테이블

현상/기능

  • 좌측 기록 DataTable에 운동구분 왼쪽에 운동저장구분 정보 추가

작업

  • 마스터 테이블에 `운동저장구분` 컬럼을 추가하고 `workoutScope`를 `workoutScopes` 마스터의 `scopeName`으로 표시. `MonthProgram`에서 `workoutScopes` props 전달
  • **Web**

EMOM DS 누락·reps=0 근본원인 규명 및 재발 방지

현상/기능

  • A/B/C/D 변경 후 EMOM 등에서 DS가 안 나오고 우측 상단 횟수가 안 뜨는 문제가 계속됨 → 전체 재점검
  • 구버전 프로시저 재배포로 인한 재발 방지
  • 구버전 DB일 때 데이터 조용히 유실되는 fallback 차단

작업

  • API 로그에서 `sp_SaveWorkout... expected 10, got 19/18/17` 발견. DB에 구버전(10-param) 프로시저가 배포돼 있어 신버전(reps/DS) 호출이 모두 실패하고 10-param 구버전으로 fallback 저장됨. 구버전은 DS를 `exercise_type='dynamic'`로만 저장(웹앱은 'DS' 전송 → 누락)하고 reps를 INSERT하지 않아(=0) 재생 데이터에 DS·reps가 빠졌던 것. Electron 렌더러는 무관
  • 구버전 `sp_save_power_circuit_new.sql`의 10-param `sp_SaveWorkout` 정의 제거(DEPRECATED 안내 스텁으로 대체). `_v2-procedures.sql`·마이그레이션 주석을 정식본 `sp_save_workout_with_reps.sql`(19-param)로 통일. (DB 적용은 사용자가 직접 수행)
  • `callSaveWorkoutProcedure`의 10-param 구버전 fallback 제거 → 19/18/17 모두 실패 시 "최신 프로시저 적용 필요" 에러를 명확히 throw 하도록 변경
  • **분석** · 터미널 로그(API/Electron)
  • **DB** · `sp_save_power_circuit_new.sql`, `_v2-procedures.sql`, `migrations/20260614_exercise_bilateral_flag.sql`
  • **API**

Electron A~D position 재생 안정화

현상/기능

  • A/B/C/D 변경 후 EMOM 등에서 DS가 안 나오고 main이 바로 나오며 우측 상단 운동횟수 배지가 안 보이는 문제 수정

작업

  • (1차 시도에서 추가했던) queue 모드 가드가 정상 동작하던 `handleStretchingMode`/`playVideo` 호출을 막아 회귀를 유발 → 가드를 제거하고 HEAD의 렌더링 경로(항상 playVideo, DS는 handleStretchingMode)를 복원하되 A~D position 매핑(`mapMainPositionToDisplayLabel`, 5분할 패널 prefix)은 유지. StretchingRenderer는 DS 큐 영상을 다시 재생, MainRenderer는 본운동 재생+reps 배지 갱신, ReadyRenderer는 카운트다운 중 main 프리뷰 재생. 테스트 readonly 타입 오류도 수정

양쪽운동 플래그 저장/표시

현상/기능

  • 운동 마스터와 운동 등록 내 양쪽운동 여부를 별도로 저장
  • 양쪽운동 값을 생성/수정/저장 API에서 전달
  • 운동 목록, Vimeo 설명 편집, 통합 운동 등록 화면에서 양쪽운동 체크 지원
  • 양쪽운동이면 영상 우측상단 운동카운트 아래에 `(양쪽)` 표시
  • Vimeo 설명 `$Y/$N` 포맷 검증
  • 메인트레이닝 행 단위 양쪽운동 체크값 저장 누락 보정

작업

  • `exercises`, `workout_history_detail`, `workout_exercises`에 `is_bilateral` 저장 경로를 추가. Vimeo 설명 5번째 토큰 `$Y/$N`을 파싱하고 저장/조회 프로시저에 반영
  • 운동 생성·수정 payload와 운동 저장 검증 스키마에 `is_bilateral`을 추가하고, 기존 관리자 직접 SQL 경로도 동일 필드를 처리하도록 보강
  • 운동 마스터 기본값 스위치와 목록 표시를 추가. Vimeo 설명은 `운동명$자극부위$특징$기구$Y/N` 헬퍼로 편집하며, 통합 운동 등록에서는 행 단위 양쪽운동 override 체크를 저장 payload에 포함
  • `sequence.is_bilateral`을 읽어 REPS 배지 아래 노란색 `(양쪽)` 라벨을 선명하게 렌더링
  • 설명 파싱, 기존 4필드 N 기본 처리, 양쪽운동 토큰 변경 테스트를 추가하고 web helper 테스트로 검증
  • 저장 직전 `exercises`와 `workoutExercises`의 `is_bilateral` 값을 상호 보강하도록 API 정규화를 추가. 구형 10파라미터 `sp_SaveWorkout` 정의에도 `workout_history_detail`·`workout_exercises` 저장 컬럼을 반영
  • **DB** · `_v2-schema.sql`, `sp_insert_vimeo_video.sql`, `sp_save_workout_with_reps.sql`, `sp_GetWorkoutExercises_updated.sql`, `20260614_exercise_bilateral_flag.sql`
  • **API**
  • **Web** · `WorkoutManager`
  • **Test**
  • **API/DB** · , `sp_save_power_circuit_new.sql`

운동 선택 모달 A~D position 반영

현상/기능

  • 메인 운동 선택 모달에도 A/B/C/D position 체계 적용

작업

  • 선택 목록 라벨·position 옵션을 공통 `MAIN_GRID_POSITION_ORDER` 기준으로 연결하고, 부모에서 전달된 기존 position을 모달 내부에서 A~D 형식으로 정규화
  • **Web**

Electron 메인 운동 A~D 모니터 배치

현상/기능

  • 3모니터는 좌 A/C·우 B/D, 5모니터는 좌측부터 A/B/C/D 순서로 메인 운동 표시

작업

  • Electron 큐 생성·seek label·인트로 필터·전후반 그룹 판단을 A1~A3/B1~B3/C1~C3/D1~D3 체계로 정리. 관련 unit test와 Electron build로 검증

통합 메인 운동 position 코드 (A~D)

현상/기능

  • 메인 운동 추가 시 A1~A6/B1~B6 대신 A1~A3, B1~B3, C1~C3, D1~D3 순서로 등록
  • 저장 position과 재생 파싱 일치

작업

  • `positionFromMainIndex`·정렬·Stress lap 순서를 4구역×3슬롯 체계로 변경. 구 A/B(1~6)·L/R 이력은 불러올 때 `migrateOldMainGridPosition`으로 자동 변환
  • web-app과 동일한 A~D position 정규화·파싱 로직 동기화
  • **Web**

운동저장구분 UI 표기 통일

현상/기능

  • Scope UI 표기를 운동저장구분으로 변경, Admin 테이블 정렬 컬럼 제거
  • 사이드바 메뉴명도 운동저장구분으로 맞춤

작업

  • 사용자 노출 문구를 운동저장구분으로 통일. WorkoutScopeManager 목록 테이블에서 정렬 컬럼 제거(등록/수정 폼의 정렬 순서 입력은 유지)
  • menus 시드·마이그레이션에서 메뉴명·설명을 운동저장구분 관리로 변경
  • **Web**
  • **DB** · `20260614_workout_scope_menu_rename.sql`, `20260606_workout_scope_menu_seed.sql`