프로젝트

[PowerUp 개발기 3편] 지운 기능과 고친 버그

TerryDev 2026. 10. 16. 19:22

이 글 요약

  • 지운 것: 지난번의 나와 싸우는 대결 화면(9일), 내 의도를 모르는 AI 코치(두 달), 세울 때만 확실했던 목표(두 달 반)
  • 고친 것: 1975년을 가리킨 잠금 화면 타이머, 끝나지 않는 '휴식', 끊기는 음악, 지하에서 사라진 세트
  • 지운 기능은 헬스장에서 식었고, 버그는 헬스장에서 터졌다

2편에서 지금의 PowerUp을 하루 동선으로 소개했다. 이번 편은 그 화면들 뒤에 있는 것들이다.

이 앱에는 무언가를 지운 커밋이 81개 있다. 앞부분은 만들었다가 지운 기능, 뒷부분은 남긴 기능에서 터진 버그다. 둘 다 발견한 곳은 같다. 헬스장이다.


지운 것

대결 화면: 9일

처음 아이디어는 게임이었다. 상대가 있으면 한 회라도 더 하게 된다. 그 상대를 지난번의 나로 하자. 왼쪽은 오늘의 나, 오른쪽은 지난번의 나. 세트를 마칠 때마다 가운데에 승(W), 무(=), 패(L)가 켜진다.

7월 3일 확정한 대결 화면 목업. 가운데 W와 L이 세트별 승패다

문제는 판정이었다. 지난번에 80, 75, 75, 70kg으로 4세트를 했는데 오늘 80, 80, 75kg으로 3세트를 했다면 이긴 건가. 답을 찾는 동안 기획 문서는 22편, 목업은 수백 장이 됐다.

7월 3일 결론은 단순했다. 대결 중에는 지난번 세트 수와 무게를 그대로 들고, 반복 수만 비교한다. 그런데 그러면 컨디션 좋은 날 무게를 올리려면 대결을 꺼야 했다. 점진적 과부하를 돕겠다는 화면이 무게를 올리는 순간 빠지게 만들고 있었다.

결정적인 순간은 없었다. 쓸수록 식었다. 7월 12일 커밋 메시지는 "대결 모드 완전 삭제(지난 기록 유지)"다. 괄호 안의 "지난 기록 유지"가 2편의 "이전" 칸이 됐다.

AI 코치: 두 달 가까이

6월 16~17일 이틀 만에 주간 브리핑, 기간 리포트, 코치 채팅이 생겼다. 원칙도 세웠다. 숫자는 사실을, AI는 판단을.

6월의 AI 코치 탭

그런데 AI는 내 숫자는 알았지만 의도는 몰랐다. 세트가 줄면 줄었다고, 무게가 그대로면 정체라고 읽었다. 그게 계획이었는지, 내 목표가 무엇인지는 기록에 없다. 답은 부정확하거나, 틀리지 않으려고 모호했다.

8월 6일에 지웠다.

목표: 두 달 반

7월 말에 목표 탭을 만들었다. 종목마다 목표를 정하면 증량할 때인지 정체인지 알려 주고, "62.5kg 제안" 칩을 띄웠다.

7월 말에 만든 목표 탭

목표는 세울 때 가장 확실하다. 사이드 레터럴 레이즈 5kg으로 30회. 그런데 막상 운동하다 보면 흐려졌다. 헬스장에서 중요한 건 그날 운동에 최선을 다하는 것이었다. 나중에는 목표를 세우지도 않았다. 누군가에게는 좋은 기능이다. 나는 안 썼다.

10월 16일, 제출 직전에 지웠다. 지우는 순서는 AI 때와 같았다. 데이터를 파일로 떠 두고(덤프), 쓰는 쪽부터 지운다. 앱 → 서버 → 데이터베이스. 서버를 먼저 지우면 아직 부르는 앱이 오류를 낸다.

셋이 몰랐던 것

기능 기간 몰랐던 것
대결 화면 9일 컨디션이 좋으면 무게를 올려야 한다는 것
AI 코치 두 달 가까이 내가 왜 이렇게 운동했는지
목표 두 달 반 목표는 날마다 같은 무게로 다가오지 않는다는 것

셋 다 운동을 미리 정한 기준으로 재려고 했다. 운동은 그날 몸 상태에서 할 수 있는 만큼 하는 것이었다.


고친 것

나는 코드를 거의 읽지 않았다. 확인은 화면으로 했고, 진짜 확인은 헬스장에서 했다. 그래서 버그도 대부분 운동하는 중에 만났다.

