-
[Google Spreadsheet & Apps Script] Gemini API로 번역 및 검수하기Unity 2025. 3. 7. 15:05
개요
해당 포스팅은 하단의 포스팅의 연장선으로 작성되었다. Localization을 아직 연동시키지 않았다면 다음 포스팅을 참고하기 바란다.
[Unity + Google SpreadSheet] 구글 스프레드 시트 자동 번역 기능 제작 & Unity 연결(Google Sheet Service) (1)
개요해당 포스팅은 하단의 포스팅의 연장선으로 작성되었다. Localization을 아직 연동시키지 않았다면 다음 포스팅을 참고하기 바란다. [Unity] Localization을 활용하여 국가별 맞는 언어 적용하기
cgmoon.tistory.com
이전 포스팅에서 구글 스프레드 시트에 자동 번역 스크립트를 추가하는 작업을 진행했었다.
구글에서 제공하는 LanguageApp 라이브러리를 활용하여 간단하게 기계번역을 진행했었다.
하지만 조금 더 자연스러운 번역을 원했고, 이에 다양한 방법을 고민해보았다.
0. 번역 및 검수 작업 프로세스 고민 과정
번역과 검수 작업을 진행하기 위한 세가지 방법을 생각해 보았다.
- LanguageApp.translate: 기존 코드에 사용한 방법. 기본적으로 제공하는 라이브러리를 사용하여 기계 번역(무료)
- Google Cloud Translation Advanced API: 신경망 기반 번역을 활용한 자연스러운 번역이 가능 (유료)
- AI API(Gemini / ChatGPT 등등): 인공지능을 활용하여 자연스러운 번역을 진행(무료 / 유료)
고려사항은 다음과 같았다.
1. 길고 복잡한 텍스트를 번역하지는 않기 때문에, 고도화된 기능을 쓸 필요는 없다.
2. 속도가 느리지는 않았으면 한다.
3. 현재는 돈을 사용하기에는 부담스럽다.
그래서 선택한 방법은
- LanguageApp.translate를 써서 1차적으로 번역을 진행한다.
- AI API를 써서 번역 검수를 진행하고, 문제가 있으면 수정하여 반환한다.
여기서 AI API 는 gemini 무료 플랜을 사용하였다. Chatgpt는 사용하려면 토큰을 충전해줘야 되기 때문에,
1. Gemini API 키 발급받기
로그인 - Google 계정
이메일 또는 휴대전화
accounts.google.com
해당 링크로 들어가서 로그인하면 다음과 같은 화면이 뜬다.
Get API Key를 누르고 개인정보 처리방침에 동의하면,
다음과 같은 화면이 팝업된다.
API 키 만들기를 눌러 키를 생성해주자.
생성된 키를 복사하여 안전한 곳에 붙여두자.
2. 기존 Apps Script 수정하기
이제 기존 Apps Script에서, AI를 활용하여 검수가 가능하도록 코드를 수정해보자.
기존 코드는 다음과 같다
// 구글 스프레드 시트에 버튼을 만들어주는 함수 function onOpen() { var ui = SpreadsheetApp.getUi(); ui.createMenu("번역 탭") .addItem("자동 번역 실행", "autoTranslateSheet") .addToUi(); } //번역을 진행하는 함수 function autoTranslateSheet() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); var range = sheet.getDataRange(); var values = range.getValues(); // 컬럼 인덱스 찾기 var headers = values[0]; var keyIndex = headers.indexOf("Key"); var enIndex = headers.indexOf("English(en)"); var jaIndex = headers.indexOf("Japanese(ja)"); var koIndex = headers.indexOf("Korean(ko)"); if (keyIndex === -1 || enIndex === -1 || jaIndex === -1 || koIndex === -1) { SpreadsheetApp.getUi().alert("'Key', 'English(en)', 'Japanese(ja)', 'Korean(ko)' 컬럼을 찾을 수 없습니다. 헤더를 확인하십쇼."); return; } for (var i = 1; i < values.length; i++) { var koText = values[i][koIndex]; // 한국어 탭에 내용이 있는경우 if (koText) { if (!values[i][enIndex]) { //한국어를 영어로 values[i][enIndex] = LanguageApp.translate(koText, "ko", "en"); } if (!values[i][jaIndex]) { //한국어를 일본어로 values[i][jaIndex] = LanguageApp.translate(koText, "ko", "ja"); } } } // 번역된 값 다시 시트에 반영 range.setValues(values); SpreadsheetApp.getUi().alert("✅ 번역 완료!"); }
자 이제 수정을 진행해보자.
1. API 키를 변수로 생성해준다. (맨 위에)
var GEMINI_API_KEY = "API 키를 붙어녛으세요";
2. Gemini API를 활용한 번역 검수 함수를 작성한다.
function refineTranslationWithGemini(text, targetLang) { if (!text) return ""; var url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateText?key=" + GEMINI_API_KEY; var payload = { contents: [{ role: "user", parts: [{ text: `Please refine the following translation to sound more natural in ${targetLang}. This text will be used in a video game UI or system messages, so make sure the translation is appropriate for a gaming context. Adjust the wording to match common game terminology and ensure clarity for players. Keep the response as short and natural as possible, without additional explanation. Only return the corrected translation without formatting or extra comments: "${text}"` }] }] }; var options = { method: "post", contentType: "application/json", payload: JSON.stringify(payload), muteHttpExceptions: true }; try { Logger.log("Gemini API 요청 중: " + text); var response = UrlFetchApp.fetch(url, options); var json = JSON.parse(response.getContentText()); var result = json.candidates && json.candidates.length > 0 ? json.candidates[0].content.parts[0].text : text; Logger.log("Gemini 응답 완료: " + result); return result; } catch (error) { Logger.log("Gemini API Error: " + error); return text; // 오류 발생 시 원문 유지 }
해당 함수는 검수를 중점적으로 하는 함수이다.
text: 기계번역을 통해 변환된 텍스트
targetLang: "English", "Japanaese"와 같이 어떤 언어로 검수할지 정의
예시로, key: continue / Korean: 계속하기 로 작성이 되어있고,
LanguageApp.translate를 통해 번역된 키워드는 en: continue / ja: 続ける
그렇다면, 여기서 text는 다음 단어들이 매개변수로 들어간다.
이에 맞게 refineTranslationWithGemini("continue","English")로 함수를 실행시키게 되는것이다.gemini에서 제공하는 url 형식에 맞춰, 프롬프트를 작성해준다.
해당 프롬프트의 내용은
"좀 더 자연스러운 방향으로 수정해봐라. 비디오 게임 UI에 맞는 용어로 수정하고, 잡다한 설명은 붙이지 마라. 맞는 번역만 반환해라"
처음에는
"Please refine the following translation to sound more natural in " + targetLang + ": '" + text + "'"
다음과 같은 프롬프트로 작성하였는데, 단어만 반환하는 것이 아닌 전체적인 내용을 반환해주어
프롬프트를 수정해주었다.이제 다음 url로 option에 맞게 반환을 요청하고, 진행상황을 로그로 확인할 수 있도록 Logger.log를 작성해주었다.
이제 번역을 진행하는 for문 안에 검수 요청을 넣어주자.
for (var i = 1; i < values.length; i++) { var koText = values[i][koIndex]; // 한국어 원문 가져오기 if (koText) { Logger.log(`처리 중: Row ${i} / ${totalRows}`); // Step 1: Google 번역 API 사용 (기본 번역) var enTranslation = values[i][enIndex] || LanguageApp.translate(koText, "ko", "en"); var jaTranslation = values[i][jaIndex] || LanguageApp.translate(koText, "ko", "ja"); // Step 2: Gemini API로 검수 요청 (게임 용어 반영) values[i][enIndex] = refineTranslationWithGemini(enTranslation, "English"); values[i][jaIndex] = refineTranslationWithGemini(jaTranslation, "Japanese"); processedRows++; //10개 단위로 진행상황 피드백 해주기 if (processedRows % 10 === 0) { SpreadsheetApp.getActiveSpreadsheet().toast(`🔄 ${processedRows} / ${totalRows} 번역 완료...`, "진행 상황", 5); } } }
기계번역을 진행하고, API로 검수 작업을 진행한다.
AI 피드백에서 걸리는 시간을 확인하기 위해, 10개단위로 토스트 메시지를 띄워 너무 오래걸리지는 않는지 확인할 수 있게 한다.
수정된 전체 코드는 다음과 같다
var GEMINI_API_KEY = "API Key"; // Gemini API 키 입력 function onOpen() { var ui = SpreadsheetApp.getUi(); ui.createMenu("번역 탭") .addItem("자동 번역 실행", "autoTranslateSheet") .addToUi(); } function autoTranslateSheet() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); var range = sheet.getDataRange(); var values = range.getValues(); var headers = values[0]; var keyIndex = headers.indexOf("Key"); var enIndex = headers.indexOf("English(en)"); var jaIndex = headers.indexOf("Japanese(ja)"); var koIndex = headers.indexOf("Korean(ko)"); if (keyIndex === -1 || enIndex === -1 || jaIndex === -1 || koIndex === -1) { SpreadsheetApp.getUi().alert("컬럼을 찾을 수 없습니다. 확인해주세요."); return; } // 실행 중 메시지 표시 SpreadsheetApp.getActiveSpreadsheet().toast("번역 및 검수 작업을 시작합니다...", "진행 상황", 5); var totalRows = values.length - 1; var processedRows = 0; for (var i = 1; i < values.length; i++) { var koText = values[i][koIndex]; // 한국어 원문 가져오기 if (koText) { Logger.log(`처리 중: Row ${i} / ${totalRows}`); // Step 1: Google 번역 API 사용 (기본 번역) var enTranslation = values[i][enIndex] || LanguageApp.translate(koText, "ko", "en"); var jaTranslation = values[i][jaIndex] || LanguageApp.translate(koText, "ko", "ja"); // Step 2: Gemini API로 검수 요청 (게임 용어 반영) values[i][enIndex] = refineTranslationWithGemini(enTranslation, "English"); values[i][jaIndex] = refineTranslationWithGemini(jaTranslation, "Japanese"); processedRows++; if (processedRows % 10 === 0) { SpreadsheetApp.getActiveSpreadsheet().toast(`🔄 ${processedRows} / ${totalRows} 번역 완료...`, "진행 상황", 5); } } } // Google Sheets에 업데이트 range.setValues(values); SpreadsheetApp.getActiveSpreadsheet().toast("번역 및 검수 완료!", "완료", 5); } //Gemini API를 활용한 번역 검수 함수 (게임 용어 반영 프롬프트 추가) function refineTranslationWithGemini(text, targetLang) { if (!text) return ""; var url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateText?key=" + GEMINI_API_KEY; var payload = { contents: [{ role: "user", parts: [{ text: `Please refine the following translation to sound more natural in ${targetLang}. This text will be used in a video game UI or system messages, so make sure the translation is appropriate for a gaming context. Adjust the wording to match common game terminology and ensure clarity for players. Keep the response as short and natural as possible, without additional explanation. Only return the corrected translation without formatting or extra comments: "${text}"` }] }] }; var options = { method: "post", contentType: "application/json", payload: JSON.stringify(payload), muteHttpExceptions: true }; try { Logger.log("🔄 Gemini API 요청 중: " + text); var response = UrlFetchApp.fetch(url, options); var json = JSON.parse(response.getContentText()); var result = json.candidates && json.candidates.length > 0 ? json.candidates[0].content.parts[0].text : text; Logger.log("✅ Gemini 응답 완료: " + result); return result; } catch (error) { Logger.log("❌ Gemini API Error: " + error); return text; // 오류 발생 시 원문 유지 } }
이제 이 기능을 실행시켜보자.
먼저 테이블에 데이터를 입력해주자.
Key English(en) Japanese(ja) Korean(ko) welcome 환영합니다! start_game 게임 시작 exit 게임 종료하기 edit_farm 농장 꾸미기 shop 상점 new_game 새 게임 continue 계속하기 load_game 불러오기 save_game 저장하기 settings 설정 audio_settings 오디오 설정 graphics_settings 그래픽 설정 language 언어 help 도움말 pause 일시정지 resume 계속하기 restart 다시 시작하기 back 뒤로 가기 confirm 확인 cancel 취소 tutorial 튜토리얼 inventory 인벤토리 quest 퀘스트 skills 스킬 achievements 업적 level_up 레벨 업! mission_complete 미션 완료! mission_failed 미션 실패! game_over 게임 오버 victory 승리! defeat 패배… reward 보상 collect 수집하기 claim_reward 보상 받기 attack 공격 defend 방어 special_move 특수 기술 use_item 아이템 사용 equip 장착하기 unequip 해제하기 upgrade 업그레이드 daily_bonus 오늘의 보너스 event 이벤트 leaderboard 리더보드 multiplayer 멀티플레이 reconnect 다시 연결하기 일단 테이블에 다음과 같이 데이터를 작성해보자.
그러고 번역탭을 눌러 기능을 실행시켜보자.
우측 하단에 토스트 메시지가 팝업되며, 진행상황을 확인할 수 있다.
완료된 후 테이블을 보면,
와우! 꽤나 깔끔하게 번역된 것을 확인할 수 있다.
마무리하며....
우리는 이제 번역 및 검수작업을 자동으로 진행해주는 프로그램을 완성시켰다.
이 코드는 당연히 더 발전시킬 수 있는 여지가 있다.
텍스트 변동이 감지되면 자동으로 번역을 해주거나
이상한 부분을 어떻게 수정했는지 띄워주거나.
각자의 역량을 활용해서 재밌는 기능을 더 추가해 볼 수 있을것이다.
이 포스팅 글이 이상한 번역때문에 곤욕을 치른 사람들에게 도움이 되길 바라며,
😘즐코(즐거운 코딩 되시길)!
'Unity' 카테고리의 다른 글
[Unity + Google SpreadSheet] 구글 스프레드 시트 자동 번역 기능 제작 & Unity 연결(Google Sheet Service) (2) (1) 2025.03.07 [Unity + Google SpreadSheet] 구글 스프레드 시트 자동 번역 기능 제작 & Unity 연결(Google Sheet Service) (1) (1) 2025.03.07 [Unity] Localization을 활용하여 국가별 맞는 언어 적용하기 (0) 2025.03.06 [Unity & iOS] 유니티에서 iOS용 앱 빌드하기 (Feat. 처음 iOS개발할때 발생하는 문제들) (0) 2025.02.14 [Firebase] 유니티에 파이어베이스 연동하기 (4) 2025.02.01