refactor: AI 타임아웃을 백엔드·프론트 동일 값 + 환경변수(AI_TIMEOUT_MS)로 통일

기존: 백엔드 30초(하드코딩 const)·프론트 60초(하드코딩)로 불일치
변경: 루트 .env 의 AI_TIMEOUT_MS(기본 60000)를 단일 소스로
- 백엔드 ai.service: REQUEST_TIMEOUT_MS const → ConfigService(AI_TIMEOUT_MS) 주입, 기본 60s
- 프론트 useAi: import.meta.env.VITE_AI_TIMEOUT_MS 사용, 기본 60s
- docker-compose: 백엔드 environment 에 AI_TIMEOUT_MS, 프론트 build arg 에 VITE_AI_TIMEOUT_MS=${AI_TIMEOUT_MS}
- 프론트 Dockerfile ARG/ENV, env.d.ts 타입, 루트 .env.example 추가
미설정/비정상 값이면 양쪽 모두 기본 60초로 폴백.

검증: 백엔드 build/lint 0, 프론트 type-check/lint/build 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 13:01:51 +09:00
parent ff33fb2e6c
commit 042d724b3a
6 changed files with 27 additions and 4 deletions
+7 -2
View File
@@ -43,7 +43,8 @@ export interface ChecklistSuggestionGroup {
}
const ANTHROPIC_URL = 'https://api.anthropic.com/v1/messages';
const REQUEST_TIMEOUT_MS = 30_000;
// AI 요청 타임아웃 기본값(ms) — env AI_TIMEOUT_MS 로 재정의. 프론트와 동일 값을 사용한다.
const DEFAULT_AI_TIMEOUT_MS = 60_000;
const MAX_TOKENS = 1024;
const TITLE_MAX = 60;
// 컨텍스트로 주입할 담당 업무 최대 건수(토큰 절약)
@@ -99,6 +100,7 @@ export class AiService {
private readonly logger = new Logger(AiService.name);
private readonly apiKey: string;
private readonly model: string;
private readonly timeoutMs: number;
constructor(
config: ConfigService,
@@ -113,6 +115,9 @@ export class AiService {
this.model = (
config.get<string>('CLAUDE_MODEL') ?? 'claude-sonnet-4-6'
).trim();
// AI 타임아웃 — env AI_TIMEOUT_MS(ms), 미설정/비정상이면 기본값
const t = Number(config.get<string>('AI_TIMEOUT_MS'));
this.timeoutMs = Number.isFinite(t) && t > 0 ? t : DEFAULT_AI_TIMEOUT_MS;
if (!this.apiKey) {
this.logger.warn('CLAUDE_API_KEY 미설정 — AI 채팅 비활성화');
}
@@ -446,7 +451,7 @@ export class AiService {
system,
messages,
}),
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
signal: AbortSignal.timeout(this.timeoutMs),
});
} catch (e) {
this.logger.error(