/** * Gemini 번역 서비스 * @google/genai SDK를 사용한 이메일 번역 */ const SystemConfig = require("../models/SystemConfig"); const GeminiModel = require("../models/GeminiModel"); /** * DB에서 활성화된 Gemini 모델 목록 조회 */ const listModels = async () => { try { const models = await GeminiModel.findAll({ where: { isActive: true }, order: [["sortOrder", "ASC"]], attributes: ["modelId", "name", "description"], }); return models.map((m) => ({ id: m.modelId, name: m.name, description: m.description || "", })); } catch (error) { console.error("Gemini 모델 목록 조회 오류:", error); // 폴백: 기본 모델 반환 return [ { id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", description: "" }, ]; } }; /** * Gemini API로 텍스트 번역 * @param {string} text - 번역할 텍스트 * @param {string} targetLang - 대상 언어 (ko, en, ja, zh 등) * @param {string} apiKey - Gemini API 키 * @param {string} model - 사용할 모델 ID */ const translateText = async (text, targetLang, apiKey, model) => { if (!apiKey) { throw new Error("Gemini API 키가 설정되지 않았습니다."); } const langNames = { ko: "한국어", en: "영어", ja: "일본어", zh: "중국어", es: "스페인어", fr: "프랑스어", de: "독일어", ru: "러시아어", pt: "포르투갈어", it: "이탈리아어", }; const targetLangName = langNames[targetLang] || targetLang; const selectedModel = model || "gemini-2.5-flash"; // ES Module 동적 import const { GoogleGenAI } = await import("@google/genai"); // Google GenAI SDK 초기화 const ai = new GoogleGenAI({ apiKey }); // HTML 태그 보존하면서 번역하도록 프롬프트 작성 const prompt = `다음 이메일 내용을 ${targetLangName}로 번역해주세요. HTML 태그가 있다면 그대로 유지하고 텍스트만 번역해주세요. 번역만 출력하고 다른 설명은 하지 마세요. ${text}`; try { const response = await ai.models.generateContent({ model: selectedModel, contents: prompt, }); const translatedText = response.text; if (!translatedText) { throw new Error("번역 결과를 가져올 수 없습니다."); } return translatedText; } catch (error) { console.error("Gemini 번역 오류:", error); throw new Error(error.message || "번역 중 오류가 발생했습니다."); } }; /** * Gemini 설정 조회 (DB에서 모델 목록 가져오기) */ const getGeminiConfig = async () => { const apiKeyRecord = await SystemConfig.findOne({ where: { key: "gemini_api_key" }, }); const modelRecord = await SystemConfig.findOne({ where: { key: "gemini_model" }, }); // DB에서 모델 목록 조회 const models = await listModels(); return { gemini_api_key: apiKeyRecord?.value || "", gemini_model: modelRecord?.value || "gemini-2.5-flash", models, }; }; /** * Gemini 설정 저장 */ const saveGeminiConfig = async (config) => { // API 키가 마스킹된 값이 아닐 때만 저장 (********로 시작하지 않을 때) if ( config.gemini_api_key !== undefined && !config.gemini_api_key.includes("*") ) { await SystemConfig.upsert({ key: "gemini_api_key", value: config.gemini_api_key, }); } if (config.gemini_model !== undefined) { await SystemConfig.upsert({ key: "gemini_model", value: config.gemini_model, }); } }; module.exports = { translateText, getGeminiConfig, saveGeminiConfig, listModels, };