잠금 화면 타이머가 1975년을 가리켰다

2편의 잠금 화면 휴식 타이머는 휴식 중이 아닐 때 운동 시작부터 흐른 시간을 센다. 7월 21일, 거기에 이런 숫자가 떴다.

17307669:27:45

1,730만 시간. 대략 1975년 치다. 흐른 시간을 세려면 끝이 없어야 하는데, 끝을 비워 둘 수 없어서 "아주 먼 미래"를 넣었다. iOS의 먼 미래는 서기 4001년쯤이다. 그런데 화면에는 "위로 세라"는 방향을 안 알려 줬다. 타이머는 4001년까지 남은 시간을 거꾸로 셌다.

끝을 "시작 후 12시간"으로 바꾸고 방향을 명시했다. 12시간 넘게 운동할 일은 없다고 판단했다. 아직은 맞다.

운동은 끝났는데 '휴식'이 남았다

9월에는 운동을 끝냈는데 잠금 화면에 '휴식'이 계속 떠 있었다. 앱은 잠금 화면 타이머의 번호를 메모리에만 들고 있었고, 운동 중에 앱이 다시 켜지면 번호를 잊었다. 번호를 모르니 끌 수도 없었다. 이제는 앱이 켜질 때마다 내 앱이 띄운 타이머를 전부 찾아서 끈다.

휴식을 시작하면 음악이 끊겼다

가끔, 휴식 타이머가 시작되는 순간 듣던 음악이 멈췄다. 앱은 시작할 때 "다른 앱 음악과 섞어서 재생"으로 소리 설정을 한 번 걸어 뒀다. 그런데 iOS는 이 설정을 영원히 지켜 주지 않는다. 전화나 다른 앱이 소리를 쓰고 나면 풀린다. "가끔"의 정체는 "전화나 다른 앱이 소리를 쓴 다음"이었다. 소리를 낼 때마다 설정을 다시 걸게 고쳤다.

지하에서 세트가 사라졌다

가장 늦게 고쳤고, 가장 무서운 버그다.

세트 저장에 실패하면 앱은 화면에서 그 세트를 지웠다. 서버가 "이 값은 틀렸다"고 거절한 경우를 생각한 처리였다. 그런데 신호가 약해서 실패한 경우도 똑같이 지웠다. 신호가 약한 지하 헬스장에서 친 세트는 화면에서도 서버에서도 사라졌다.

10월 15일, 앱스토어 제출 하루 전에 고쳤다. 신호 문제로 실패한 세트는 휴대폰 안의 대기열에 보관하고, 화면에 구름 표시와 "저장 대기" 안내를 띄운다. 연결이 돌아오면 다시 보낸다. 다시 보내기 전에는 서버에 이미 들어갔는지 먼저 확인한다. 응답만 늦었고 저장은 됐던 경우에 같은 세트가 두 번 들어가지 않게 하기 위해서다.

목록에 넣기 애매한 날도 하나 있다. 헬스장에서 앱이 아예 열리지 않았다. 서버가 집에 있는 맥북이었고, 그 맥북이 꺼져 있었다. 이 이야기는 맥북 서버 탈출기에 따로 썼다.


에이전트와 한 부분

에이전트가 한 일: 기획 문서와 목업, 기능을 만드는 일과 지우는 일, 버그 원인 추적과 수정. 그리고 커밋 메시지 본문에 원인을 길게 적어 두는 것. 이 글의 버그 설명은 전부 그 커밋 본문에서 가져왔다.

내가 한 일: 헬스장에서 써 보고 식는 것, 헬스장에서 써 보다 이상한 걸 보는 것. 그리고 무엇을 지울지 정하는 것. 기준은 하나였다. 내가 안 쓰면 뺀다.

직접 코드를 짰다면 대결 화면을 9일 만에 지우지 못했을 것이다. 들인 시간이 아까웠을 테니까. 에이전트는 하루면 만들었고, 그래서 지울 때도 미련이 덜했다.

대신 테스트는 지금 616개인데, 위의 버그 네 개는 어느 테스트도 잡지 못했다. 잠금 화면, 전화 뒤의 소리 설정, 약한 신호는 실제 휴대폰을 들고 실제 헬스장에 가야 생기는 일이었다.


오늘의 교훈
지운 기능은 헬스장에서 식었고, 버그는 헬스장에서 터졌다. 결국 테스터는 헬스장이었다.

다음 편은 앱스토어 제출이다. 에이전트가 브라우저로 거의 다 입력했고, 나는 버튼 몇 개를 눌렀다.