[Spring] DeepL API를 이용한 번역 기능 추가하기

2024. 9. 20. 23:21·Spring
반응형

 

Spring

 

DeepL 번역

대표적인 번역 API로는 Google Translate API, Microsoft Azure Translator, 그리고 최근 많이 사용되는 DeepL API가 있다.

솔직히, 아직까지는 DeepL이 다른 번역 API들보다 더 우수한 번역 결과를 보여주는 것 같다. 이번 시간에는 DeepL API를 스프링 부트에 적용하여 번역 기능을 추가해보자. 

 

DeepL API Key 발급

우선 아래 사이트로 접속한다. 

 

DeepL Pro | 텍스트, Word 및 기타 문서를 안전하게 번역하세요

빠르고 정확하며 안전한 번역. 개인 및 팀 사용자용 DeepL Pro.

www.deepl.com

 

 

DeepL 요금플랜

회원가입을 한 후에, 위 화면에서 DeepL API Free 플랜을 신청한다.

DeepL API Free 1단계
모든 필드를 작성하자

위와 같은 화면이 나오는데, 요금이 발생하지는 않는다. 무료 플랜의 경우 500,000자까지 이용할 수 있다.

API키

무료 플랜 구독을 완료한 후에, 내 계정에 들어가서 위의 API키를 복사한다.

Deepl-mock

Deepl-mock은 DeepL API를 모방하여 애플리케이션 테스트를 간소화하기 위한 모의 서버이다. 이를 통해 실제 API 호출을 하지 않고도 DeepL API와의 상호작용을 테스트할 수 있으며, 프록시 서버도 포함되어 있어 프록시 사용 테스트도 가능하게 해준다.

 

GitHub - DeepLcom/deepl-mock: deepl-mock is a mock HTTP server that simulates some behavior of the DeepL API to simplify applica

deepl-mock is a mock HTTP server that simulates some behavior of the DeepL API to simplify application testing. - DeepLcom/deepl-mock

github.com

위의 리포지토리를 클론 받은 후에 도커로 띄우거나 npm으로 실행하면 된다. 도커로 띄어보자.

$ docker image build -t deepl/deepl-mock .
$ docker run -d --rm --name deepl-mock -p3000:3000 -p3001:3001 deepl/deepl-mock

 

프로젝트 구성

build.gradle.kts

gradle 파일에 deepL라이브러리를 추가해준다.

implementation("com.deepl.api:deepl-java:1.6.0")

 

TranslateController.kt

@RestController
@RequestMapping("/api/v1/translate")
class TranslateController(
    private val translateService: TranslateService
) {

    @PostMapping
    fun translate(@RequestBody translateRequest: TranslateRequest): String {
        return translateService.translate(translateRequest)
    }
}

TranslateRequest.kt

data class TranslateRequest(
    val text: String,
    val targetLang: LanguageCode
)

TranslateService.kt

@Service
class TranslateService(
    private val translator: Translator = Translator(
        "여기에 발급 받은 DeepL API Key 값을 입력. 절대 외부(깃허브 등)에 노출 금지!!",
        TranslatorOptions().setServerUrl("http://localhost:3000") // deepL-mock을 연결하기 위한 로컬주소. 제거 예정 
        .setSendPlatformInfo(false) // DeepL로 내 어플리케이션 정보를 보내지 않음
    ),

    ) {

    fun translate(text: String, targetLang: LanguageCode): String {
        return translator.translateText(
            text, null, targetLang.code, TextTranslationOptions().setFormality(Formality.PreferMore)
        ).text
    }
}

enum class LanguageCode(val code: String) {
    ENGLISH("en-US"),
    KOREAN("ko"),
}

테스트 결과

이제 서버를 실행 후, 호출을 해보면 아래와 같이 `양성자 빔`값(테스트용 고정 값)을 리턴한다.

응답

DeepL API 호출이 정상적으로 동작하는 것을 확인했으므로, 이제 실제 API를 호출할 수 있도록 `TranslateService.kt` 코드에서 `.setServerUrl("http://localhost:3000")`를 제거한다.

결과

결과값 2

번역이 잘 된것을 확인 할 수 있다. 그러나, 첫 번째 단어인 `Hooks`는 `후크`로 번역하기 보다는 `Hooks`그대로 두거나, `훅`으로 번역되기를 원한다면. DeepL의 glossary 기능을 사용하여 특정 단어를 사용자 정의할 수 있다.

Glossary 기능 추가

Glossary기능을 통해 커스텀 용어집을 만들어보자. 우선 이전 코드를 수정해야한다.

 

TranslateRequest.kt

data class TranslateRequest(
    val text: String,
    val targetLang: Lang,
    val sourceLang: Lang,
    val glossaryId: String?
)

 

TranslateService.kt

