728x90
반응형

문제점

번역할 텍스트가 적다면 오래 걸리진 않겠지만 번역할 텍스트 리스트가 많다면 아래와 같이 반복문을 활용하여 호출 시 굉장히 오래 걸려서 만족한 응답시간을 기대할 수 없을 것이다. 이유는 반복적으로 호출 시 내부적으로는 구글 API를 여러 번 호출하기 때문에 굉장히 오래 걸린다.
웹으로 서비스한다고 생각하면 타임아웃이 걸리거나 오래 걸려서 고객이 이탈할 수도 있다.

from googletrans import Translator

target_texts = ['안녕하세요', '밥 먹었습니까?']

translator = Translator()
translated_texts = []

for target_text in target_texts:
    translated_texts.append(translator.translate(text=target_text, dest='en').text)
    
translated_texts

['Hello', 'Did you have some meal?']
 

해결방안

해결 방안은 15k까지 텍스트 제한을 한다고 하니 리스트 요소마다 구분자를 넣어주고 15k씩 텍스트를 잘라서 요청하여 API 요청 횟수를 줄이면 된다.

1. wrap, unwrap 함수 정의

DELIMITER = '\n'
MAX_BYTE = 1024 * 15  # 15k

def wrap_text(texts):
    """
    번역을 하지 않는 구간을 특정 기호로 문장을 합쳐서 요청한다.
    예) ['안녕하세요', '밥 먹었습니까?'] → '안녕하세요\n밥 먹었습니까?'
    """
    texts = [text.replace(DELIMITER, '<span class="notranslate">space</span>') for text in texts]
    return DELIMITER.join(texts)

def unwrap_text(wrapped_text):
    """
    번역된 문장을 다시 특정 기호로 문장을 잘라준다.
    예) '안녕하세요\n밥 먹었습니까?' →  ['안녕하세요', '밥 먹었습니까?']
    """
    texts = wrapped_text.split(DELIMITER)
    texts = [text.replace('<span class="notranslate">space</span>', DELIMITER) for text in texts]
    return texts
    
def chunk_text_byte(text, max_byte=MAX_BYTE, delimiter=DELIMITER):
    """
    대량의 번역 문장들을 순차적으로 translate 함수를 요청시 내부적으로는 API 요청을 여러번 요청하게 되어 있으므로 성능적으로 느린 응답을 가져오게 된다.
    15K 까지 글자수가 제한이 되어있으므로 15K씩 잘라서 요청하는 것으로 네트워크 부하를 줄일 수 있다.
    """
    text = text.encode('utf-8')
    delimiter = delimiter.encode('utf-8')
    words = iter(text.split(delimiter))
    lines, current = [], next(words)

    for word in words:
        if len(current) + 1 + len(word) > max_byte:
            lines.append(current.decode('utf-8'))
            current = word
        else:
            current += delimiter + word
    lines.append(current.decode('utf-8'))
    return lines

2. 구글 번역 API 요청

위에서 만든 함수를 활용하여 15k씩 잘라서 요청을 하도록 한다.

from googletrans import Translator

translator = Translator()
translation = ''
for splitted_text in chunk_text_byte(wrap_text(target_texts)):
    translation += translator.translate(text=splitted_text, dest='en').text

3. 번역된 문장

translated_texts = []
for translated_text in unwrap_text(translation):
    translated_texts.append(translated_text)    
    
print(translated_texts)

['Hello', 'Did you have some meal?']

728x90
반응형