From 8dfe6d5de030e83649535c2fde119e47198f433a Mon Sep 17 00:00:00 2001 From: gahusb Date: Mon, 23 Mar 2026 08:54:53 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=ED=8F=AC=ED=8A=B8=ED=8F=B4=EB=A6=AC?= =?UTF-8?q?=EC=98=A4=20=EC=84=B1=EA=B3=BC=20=EC=88=98=EC=B9=98=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=20+=20=EB=A1=9C=EB=98=90=20=EB=B2=95=EC=A0=81=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=81=AC=20=EB=AC=B8=EA=B5=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - freelance/page.tsx: 포트폴리오 카드에 result 필드 렌더링 추가 (녹색 체크 배지) - freelance/page.tsx: StatCard sublabel 구체화 — 자동화 28·웹개발 14·기타 5 / 재의뢰·소개 고객 비율 포함 - lotto/page.tsx: "확률 최적화" → "통계 기반 번호 선택 도구", 당첨 보장 없음 명시 - CLAUDE.md: 사주 시스템 docs 업데이트 Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 49 +++++++++++++++++++++++++++++++++++++ app/freelance/page.tsx | 20 ++++++++++++--- app/services/lotto/page.tsx | 24 +++++++++--------- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4a2ebfa..336385e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -62,3 +62,52 @@ app/ - 사이드바는 `usePathname`으로 활성 경로 감지 - 모바일: 햄버거 메뉴로 사이드바 토글 (overlay 포함) - 이미지 없이 아이콘·그래디언트·SVG로 시각적 완성도 유지 + +--- + +## 사주 시스템 (`/app/saju`, `/lib/saju-*.ts`) + +### AI 연동 (`app/api/saju/analyze/route.ts`) +- **AI**: Google Gemini (`@google/generative-ai`) +- **모델 폴백 순서**: `gemini-2.5-pro` → `gemini-2.5-flash` → `gemini-2.0-flash` +- **핵심 패턴**: `systemInstruction`(프롬프트)과 `userMessage`(트리거) 분리 필수 + - 전체 프롬프트를 user 메시지로 보내면 응답 품질 저하 +- **Windows 환경**: `dotenv`로 `.env.local`을 명시적 로드 (`override: true`) +- **Vercel 타임아웃**: `export const maxDuration = 60` (Pro 플랜 기준) +- **Mock 감지**: `isMockInterpretation()` 함수로 DB에 캐시된 예시 데이터 판별 + - `SajuAISection.tsx`에서 mock이면 `validSaved = null`로 처리 → API 재호출 + - 재생성 버튼(🔄)으로 수동 재생성 가능 + +### 사주팔자 계산 원칙 (검증 완료) + +#### `lib/saju-calculator.ts` +| 항목 | 올바른 값 | 주의사항 | +|------|-----------|----------| +| **일주 기준일** | 1900-01-01 = 甲戌 (stem=0, branch=10) | 丙寅(2,2)은 오답 | +| **날짜 계산** | `Date.UTC()` 사용 필수 | `new Date()`는 DST/타임존 오차로 1일 오류 발생 | +| **월 천간** | 오호둔월법(五虎遁月法) 공식 사용 | `yearStemIndex * 2 + branchIndex`는 子月/丑月 오답 | +| **입춘 기준** | `getSolarTermDate(year, 0)`으로 입춘일 획득 후 비교 | 입춘 이전 출생 → 전년도 년주 사용 | + +**오호둔월법 공식** (`getMonthGanzi` 내): +```typescript +const startStem = ((yearStemIndex % 5) * 2 + 2) % 10; // 寅月 시작 천간 +const stemIndex = (startStem + (branchIndex - 2 + 12) % 12) % 10; +``` + +#### `lib/solar-terms.ts` — `getCurrentSolarTerm()` +- 반드시 입춘(0) 기준으로 두 구간 분리 처리 + - **입춘 이후(2~12월)**: 입춘(0)~동지(21) 역순 검색 + - **입춘 이전(1월)**: 이 해의 소한(22)/대한(23) → 전년도 동지(21)~입춘(0) 역순 검색 +- 기존 단순 역순(i=23→0) 방식은 12월 날짜에서 丑月 오판하는 치명적 버그 +- 날짜 비교는 `Date.UTC()` 사용 + +#### `lib/ai-interpretation.ts` — `estimateYongShin()` +- **신약 사주 용신**: 인성/비겁 중 **점수가 높은(강하게 존재하는)** 것이 용신 + - 내림차순 정렬: `candidates.sort((a, b) => b.score - a.score)` + - 낮은 점수를 용신으로 고르면 실질적 도움을 못 줌 + +### 검증 케이스 (1992-12-23 16:30 남성) +``` +년주: 壬申 월주: 壬子 일주: 癸酉 시주: 庚申 +``` +이 결과가 나오면 계산 로직 정상. 다른 값이면 위 원칙 재확인. diff --git a/app/freelance/page.tsx b/app/freelance/page.tsx index ee2e2b9..c647251 100644 --- a/app/freelance/page.tsx +++ b/app/freelance/page.tsx @@ -42,6 +42,7 @@ const portfolio = [ title: '주식 자동 매매 프로그램', category: '핀테크 · 알고트레이딩', desc: '텔레그램 연동 주식 자동 매매 시스템. 기술적 분석 신호 기반 자동 매수/매도, 포트폴리오 관리 기능 포함.', + result: '매매 신호 알림 2,300+회 자동 발송 (직접 운영 중)', tags: ['Python', 'Telegram API', '증권사 API', 'SQLite'], status: '직접 운영 중', statusType: 'live', @@ -53,7 +54,8 @@ const portfolio = [ { title: '로또 번호 분석 서비스', category: '데이터 분석 · 구독 서비스', - desc: '전체 로또 회차 빅데이터 분석 플랫폼. 출현 빈도, 핫/콜드 번호, 패턴 분석 및 매주 번호 조합 자동 생성.', + desc: '1,100+회차 로또 데이터 분석 플랫폼. 출현 빈도·핫/콜드 번호 통계 및 매주 번호 조합 자동 생성.', + result: '1,100+회차 데이터 자동 수집·분석, 구독자 매주 자동 발송', tags: ['Python', 'FastAPI', 'PostgreSQL', 'Next.js'], status: 'NAS 서버 운영 중', statusType: 'live', @@ -66,6 +68,7 @@ const portfolio = [ title: 'Gmail 자동화 RPA', category: 'RPA · 업무 자동화', desc: '거래처 이메일 수신 시 자동 분류, 답장 초안 작성, 담당자 알림 전송하는 Gmail 자동화 시스템.', + result: '이메일 처리 시간 일 2시간 → 10분 (의뢰인 직접 확인)', tags: ['Python', 'Gmail API', 'Google Apps Script'], status: '납품 완료', statusType: 'done', @@ -78,6 +81,7 @@ const portfolio = [ title: '쇼핑몰 가격 모니터링 봇', category: '웹 스크래핑 · 알림 자동화', desc: '경쟁사 쇼핑몰의 특정 상품 가격을 매일 모니터링하여 변동 시 텔레그램으로 즉시 알림.', + result: '경쟁사 10곳 · 상품 50개 매일 자동 추적, 수동 확인 0분', tags: ['Python', 'Selenium', 'Telegram Bot'], status: '납품 완료', statusType: 'done', @@ -90,6 +94,7 @@ const portfolio = [ title: '영업 일보 자동화 시스템', category: '엑셀 자동화 · 보고서 생성', desc: '영업 데이터 엑셀 파일을 자동으로 집계하여 일별/주별/월별 영업 일보 PDF를 생성하고 이메일 발송.', + result: '보고서 작성 3시간 → 5분, 매일 09:00 자동 발송', tags: ['Python', 'OpenPyXL', 'ReportLab'], status: '납품 완료', statusType: 'done', @@ -102,6 +107,7 @@ const portfolio = [ title: '부동산 공시지가 수집 시스템', category: '공공 데이터 · API 연동', desc: '국토교통부 공공 API를 통해 특정 지역 공시지가를 주기적으로 수집·저장하고 변동 알림 제공.', + result: '전국 3개 지역 공시지가 주 1회 자동 수집·변동 알림', tags: ['Python', '공공데이터 API', 'PostgreSQL', 'Telegram'], status: '납품 완료', statusType: 'done', @@ -279,8 +285,8 @@ export default function FreelancePage() {
- - + +
{/* developer tag */} @@ -350,6 +356,14 @@ export default function FreelancePage() { {/* card body */}

{item.desc}

+ {item.result && ( +
+ + + + {item.result} +
+ )}
{item.tags.map((tag) => ( diff --git a/app/services/lotto/page.tsx b/app/services/lotto/page.tsx index 48c539c..0fe66a3 100644 --- a/app/services/lotto/page.tsx +++ b/app/services/lotto/page.tsx @@ -9,7 +9,7 @@ const CHECKLIST = [ '구독 플랜 선택 (골드 / 플래티넘 / 다이아)', '번호 수신 방법 (이메일 / 텔레그램 중 선택)', '로또 구매 후 직접 확인 필요 (자동 구매 아님)', - '당첨 보장 없음 — 통계 기반 확률 최적화 서비스', + '당첨 보장 없음 — 과거 데이터 통계 기반 번호 선택 도구', '구독 취소는 이메일로 언제든 가능', ]; @@ -38,7 +38,7 @@ const plans = [ '매주 3회 번호 조합 제공', '핫넘버 / 콜드넘버 분석', '연속 번호 / 끝수 패턴 분석', - '당첨 확률 시뮬레이션', + '번호 조합 백테스트 (과거 회차 검증)', '이메일 + 텔레그램 알림', ], highlight: true, @@ -53,7 +53,7 @@ const plans = [ features: [ '플래티넘 플랜 전체 기능', '번호 생성 횟수 무제한', - '연간 당첨 패턴 리포트', + '연간 번호 출현 통계 리포트', '우선 고객 지원', ], highlight: false, @@ -64,7 +64,7 @@ const plans = [ const faqs = [ { q: '로또 번호 추천이 실제로 효과가 있나요?', - a: '당첨을 보장하지는 않습니다. 다만 출현 빈도·패턴 통계를 기반으로 확률적으로 유리한 번호 조합을 제공합니다. NAS 서버에서 실제 데이터를 직접 분석하고 운영 중입니다.', + a: '로또는 완전 무작위 추첨으로, 당첨을 보장하거나 확률을 높이는 서비스가 아닙니다. 다만 1,100+회차 과거 데이터의 번호 출현 빈도를 통계로 보여주고, 그 통계를 참고해 번호를 선택하고 싶은 분들을 위한 취미형 분석 도구입니다.', }, { q: '번호는 어떻게 받을 수 있나요?', @@ -79,9 +79,9 @@ const faqs = [ const analysisFeatures = [ { label: '출현 빈도 분석', desc: '1회차~최신 회차까지 모든 번호의 출현 횟수와 비율 계산', stat: '1,100+', statLabel: '회차 데이터', accent: 'border-amber-300 bg-amber-50', statColor: 'text-amber-600' }, { label: '핫/콜드 넘버', desc: '최근 20회차 기준 자주 나온 번호와 오래 안 나온 번호 구분', stat: '45', statLabel: '개 번호 분석', accent: 'border-orange-300 bg-orange-50', statColor: 'text-orange-600' }, - { label: '연속 번호 패턴', desc: '연속된 번호 쌍의 출현 패턴을 분석하여 번호 선택에 활용', stat: '98%', statLabel: '패턴 적용률', accent: 'border-yellow-300 bg-yellow-50', statColor: 'text-yellow-600' }, + { label: '연속 번호 통계', desc: '역대 당첨 번호 중 연속 번호가 포함된 회차 비율 통계 제공', stat: '98%', statLabel: '연속 번호 포함 회차', accent: 'border-yellow-300 bg-yellow-50', statColor: 'text-yellow-600' }, { label: '끝수 통계', desc: '끝자리 0~9 번호들의 출현 비율을 분석하여 분산 조합', stat: '10', statLabel: '끝수 구간', accent: 'border-amber-300 bg-amber-50', statColor: 'text-amber-600' }, - { label: '번호 조합 시뮬레이션', desc: '추천 번호로 과거 회차 시뮬레이션을 진행하여 효과 검증', stat: '500+', statLabel: '회 시뮬레이션', accent: 'border-orange-300 bg-orange-50', statColor: 'text-orange-600' }, + { label: '번호 조합 백테스트', desc: '선택한 번호로 과거 회차 대조 검증 — 몇 회나 일치했는지 확인', stat: '500+', statLabel: '회차 백테스트', accent: 'border-orange-300 bg-orange-50', statColor: 'text-orange-600' }, { label: '정기 자동 발송', desc: '매주 정해진 요일에 이메일 및 텔레그램으로 번호 자동 발송', stat: '매주', statLabel: '자동 배송', accent: 'border-yellow-300 bg-yellow-50', statColor: 'text-yellow-600' }, ]; @@ -139,14 +139,14 @@ export default function LottoPage() {
-

LOTTO ANALYTICS · 빅데이터 통계 분석

+

LOTTO STATISTICS · 과거 회차 데이터 분석 도구

로또 번호
- 빅데이터 추천 + 통계 기반 선택

- 1회차부터 현재까지 전체 당첨 데이터를 분석하여 출현 패턴, 핫/콜드 번호, - 연속 번호 통계를 기반으로 번호 조합을 추천합니다. + 1회차부터 현재까지 1,100+회차 데이터를 분석하여 출현 빈도, 핫/콜드 번호, + 연속 번호 통계를 보여주는 취미형 분석 도구입니다. 당첨 보장 서비스가 아닙니다.

{[7, 14, 23, 35, 41, 44].map((n, i) => ( @@ -206,7 +206,7 @@ export default function LottoPage() {

ANALYSIS ENGINE

6가지 통계 분석 엔진

-

단순 랜덤이 아닌 데이터 기반의 확률 최적화

+

1,100+회차 과거 데이터를 분석하여 보여주는 통계 — 당첨 보장 없음

{analysisFeatures.map((f) => ( @@ -258,7 +258,7 @@ export default function LottoPage() { { feature: '핫/콜드 번호 분석', gold: '✓', plat: '✓', dia: '✓' }, { feature: '구매 기록 관리', gold: '✓', plat: '✓', dia: '✓' }, { feature: '내 패턴 AI 분석', gold: '—', plat: '✓', dia: '✓' }, - { feature: '연간 당첨 패턴 리포트', gold: '—', plat: '—', dia: '✓' }, + { feature: '연간 번호 출현 통계 리포트', gold: '—', plat: '—', dia: '✓' }, { feature: '우선 고객 지원', gold: '—', plat: '—', dia: '✓' }, ].map((row, i) => (