@Service
class TranslateService(
    private val translator: Translator = Translator(
        "여기에 발급 받은 DeepL API Key 값을 입력. 절대 외부(깃허브 등)에 노출 금지!!",
        TranslatorOptions().setSendPlatformInfo(false) // DeepL로 내 어플리케이션 정보를 보내지 않음
    ),

    ) {

	fun translate(translateRequest: TranslateRequest): String {
        val translationOptions = TextTranslationOptions().setFormality(Formality.PreferMore)
        // glossaryId가 있으면 glossary를 사용하겠다는 의미
        translateRequest.glossaryId?.let { translationOptions.setGlossary(it) }

        val text = translator.translateText(
            translateRequest.text,
            // Glossary 기능을 설정하면 sourceLang을 꼭 지정을 해야한다.
            translateRequest.sourceLang.sourceCode,
            translateRequest.targetLang.targetCode,
            translationOptions
        ).text
        return text
    }

    fun createGlossary(createGlossaryRequest: CreateGlossaryRequest): CreateGlossaryResponse {
        val createGlossary = translator.createGlossary(
            createGlossaryRequest.glossaryName,
            createGlossaryRequest.sourceLang.sourceCode,
            createGlossaryRequest.targetLang.targetCode,
            GlossaryEntries(createGlossaryRequest.entries)
        )
        return CreateGlossaryResponse(
            glossaryId = createGlossary.glossaryId,
            ready = createGlossary.isReady,
            name = createGlossary.name,
            sourceLang = createGlossary.sourceLang,
            targetLang = createGlossary.targetLang,
            creationTime = createGlossary.creationTime,
            entryCount = createGlossary.entryCount
        )
    }

    fun getGlossary(glossaryId: String): GlossaryInfo {
        return translator.getGlossary(glossaryId)
    }
}

// 영어의 경우 번역시 sourceCode일때와 targetCode일때 코드가 다르다. 
// targetCode일때는 EN-US, EN-GB로 구분해서 써야한다.
enum class Lang(val sourceCode: String, val targetCode: String) {
    ENGLISH("EN", "EN-US"),
    KOREAN( "KO","KO"),
}

 

Glossary 적용 후, 테스트 결과

glossary 1
위의 glossaryId를 저장해두자.

 

`Hook : 훅`으로 저장한 후 다시 번역을 시도해보니, 성공적으로 `Hooks`가 `훅`으로 번역되었다.

성공!

 

그런데...

Glossary를 사용할 때는 한계가 있다. Glossary 기능을 이용하려면 `sourceLang`이 `null`일 수 없어, 언어 감지 기능을 사용할 수 없다. 
또한, `sourceLang`을 `ENGLISH`로 지정한 상태에서 번역을 진행하면, 아래와 같이 자연스럽지 않은 번역이 나올 수 있다.

그런데 말입니다

`text`가 영어, 일본어, 중국어, 프랑스어 등 다양한 언어로 무작위로 입력되는 환경에서, 그 언어에 맞게 `sourceLang`을 자동으로 변경하고 싶지만, 이를 자동화하기가 쉽지 않다. 결국 둘 중에 하나를 포기해야한다.

  1. glossary 기능을 포기
  2. `sourceLang`값 `null` (언어감지 기능)을 포기

glossary 기능을 포기하는 것이 좋을 것 같다.

 


REFERENCES

DeepL API 문서 - https://developers.deepl.com/docs/v/ko

반응형
저작자표시 동일조건 (새창열림)
'Spring' 카테고리의 다른 글
  • [Spring AI] Vector Store와 RAG를 이용한 할루시네이션 방지
  • [Spring AI] 챗봇 만들기 (Kotlin)
  • [Spring AI] 준비 (기본 개념, OpenAI API Key, 크레딧 충전)
  • [스프링 시큐리티] WebSecurityConfigurerAdapter deprecated 대응
SooJae
SooJae
코드는 효율적으로, 공부는 비효율적으로
    반응형
  • SooJae
    이수재 블로그
    SooJae
  • 전체
    오늘
    어제
    • 분류 전체보기 (60)
      • Spring (8)
      • Next.JS (4)
      • React (3)
      • Angular (1)
      • Language (6)
        • Java (1)
        • Kotlin (1)
        • Javascript (4)
      • Keycloak (5)
      • Knowledge (16)
        • Test (4)
        • Web (9)
        • Security (2)
        • Data Structure (1)
      • Infra (9)
        • Proxmox (2)
        • AWS (0)
        • Kubernetes (3)
      • Tools (1)
        • IntelliJ (1)
      • Algorithm (2)
      • Tistory (4)
      • ETC (1)
  • 블로그 메뉴

    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    스프링 번역
    test
    spring ai
    Auth
    스프링 ai
    ai
    Next.js
    React
    deepl api
    keycloak
    javascript
    GPT
    티스토리챌린지
    ChatGPT
    Functional Programming
    openAI
    Kotlin
    springboot
    웹 마스터 도구
    오블완
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
SooJae
[Spring] DeepL API를 이용한 번역 기능 추가하기
상단으로

티스토리툴바