From a0c507a350f8055d77b817ed01584b6ac47a7fab Mon Sep 17 00:00:00 2001 From: ttipo Date: Thu, 12 Nov 2026 10:45:08 +0900 Subject: [PATCH] =?UTF-8?q?chore(backend):=20=EC=98=88=EC=8B=9C=20env=20?= =?UTF-8?q?=EC=97=90=20AI=20=EC=BD=94=EC=8A=A4=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=95=AD=EB=AA=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AI 설정(AI_PROVIDER · 모델 · effort · 하루 횟수 · 비용 상한 · 제한 시간)이 예시 파일에 없어서, 실제 env 에 무엇을 적을 수 있는지 코드를 읽어야 알 수 있었다. 키와 기본값 설명을 빈 값으로 적어 둔다. 비어 있으면 코드 기본값을 쓰므로 예시를 그대로 옮겨도 동작이 바뀌지 않는다. 설계 §11 은 이 설정들이 루트 .env 에서 compose 로 넘어간다고 적었지만 compose 는 넘기지 않는다. backend/.env.{env} 에 적는 것으로 고쳤다. Co-Authored-By: Claude Opus 5.5 --- backend/.env.development.example | 19 +++++++++++++++++++ backend/.env.production.example | 19 +++++++++++++++++++ docs/design/ai-course.md | 15 ++++++++------- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/backend/.env.development.example b/backend/.env.development.example index a0e090b..22d0bdf 100644 --- a/backend/.env.development.example +++ b/backend/.env.development.example @@ -32,3 +32,22 @@ KAKAO_REST_API_KEY=change-me-kakao-rest-api-key # Claude API 키 — AI 코스 생성. 사용량만큼 과금된다. ANTHROPIC_API_KEY=change-me-anthropic-api-key + +# ── AI 코스 생성 설정 (설계 docs/design/ai-course.md §11) ── +# 비워 두면 코드 기본값을 쓴다. 바꿀 때만 값을 적는다 — 값을 적으면 코드 기본값이 바뀌어도 이 값이 이긴다. +# AI 를 부르는 곳: anthropic(기본) · fake(키 없이 흐름만 확인하는 가짜 AI) +AI_PROVIDER= +# 코스 초안 모델(기본 claude-sonnet-5-5) · 조건 해석 모델(기본 claude-haiku-5-5) +# claude-haiku-5-5 · claude-sonnet-5-5 만 받는다(가격표 src/shared/utils/ai-pricing.ts). 바꾸면 npm run ai:eval 로 다시 잰다 +AI_COURSE_MODEL= +AI_CONDITION_MODEL= +# 추론 깊이 low · medium · high (기본 low · low) +AI_COURSE_EFFORT= +AI_CONDITION_EFFORT= +# 하루 생성 횟수 — 비로그인(기기 기준) · 로그인(사용자 기준) (기본 2 · 5) +AI_DAILY_LIMIT_GUEST= +AI_DAILY_LIMIT_MEMBER= +# 하루 비용 상한(정수 달러, 조건 해석 포함, 기본 3) — 넘으면 그날 새 생성을 막는다 +AI_DAILY_BUDGET_USD= +# AI 호출 한 번의 제한 시간(ms, 기본 30000) +AI_TIMEOUT_MS= diff --git a/backend/.env.production.example b/backend/.env.production.example index 3c4fd22..f739904 100644 --- a/backend/.env.production.example +++ b/backend/.env.production.example @@ -29,3 +29,22 @@ KAKAO_REST_API_KEY=change-me-kakao-rest-api-key # Claude API 키 — 운영용 키를 따로 발급하고 사용량 한도를 걸어 둔다. ANTHROPIC_API_KEY=change-me-anthropic-api-key + +# ── AI 코스 생성 설정 (설계 docs/design/ai-course.md §11) ── +# 비워 두면 코드 기본값을 쓴다. 바꿀 때만 값을 적는다 — 값을 적으면 코드 기본값이 바뀌어도 이 값이 이긴다. +# 운영에서는 ANTHROPIC_API_KEY 가 필수이고, AI_PROVIDER=fake 면 기동하지 않는다 +AI_PROVIDER= +# 코스 초안 모델(기본 claude-sonnet-5-5) · 조건 해석 모델(기본 claude-haiku-5-5) +# claude-haiku-5-5 · claude-sonnet-5-5 만 받는다(가격표 src/shared/utils/ai-pricing.ts). 바꾸면 npm run ai:eval 로 다시 잰다 +AI_COURSE_MODEL= +AI_CONDITION_MODEL= +# 추론 깊이 low · medium · high (기본 low · low) +AI_COURSE_EFFORT= +AI_CONDITION_EFFORT= +# 하루 생성 횟수 — 비로그인(기기 기준) · 로그인(사용자 기준) (기본 2 · 5) +AI_DAILY_LIMIT_GUEST= +AI_DAILY_LIMIT_MEMBER= +# 하루 비용 상한(정수 달러, 조건 해석 포함, 기본 3) — 넘으면 그날 새 생성을 막는다. 운영 값은 출시 전에 정한다 +AI_DAILY_BUDGET_USD= +# AI 호출 한 번의 제한 시간(ms, 기본 30000) +AI_TIMEOUT_MS= diff --git a/docs/design/ai-course.md b/docs/design/ai-course.md index c175ad8..c1e4335 100644 --- a/docs/design/ai-course.md +++ b/docs/design/ai-course.md @@ -575,16 +575,17 @@ E01 | ○○ 빛 축제 | 축제 | 실외 | 남 300m | 18:00–22:00 | 반려: | `ANTHROPIC_API_KEY` | `backend/.env.{env}` | — | 운영에서는 필수(없으면 기동 실패). 개발에서 없으면 AI API 가 `AI_002` 를 준다 | | `PUBLIC_DATA_SERVICE_KEY` | `backend/.env.{env}` | — | 이미 있는 공공데이터포털 키(장소 동기화). 날씨도 쓴다. 없으면 날씨만 '예보 없음'이다 | | `AI_PROVIDER` | `backend/.env.{env}` | `anthropic` | `fake` 면 키 없이 흐름만 돌리는 가짜 AI(개발용). 운영에서는 `fake` 면 기동 실패 | -| `AI_COURSE_MODEL` | 루트 `.env` → compose | `claude-sonnet-5-5`(평가로 정함, §8) | 코스 생성 모델. 가격표(`shared/utils/ai-pricing.ts`)에 있는 모델만 받는다 | -| `AI_CONDITION_MODEL` | 루트 `.env` → compose | `claude-haiku-5-5` | 조건 해석 모델(같은 가격표) | +| `AI_COURSE_MODEL` | `backend/.env.{env}` | `claude-sonnet-5-5`(평가로 정함, §8) | 코스 생성 모델. 가격표(`shared/utils/ai-pricing.ts`)에 있는 모델만 받는다 | +| `AI_CONDITION_MODEL` | `backend/.env.{env}` | `claude-haiku-5-5` | 조건 해석 모델(같은 가격표) | | `AI_COURSE_EFFORT` · `AI_CONDITION_EFFORT` | `backend/.env.{env}` | `low` · `low` | 추론 깊이 low · medium · high. 평가(6단계)로 둘 다 low 로 정했다(§8) | -| `AI_DAILY_LIMIT_GUEST` · `AI_DAILY_LIMIT_MEMBER` | 루트 `.env` → compose | 2 · 5 | §5 | -| `AI_DAILY_BUDGET_USD` | 루트 `.env` → compose | 개발 3 | 하루 비용 상한(정수 달러) | -| `AI_TIMEOUT_MS` | 루트 `.env` → compose | 30000 | AI 호출 제한 시간 | +| `AI_DAILY_LIMIT_GUEST` · `AI_DAILY_LIMIT_MEMBER` | `backend/.env.{env}` | 2 · 5 | §5 | +| `AI_DAILY_BUDGET_USD` | `backend/.env.{env}` | 개발 3 | 하루 비용 상한(정수 달러) | +| `AI_TIMEOUT_MS` | `backend/.env.{env}` | 30000 | AI 호출 제한 시간 | - 숫자는 `parsePositiveInt` 로 읽는다(빈 문자열 방어). 새 필수 값은 `env.validation.ts` 와 테스트에 함께 추가한다. -- 4단계(2026-11-08)는 `AI_DAILY_LIMIT_*` · `AI_DAILY_BUDGET_USD` · `AI_TIMEOUT_MS` 를 `ConfigService` 로 읽고 없으면 위 기본값을 쓴다(형식은 `env.validation.ts` 가 본다). - compose 로 넘기는 설정은 값을 바꿀 일이 생길 때 더한다 — 그 전에는 `backend/.env.{env}` 에 적으면 된다. +- AI 설정은 모두 `ConfigService` 로 읽고, 없거나 비어 있으면 위 기본값을 쓴다(형식은 `env.validation.ts` 가 본다). + compose 가 넘기지 않으므로 `backend/.env.{env}` 에 적는다. 예시 파일(`backend/.env.{env}.example`)에 빈 값으로 키를 모두 적어 두었다(2026-11-12). + 값을 적으면 코드 기본값이 바뀌어도 그 값이 이기므로, 바꿀 때만 적는다. - SDK(`@anthropic-ai/sdk`)는 컨테이너 안에서 설치하고, 잠금 파일을 npm 10 으로 확인한다(nestjs 스킬의 의존성 주의 항목). 5단계(2026-11-11)에 1.5.0 을 넣었다. 컨테이너 npm 11 이 지운 선택 peer 항목(chokidar 3개)은 이전 잠금 파일에서 되살렸다. - 모델 값은 가격표에 있어야 기동한다. 하루 비용 상한이 그 가격으로 계산되기 때문이다. 모델을 더하면 가격표와 테스트를 함께 고친다. -- 2.52.0