프리미엄 기능 크래시 5연속 — AI가 만든 코드의 타입 불일치 해결기

문제 해결 노트··19분 읽기·
프리미엄 예측 기능에서 발생한 5개 연속 버그를 수정하는 과정

프리미엄 기능을 켰더니 아무것도 안 됐다

프리미엄 예측 기능을 만들고 테스트를 해봤는데, 설정이 저장 안 되고, 자동 예측은 엉뚱한 함수를 호출하고, 분석 페이지는 빈 화면. 한 번에 5개가 터졌습니다.

AI한테 "프리미엄 기능 안 돼. 고쳐줘"라고 하면 뭘 고쳐야 하는지 모르죠. 그래서 하나씩 에러를 추적해서 구체적으로 물어봤습니다.

버그 1: Math.min이 -1을 5로 바꿔버렸다

설정 페이지에서 분석 기간을 -1(전체)로 선택했는데, 저장하면 5로 바뀌어 있었습니다.

원인은 AI가 넣어둔 범위 제한 코드:

// 문제 코드 (settings/route.ts line 80, 86)
analysis_period: Math.min(Math.max(settings.analysis_period, 5), 50)
daily_prediction_count: Math.min(Math.max(settings.daily_prediction_count, 10), 200)

-1은 "전체 기간"을 의미하는 특수값인데, Math.max(-1, 5) = 5. 특수값이 사라진 겁니다. 0(기본값)도 마찬가지로 5로 변환되고 있었고요.

당신은 React 폼 유효성 검사 전문가입니다.

[에러 상황]
- 설정 저장 API에서 Math.min(Math.max(value, 5), 50)으로 범위 강제
- 유효 값: -1(전체), 0(기본), 5~50(커스텀)
- 특수값 -1, 0이 5로 변환되어 저장됨

[요청]
특수값(-1, 0)은 범위 제한에서 제외하고,
커스텀 값(1 이상)만 5~50 범위로 제한하는 검증 로직을 만들어주세요.
settings/route.ts line 80, 86 두 곳 모두 적용해주세요.

AI가 특수값 체크를 앞에 넣는 로직으로 수정해줬습니다. "line 80, 86"처럼 정확한 위치를 알려주니까 AI가 정확히 그 부분만 고쳤습니다.

버그 2: AI가 만든 임시 함수가 프로덕션에 남아있었다

오전 9시 자동 예측(cron job)이 실제 AI 엔진 대신 generateWeightedRandomNumbers()라는 함수를 호출하고 있었습니다. AI가 프로토타입 단계에서 "일단 돌아가게" 만든 랜덤 함수인데, 실제 엔진으로 교체를 안 한 거예요.

[에러 상황]
/api/cron/premium/predict/route.ts에서
generateWeightedRandomNumbers() 호출 중.
이 함수는 실제 AI 분석이 아니라 가중 랜덤 번호 생성기입니다.

[요청]
1. cron job에서 실제 AI 엔진 4개(ALPHAGO, LSTM, STATISTICAL, ASSOCIATION)를
   순차 호출하도록 수정
2. 실제 API: /api/predict (POST, body에 engine 타입 전달)
3. Promise.allSettled로 병렬 실행 + 30초 타임아웃 추가

"지금 생성" 버튼도 같은 문제였습니다. 존재하지 않는 /api/predict/premium/generate 엔드포인트를 호출하고 있었거든요. AI가 "나중에 만들 거"하고 미리 연결해둔 건데, 실제로 만들지 않은 상태. 실제 엔드포인트 /api/predict로 경로만 바꿔주면 됐습니다.

버그 3: JSON 문자열을 배열로 착각

분석 API를 호출하면 크래시가 나는데, 에러 메시지가 numbers.map is not a function이었습니다.

[에러 메시지]
TypeError: numbers.map is not a function
→ LotteryDraw.numbers 필드가 배열이 아니라 JSON 문자열

[요청]
LotteryDraw.numbers를 사용하는 모든 곳에서
JSON.parse()를 먼저 실행하도록 수정해주세요.

Supabase에서 가져온 numbers 필드가 [1, 12, 23, 34, 45, 6]처럼 보이지만 실제로는 문자열 타입이었습니다. JSON.parse()를 추가하니 해결. 이 에러는 로컬에서는 안 나올 수도 있어서, 프로덕션에서만 터지면 원인 찾기가 어렵습니다.

