API 엔드포인트 및 요청 분석
번역 기능을 구현하기 위해 외부 번역 API를 호출하는 프로세스를 분석해야 합니다. 특정 번역 서비스의 웹 인터페이스는 백그라운드에서 POST 요청을 통해 데이터를 주고받습니다. 이 요청을 모방하여 번역 결과를 가져올 수 있으며, 이때 URL 파라미터와 페이로드(Payload) 구성에 주의해야 합니다. 예를 들어, 요청 URL에서 특정 접미사를 제거하고, 폼 데이터에 typoResult와 같은 필수 필드를 포함시켜야 정상적인 JSON 응답을 수신할 수 있습니다.
다음은 명령줄 인터페이스(CLI) 환경에서 requests와 json 모듈을 사용하여 번역 요청을 보내고 응답을 출력하는 기본 구현 코드입니다.
import requests
import json
def fetch_translation(query_text):
# API 엔드포인트 설정 (특정 접미사 제거)
endpoint = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
# POST 요청에 필요한 페이로드 구성
payload = {
'i': query_text,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTIME',
'typoResult': 'false'
}
# POST 요청 전송 및 예외 처리
response = requests.post(endpoint, data=payload)
response.raise_for_status()
# JSON 응답 파싱
return response.json()
if __name__ == "__main__":
user_input = input("번역할 텍스트를 입력하세요: ")
result_data = fetch_translation(user_input)
print(json.dumps(result_data, ensure_ascii=False, indent=4))
Tkinter를 활용한 GUI 애플리케이션 구축
명령줄 기반의 스크립트를 실제 사용자가 편리하게 사용할 수 있는 데스크톱 애플리케이션으로 전환하기 위해 Python의 표준 GUI 라이브러리인 Tkinter를 사용합니다. Tkinter는 윈도우, 버튼, 텍스트 입력 및 출력 영역과 같은 위젯을 제공하여 직관적인 사용자 인터페이스를 빠르게 구축할 수 있게 해줍니다.
아래 코드는 객체지향 설계를 적용하여 번역 로직과 UI 로직을 분리한 완전한 GUI 번역기 애플리케이션입니다. place 대신 pack 레이아웃 매니저를 사용하여 위젯 배치를 유연하게 관리하며, 예외 처리와 입력값 검증을 추가하여 안정성을 높였습니다.
import requests
import json
import tkinter as tk
from tkinter import messagebox
class TranslationService:
@staticmethod
def get_translated_text(text):
api_url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
form_data = {
'i': text,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTIME',
'typoResult': 'false'
}
try:
res = requests.post(api_url, data=form_data)
res.raise_for_status()
parsed_json = res.json()
# 응답 JSON에서 실제 번역 결과 추출
return parsed_json['translateResult'][0][0]['tgt']
except requests.exceptions.RequestException as e:
return f"네트워크 오류 발생: {e}"
except (KeyError, IndexError):
return "응답 데이터를 파싱하는 데 실패했습니다."
class TranslatorApp:
def __init__(self, root):
self.root = root
self.root.title("데스크톱 번역기")
self.root.geometry("420x450")
self.root.resizable(False, False)
self.service = TranslationService()
self._build_ui()
def _build_ui(self):
# 원본 텍스트 입력 영역
tk.Label(self.root, text="원본 텍스트:", font=("Malgun Gothic", 10, "bold")).pack(pady=(15, 5))
self.input_text = tk.Text(self.root, height=7, width=48, bg="#f4f8fb", relief="solid", borderwidth=1)
self.input_text.pack(padx=15)
# 컨트롤 버튼 영역
btn_frame = tk.Frame(self.root)
btn_frame.pack(pady=15)
self.translate_btn = tk.Button(btn_frame, text="번역하기", command=self._execute_translation, width=12, bg="#4CAF50", fg="white")
self.translate_btn.pack(side=tk.LEFT, padx=10)
self.clear_btn = tk.Button(btn_frame, text="초기화", command=self._clear_fields, width=12, bg="#f44336", fg="white")
self.clear_btn.pack(side=tk.LEFT, padx=10)
# 번역 결과 출력 영역
tk.Label(self.root, text="번역 결과:", font=("Malgun Gothic", 10, "bold")).pack(pady=(5, 5))
self.output_text = tk.Text(self.root, height=7, width=48, bg="#e8f5e9", relief="solid", borderwidth=1)
self.output_text.pack(padx=15)
def _execute_translation(self):
# 입력된 텍스트 가져오기 및 포맷팅
source = self.input_text.get("1.0", tk.END).strip().replace("\n", " ")
if not source:
messagebox.showwarning("입력 오류", "번역할 텍스트를 입력해주세요.")
return
# 번역 서비스 호출 및 결과 표시
translated = self.service.get_translated_text(source)
self.output_text.config(state=tk.NORMAL)
self.output_text.delete("1.0", tk.END)
self.output_text.insert(tk.END, translated)
def _clear_fields(self):
# 모든 텍스트 필드 초기화
self.input_text.delete("1.0", tk.END)
self.output_text.delete("1.0", tk.END)
if __name__ == "__main__":
main_window = tk.Tk()
app = TranslatorApp(main_window)
main_window.mainloop()