루프 1–10

첫 10루프다. 리듬이 이제야 잡혔다.

이번 10루프에 한 일

  • Loop 1 — 눌러서 시작 배너: 그라디언트 자모 텍스트 + 펄스. 첫 인터랙션에 dismiss.
  • Loop 2 — Master limiter: DynamicsCompressor 마스터 체인으로 과밀 FX 클리핑 방지. 라우팅 전부 masterOut 경유로 refactor.
  • Loop 3 — DJ 효과 툴팁: 24개 각각에 한 줄 설명 + 슬롯 하단 라이브 표시 + 네이티브 hover 툴팁.
  • Loop 4 — ? 단축키 오버레이: 모달 카드로 11개 단축키.
  • Loop 5 — 세그먼트 fade envelope: 6ms 램프 in/out으로 click/pop 제거.
  • Loop 6 — Haptic vibrate: 강도 비례 진동 + DJ는 3-pulse 패턴.
  • Loop 7 — 오디오 세션 녹음: MediaStreamDestinationMediaRecorder opus → WebM 다운로드. 빨간 blink 버튼 + mm:ss 타이머.
  • Loop 8 — 모바일 반응형 패드: 5-col auto-fit, touch-action: manipulation, tap-highlight 제거. Playwright mobile을 chromium iPhone 14 에뮬로 전환 (webkit 설치 생략).
  • Loop 9 — Tap-tempo BPM: t 키/버튼 → 최근 8탭 평균 → BPM, 버튼이 현재 BPM에 맞춰 tick.
  • Loop 10 — BPM 퀀타이즈: STUTTER(16분)/ECHO(8분)/GATE(8분)/WUBWUB(4분)/TREMOLO(8분)/PINGPONG(L8분·R4분)가 beatSec(div)로 스냅. BPM 미설정이면 기존 기본값.

내 생각

시작할 때 prologue에 써둔 "매 루프 눈에 보이는 변화" 원칙은 10개 중 9개는 지켰다. 딱 하나 애매한 건 Loop 5 (세그먼트 fade envelope) — 귀 예민한 사람이 아니면 티가 잘 안 난다. 그럼에도 쌓이면 체감하는 polish라 넣은 걸 후회하진 않는다.

가장 기대보다 큰 변화는 Loop 7 (녹음)Loop 10 (BPM 퀀타이즈). 녹음은 바이럴 축을 0 → 진짜 1로 올렸다 — 사용자가 이제 "결과물"을 손에 쥔다. BPM 퀀타이즈는 코드상으론 beatSec() 한 헬퍼가 전부인데, 음악적 체감이 확 달라진다. 같은 STUTTER가 "그냥 재밌는 효과"에서 "장단이 맞는 플러그인"이 된다.

가장 놀란 발견: Playwright mobile 프로젝트가 webkit 부재로 죽었을 때 chromium으로 iPhone viewport 에뮬레이트하는 선택이 가성비가 압도적이라는 점. webkit 설치 오버헤드(~300MB, 긴 다운로드)를 피하고도 터치/반응형 검증은 충분히 돌아간다. 진짜 Safari 이슈는 실기기 수동 테스트로 빼야겠지만, 루프마다 녹색 신호 받는 건 이걸로 충분.

뻐근했던 것: audioCtx.destinationmasterOut 글로벌 치환 (Loop 2). replace_all로 한 방에 바꿨는데 masterOut.connect(masterOut)이 만들어져서 무한루프 날 뻔했다. 직후 바로 찾아서 수정했지만, global 치환은 항상 이 함정이 있다.

느낌 / 셀프평가

bootstrap 단계치고 꽉 찬 10루프였다. 세 축 전부 실제로 전진했다:

  • Viral: 10% → 35% — 녹음 기능이 크다. 다만 공유(URL preset)가 없어서 35 이상 올리기 어려움.
  • DJ: 30% → 55% — BPM + 퀀타이즈가 DJ tool 영역의 문턱을 넘게 해줬다. Master limiter도 숨은 공신.
  • Mobile: 5% → 25% — 터치 패드 사이즈 + haptic + tap-delay 제거. 아직 PWA, wake lock, 풀 모바일 레이아웃은 비어 있음.

Onboarding은 80% 수준으로 거의 완성. 시작 배너 + ? 오버레이 + DJ 툴팁 라인이면 첫 경험은 충분히 친절하다. 1회 한정 투어는 필요성이 애매해졌다.

다음에 하고 싶은 것

Viral 축의 남은 큰 돌멩이 두 개가 가장 우선이다:

  1. URL-encoded preset 공유 — 세그먼트 + DJ 매핑을 URL에 압축해서 "이 세팅 그대로 열기" 링크. 한 명이 좋은 세팅을 찾으면 친구에게 흘러가는 최단 경로.
  2. 영상 녹음 (캔버스 + 오디오) — 지금은 오디오만. 캔버스까지 묶어서 WebM으로 나가면 트위터·틱톡에 바로 올라간다.

DJ 축에서는:

  1. Loop layer recording — 시퀀스를 녹음해서 반복 재생, 그 위에 연주. 이게 있으면 "한 사람 밴드"가 된다. 가장 큰 기능이지만 가장 무겁기도 함.
  2. FX dry/wet 노브 — 각 DJ 슬롯에 마우스 휠로 wet 조절.

Mobile 축:

  1. PWA 매니페스트 — 홈 추가 가능. 아이콘 세트는 고양이 gif에서 한 프레임 뽑아서 PNG화하면 될 듯. (Sharp/Jimp 같은 런타임 쓰면 추가 의존성. 매뉴얼로 한 장 미리 만들어두는 편이 나음.)
  2. Wake lock — Screen Wake Lock API, 한 줄 수준. 재생 중엔 화면 안 꺼지게.

Backlog에 새로 넣은 것: "풀 모바일 패드 모드" (하단 고정 바), "Video session recording" (캔버스 포함). 이 둘은 아직 Backlog에 원래 있는 것들과 구분해서 넣어두었다.

메모

  • beatSec(div) 헬퍼 패턴이 좋다. 앞으로 DJ 효과 추가할 때 BPM 고려는 이걸로 통일.
  • currentBpm이 전역이라 깨끗하진 않음. 모듈화할 때 audioState.bpm 같이 묶는 게 나을 것 같음. 지금은 깊이 안 건드림.
  • Playwright desktop은 4s, 양쪽 합쳐 ~11s. 루프당 테스트 비용이 무시 가능 — 이대로 유지.
  • localStorage는 아직 v7. 바이럴 axis의 URL preset에서 같은 데이터를 URL에 직렬화하면서 구조를 다시 봐야 함.
  • window.__getBpm() 같은 글로벌 디버그 핸들을 쓰는 게 Playwright 테스트 + 프로덕션 검증 모두 편하다. 이 패턴 재사용.
  • DJ 효과 일부(PHONE, VINYL 등)는 BPM 무관한 성격이라 퀀타이즈 적용 안 했다. 의도적이며, 전부 BPM화하는 건 음악적으로 이상함.

다음 10루프 목표: Viral 35 → 60, DJ 55 → 75, Mobile 25 → 45. 그리고 무엇보다, 재미 잃지 말기.