버그 4: 숫자를 보내는데 문자열을 기대한다

가장 머리 아팠던 버그. 프리미엄 설정에서 데이터 소스를 선택하면 숫자(-1, 0, 1, 2, 3)로 저장되는데, AI 분석 API는 문자열('dhlottery', 'all', 'machine1' 등)을 기대하고 있었습니다.

[피드백]
저장 레이어와 API 레이어의 타입이 불일치합니다.

설정 저장: 숫자 (-1=동행복권, 0=전체, 1=1호기, 2=2호기, 3=3호기)
AI API 입력: 문자열 ('dhlottery', 'all', 'machine1', 'machine2', 'machine3')

[요청]
1. 숫자 → 문자열 매핑 딕셔너리
2. API 호출 직전에 변환하는 레이어
3. 기존 DB에 숫자로 저장된 레코드를 문자열로 마이그레이션하는 SQL

AI가 만든 매핑 딕셔너리:

const dataRangeMap: Record<number, string> = {
  [-1]: 'dhlottery',  // 동행복권 공식
  0: 'all',           // 전체
  100: '100', 200: '200', 300: '300', 400: '400'
};

const machineTypeMap: Record<number, string> = {
  0: 'none',      // 사용 안함
  1: 'machine1',  // 1호기
  2: 'machine2',  // 2호기
  3: 'machine3'   // 3호기
};

그리고 이미 숫자로 저장된 데이터도 마이그레이션해야 했습니다:

UPDATE prediction_archive SET data_range = 'dhlottery' WHERE data_range = '-1';
UPDATE prediction_archive SET data_range = 'all' WHERE data_range = '0';
UPDATE prediction_archive SET machine_type = 'machine1' WHERE machine_type = '1';
UPDATE prediction_archive SET machine_type = 'machine2' WHERE machine_type = '2';

결과: data_range 103건 + machine_type 103건 = 206건 레코드 업데이트 완료.

버그 5: API 응답 구조가 프론트엔드와 안 맞다

분석 페이지가 빈 화면으로 나오는 마지막 버그. API는 데이터를 정상적으로 반환하는데, 프론트엔드가 읽는 경로가 틀렸습니다.

[에러 상황]
분석 API 응답: { patterns: { odd_even: {...}, sum: {...} } }
프론트엔드 읽기: patterns.recommendations  ← 존재하지 않는 경로

연관 분석도 빈 데이터:
- minSupport 0.2 설정 → 조건에 맞는 데이터가 없음
- 시계열 분석에서 순차 인덱스 부여 누락

[요청]
1. 프론트엔드의 API 응답 매핑을 실제 구조에 맞게 수정
2. minSupport 0.2 → 0.05로 완화
3. 시계열에 순차 인덱스 부여
4. 데이터 없을 때 빈도 기반 fallback (hot_numbers, due_numbers) 추가
minSupport를 0.2에서 0.05로 낮추니까 연관 분석 결과가 나오기 시작했고, 빈 데이터 상황에서도 빈도 기반 fallback이 작동하게 됐습니다.

5개 버그의 공통 패턴

| 버그 | 원인 패턴 | AI 코드의 특징 |
|------|----------|--------------|
| Math.min/max | 특수값 예외처리 누락 | AI가 "안전한" 범위 제한을 넣지만 특수값을 모름 |
| 임시 함수 잔존 | 프로토타입 → 프로덕션 | AI가 "일단 돌아가게" 만든 코드가 남음 |
| JSON 문자열 파싱 | DB 타입과 코드 타입 불일치 | Supabase text 컬럼을 배열로 착각 |
| 숫자↔문자열 | 레이어 간 계약 불일치 | 저장/API/표시 3개 레이어가 각각 다른 타입 |
| API 응답 경로 | 프론트↔백엔드 구조 불일치 | AI가 백엔드와 프론트를 별도로 만들면서 인터페이스 안 맞음 |

AI가 만든 코드에서 반복되는 패턴이 보입니다. 기능별로 따로 만들면 각 기능은 동작하지만, 기능 간 연결부(타입, 경로, 응답 구조)에서 불일치가 생긴다. "프리미엄 기능 안 돼"가 아니라 "이 레이어는 숫자를 보내는데 저 레이어는 문자열을 기대해"처럼, 불일치 지점을 구체적으로 짚어야 AI가 정확히 고칩니다.

공유

댓글