Rinda · Beta(Production) Hotfix

만족도 통계 · 시퀀스 진단 500 에러 핫픽스

beta 운영 환경에서 반복 발생하던 HTTP 500 2건의 근본 원인을 제거하고 alpha·beta 양 브랜치에 반영했습니다.

2026-06-19 alpha #8893 merged beta #8894 merged beta CD 배포 완료

요약

2
해소한 500 에러
3
수정 항목 (버그 2 + 테스트 가드 1)
111
단위테스트 pass / 0 fail
28~36s
로컬 CI (양 브랜치 그린)

해결한 문제

엔드포인트증상근본 원인수정
500
GET /satisfaction-survey/admin/stats
reasonRows.map is not a function — 5초간 반복 beta postgres 드라이버는 db.execute(sql`…`) 결과를 { rows } 객체로 감싸 반환하는데, getSurveyStats가 배열로 단정하고 .map 호출 → TypeError 기존 toRows() 헬퍼로 정규화 — 배열·{rows} 양쪽 드라이버 안전 처리
500
POST /sequences/propose/diagnose
Aggregated diagnosis failed schema validation 집계 쿼리는 topBusinessTypesLIMIT 10으로 반환하는데 beta 스키마는 .max(5)로 제한 → Zod 검증 실패. alpha는 #8864로 이미 해소된 상태였으나 beta 미반영(22커밋 뒤) #8864 체리픽 → 스키마 .max(10) + 대규모 그룹 집계 analyticsDb 라우팅
(가드) 단위테스트 brochure 섹션 assertion red → 머지 게이트 차단 prompt-builder가 BROCHURE — MANDATORY로 변경(URL 미주입, 서버가 첨부)됐는데 테스트는 구문구 BROCHURE LINK 기대 → alpha·beta 양쪽 CI red 테스트 assertion을 신규 동작에 동기화 (실코드 무수정)

처리 흐름

1
진단 — beta 로그에서 두 500의 정확한 실패 지점 확인. db-rows.util.ts 정규화 헬퍼가 이미 존재함을 발견(코드베이스 확립 패턴).
2
근본 원인 분리 — survey는 드라이버 반환형 차이, diagnose는 alpha엔 이미 있던 #8864가 beta에 미반영. brochure 테스트는 양 브랜치 공통 stale.
3
alphatoRows 수정 + brochure 테스트 동기화, 2개 커밋으로 분리 → PR #8893 머지.
4
beta — #8864 + survey + brochure 테스트 체리픽 → PR #8894 머지.
5
검증 — 양 브랜치 CI 그린, beta DB에서 reason 분포 SQL 직접 실행(에러 없음 → 버그가 JS 레이어임 확정), beta CD 신규 컨테이너 elysia-server-54 단독 healthy 전환 확인.

설계 노트

버그는 SQL이 아니라 JS 레이어에 있었습니다 — db.execute의 드라이버별 반환형 차이(배열 vs {rows})가 환경에 따라 갈렸기 때문에 로컬·alpha에서는 재현되지 않고 beta에서만 터졌습니다.

근본 처방: 케이스별 패치가 아니라 코드베이스에 이미 있던 toRows() 헬퍼를 사용해 모든 드라이버 반환형을 한 곳에서 흡수 — 동일 패턴의 다른 호출부와 일관성 유지(overfitting 회피).