스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
Translation API 소개
새로운 Translation 프레임워크로 앱에서 여러 언어 간에 텍스트를 번역하는 방법을 확인해 보세요. 시스템 UI에서 번역문을 빠르게 표시하는 방법, 앱 UI에서 많은 분량의 텍스트를 번역하는 방법을 소개합니다.
챕터
- 0:00 - Introduction
- 2:10 - Simple overlay translation
- 4:01 - Flexible translation
- 11:34 - Language support
- 12:48 - Best practices
리소스
관련 비디오
WWDC23
-
다운로드
안녕하세요, Louie입니다 Machine Translation 팀 엔지니어죠 ‘Translation API 소개‘를 시작합니다 저는 여행하면서 종종 다양한 언어를 번역해야 합니다 번역 앱의 장점은 모든 언어를 말할 필요는 없다는 것입니다 Apple은 언어 장벽을 없애려고 노력합니다 사용자가 번역 기능을 지원하는 머신 러닝의 혜택을 누리도록요
이런 기능에 번역 앱이 포함되는데 이 앱에 텍스트를 입력해 다양한 언어로 번역할 수 있죠…
시스템 차원 번역에서는 시스템의 어느 앱에서든 번역 시트가 나타납니다
카메라 번역에서는 이미지와 주변 세계에 있는 텍스트를 번역할 수 있습니다 오늘 새로운 API를 소개하게 되어 기쁩니다 이런 기능과 번역 앱 뒤에서 머신 러닝 모델을 활용하는 API죠 *여러분의* 앱에서 이 강력한 기능을 사용할 수 있습니다
오늘 다룰 모든 번역 API는 iOS, iPadOS, macOS에서 지원됩니다 예시로 iPhone을 사용하지만 코드가 iPad와 Mac에서도 작동하죠
저는 하이킹 애호가라 유럽의 하이킹 검색 앱을 제작하고 있죠 앱에 하이킹 명소 설명이 있어서 사용자가 하이킹 명소를 리뷰할 수 있습니다 리뷰를 작성하는 언어가 다양하기 때문에 다른 사용자도 모든 걸 이해할 수 있게 하고 싶습니다 잘 모르는 언어로 작성된 리뷰까지도요 이건 사용자가 생성한 콘텐츠라서 현지화만으로는 충분하지 않습니다 이 앱에 번역 기능을 추가해 유용한 앱으로 만드는 것이 얼마나 쉬운지 보여드리려고 합니다 오늘 다룰 내용의 개요는 다음과 같습니다 먼저, 앱 내에서 번역을 제공하기 위해 사용하는 두 가지 옵션을 살펴보겠습니다 첫 번째는 번역 오버레이를 보여주는 아주 간단한 API이고 두 번째는 유연성이 더 큰 텍스트 번역 API입니다
다음으로 어떤 언어가 지원되는지와 프로그래밍 방식으로 이를 확인하는 방법을 살펴보겠습니다
끝으로 번역 기능 작업 시 모범 사례를 살펴보겠습니다 그럼 시작하겠습니다!
.translationPresentation()으로 앱에 번역을 쉽게 추가할 수 있죠 SwiftUI 한 줄만 사용하면 사용자의 언어로 번역된 텍스트를 표시합니다 번역할 텍스트를 제공한 다음 번역 기능을 트리거하기만 하면 됩니다
이 API는 최근에 제공되어서 벌써 프로덕션 앱에 적용할 수 있습니다
자, 사용자가 다른 언어로 작성된 리뷰를 보게 되면…
…번역을 보여주는 시스템 UI를 쉽게 불러올 수 있습니다
이 기능을 앱에 추가하는 것이 얼마나 쉬운지 보여드리겠습니다 먼저, 번역문 표시 여부를 제어하는 저장공간을 추가합니다
다음, 번역 기능을 트리거하는 버튼을 빠른 메뉴에 추가합니다 버튼을 누르면 showsTranslation이 true로 설정되죠
마지막으로 .translationPresentation()을 추가해서
showsTranslation이 true일 때 표시하도록 명령하고 ...번역할 리뷰 텍스트를 제출합니다 끝났습니다!
자, 리뷰를 이해할 수 없을 때 버튼 하나만 누르면 번역문이 표시됩니다
원하면 도착어를 변경하는 옵션도 있습니다
여기서 표시되는 것은 iOS의 다른 곳에서 사용 가능한 시스템 차원 번역 기능과 같지만 텍스트 선택이 아니라 앱에 의해 트리거됩니다 정말 추가하기 쉽고 이것만으로 충분한 앱도 있죠 하지만 한 번에 번역문 하나만 표시하면 적합하지 않은 경우도 있습니다 예컨대 사용자가 번역된 댓글을 동시에 여러 개 볼 수 있게 하려면 어떻게 해야 할까요? 저는 각 리뷰에 번역문을 인라인으로 표시하고 싶습니다 이런 경우 때문에 저희는 유연한 번역 API를 만들었습니다 이 API에 관해 설명하겠습니다 유연한 번역 API의 핵심에는 TranslationSession 클래스가 있죠 TranslationSession을 사용해 한 번에 여러 문자열을 번역하고 Swift 비동기 구문을 사용해 결과를 돌려줄 수 있습니다
결과를 UI에 어떻게 표시할지는 여러분에게 달려 있습니다
직접 TranslationSession 인스턴스를 만들지 않습니다 가끔 이 클래스로 사용자에게 UI를 표시해야 하기 때문이죠 그 대신에 .translationTask를 보기에 첨부하면 클로저를 호출해 사용할 TranslationSession을 제공합니다 이 예시에서는 보기가 나타날 때 클로저가 한 번 실행됩니다
하지만 번역이 실행될 때 대부분 더 많은 제어권을 원합니다 TranslationSession.Configuration이 이때 필요합니다
이제 이 클로저는 구성이 변경될 때마다 실행됩니다 초기에 번역을 트리거하려면 nil이 아닌 값으로 구성합니다 번역을 다시 트리거해야 하면 구성을 변경해야 합니다 클로저를 다시 실행한다는 걸 SwiftUI가 알 수 있도록 말이죠 출발어나 도착어를 변경해서 그렇게 할 수 있습니다 또는 구성에서 .invalidate()를 호출할 수 있습니다 새 텍스트를 번역하고 싶다면 말이죠 앱에 이 유연한 API를 적용하는 것이 얼마나 쉬운지 봅시다 TranslationSession.Configuration 저장 공간을 추가합니다 nil로 시작합니다 사용자가 트리거할 때까지 번역 기능이 기다리도록 말입니다
다음, 이 구성을 사용하는 .translationTask()를 추가합니다
구성이 변경되고 nil이 아닐 때마다 호출되어 번역에 사용할 세션을 제공합니다
저는 번역 기능을 수행하겠습니다
이 세션에 한 묶음의 텍스트 번역을 요청합니다
여기 아래에서 이미 구현한 함수를 사용하고 있는데
필터링된 모든 리뷰를 번역하라고 요청하는 거죠 결과는 한 번에 하나씩 비동기식으로 반환됩니다
각 결과가 반환될 때마다 이미 구현한 함수를 호출해 번역 응답을 받고
응답을 모델 객체에 추가하고 UI를 업데이트합니다
이제 번역 기능을 트리거해야 합니다 리뷰를 한 언어씩 보기 위해 필터링 시스템을 추가했습니다 언어를 선택하면 필터링된 리뷰를 번역하는 버튼이 있지만 구현을 마치지 않았으니 끝마쳐 보겠습니다
먼저, 구성이 이미 있는지 확인합니다 없으면 아직 번역하지 않았으니 구성을 생성하겠습니다
여기서 기본 이니셜라이저를 사용하고 있는데 자동으로 언어를 선택할 겁니다 어떤 언어를 사용할지 제어하는 방법을 자세히 설명하겠습니다
구성이 이미 있으면 벌써 번역했다는 뜻이지만 사용자가 다시 번역을 원합니다 SwiftUI는 소스 콘텐츠 변경을 알 수 없지만 .invalidate()를 호출하면 구성이 변경되고 .translationTask 클로저 실행으로 새 콘텐츠를 번역할 수 있죠 다 됐습니다! 앱에서 작동하는 것을 보겠습니다
자, 일본어 리뷰를 필터링하면 버튼 누르기 한 번만으로
번역이 끝났을 때 리뷰에 추가되어 리뷰를 각각 번역하지 않아도 한 번에 모두 읽을 수 있습니다
멋지지만 꽤 힘든 하이킹이라고들 말하고 있는 것 같네요 전 그날은 장거리 하이킹을 할 시간이 없을 것 같아 다른 코스를 찾아보겠습니다
‘Tulips and Windmill Walk‘가 제가 찾고 있는 것에 더 가까운 것 같은데 사람들의 의견이 궁금하네요
대부분 네덜란드어로 된 리뷰같으니 번역해 보겠습니다
하지만 지금은 네덜란드어 콘텐츠를 번역할 때 언어를 다운로드하라는 메시지가 나타나네요 어떻게 된 건지 설명하겠습니다
TranslationSession은 온디바이스 ML 모델을 사용해 번역합니다
이 모델은 번역 앱을 비롯해 시스템의 모든 앱에서 공유됩니다 언어가 이미 다운로드되었으면 앱에서 사용할 수 있습니다
API가 세부 사항을 처리합니다 언어가 아직 설치되지 않았으면 앱이 번역할 때 프레임워크에서 다운로드 권한을 요청합니다 또한 다운로드 중에 사용자에게 진행 상황을 보여줍니다 다운로드는 백그라운드에서 계속 진행됩니다 사용자가 이 시트를 닫거나 앱에서 완전히 나가는 경우에도 말이죠 다음, 언어를 선택하는 방법을 설명하겠습니다 사용할 출발어와 도착어를 지정할 수 있습니다 또는 앞에서 제가 한 것처럼 자동으로 선택하게 할 수 있습니다
.translationTask에 직접 언어를 지정하거나 TranslationSession.Configuration에 지정합니다
출발어에 nil을 사용하면 콘텐츠 언어를 자동으로 식별하려고 시도합니다 언어를 판단하지 못하면 선택하라는 메시지가 표시됩니다 도착어에 nil을 사용하면 적절한 도착어가 선택됩니다 출발어로 무엇이 사용되든 사용자의 기본 언어에 따라 도착어를 선택하는 거죠
Locale과 Locale.Language는 여러 가지 형태일 수 있다는 걸 유의해야 하는데, 솔직히 좀 헷갈릴 수 있습니다 알고 있어야 하는 조합과 변형이 많기 때문이죠 예를 들어 언어를 반환하는 API에 따라 표준 언어일 수도 있고 변형어, 지역 방언 또는 겉보기에는 관련이 없어 보이는 지역 방언일 수도 있습니다 예를 들면 일본에 사는 프랑스어 사용자가 있죠
최상의 결과를 얻으려면 LanguageAvailability.supportedLanguages API가 반환한 언어를 사용해야 합니다
콘텐츠가 어떤 언어인지 아는 방법이 궁금할 겁니다 가능하면 TranslationSession에 출발어를 nil로 지정해 언어를 자동으로 식별하는 것이 좋습니다 하지만 여러분이 텍스트 언어를 식별해야 하는 경우 NLLanguageRecognizer를 사용할 수 있습니다 processString 함수를 호출하고 dominantLanguage를 가져온 다음 TranslationSession에서 사용하는 Locale.Language로 변환합니다
한 번에 여러 문자열을 번역하는 기능이 필요한 앱이 많습니다 앞에서 다양한 사용자 리뷰를 번역했을 때와 같은 경우죠 또는 앱이 문서나 이미지에 있는 다양한 문자열을 번역해야 할 수도 있습니다
같은 언어로 된 여러 문자열을 번역할 때는 단일 문자열 번역 함수보다는 묶음 번역 함수 중 하나를 사용하는 것이 가장 좋고 효율적입니다
두 가지 옵션이 있습니다 전자는 모든 준비가 된 후에 결과를 모두 한꺼번에 원래 순서대로 반환합니다 순서가 항상 같고 각 응답에 대해 수행할 작업을 알기 쉬워서 더 간단하고 사용하기 쉬운 옵션입니다 번역을 마칠 때까지 기다렸다가 모든 번역을 표시하려는 경우에도 사용하기에 가장 좋습니다
후자의 함수는 결과가 제공되는 대로 스트리밍합니다 AsyncSequence처럼 말이죠 UI 응답 속도가 더 빠르다는 느낌을 주기 때문에 좋습니다 첫 번째 결과가 더 빠르게 도착하고 사용자가 결과를 UI에 즉시 반영할 수 있기 때문이죠 결과를 스트리밍하는 이 함수를 사용할 때 각 요청에서 clientIdentifier를 설정하고자 합니다 각 응답을 받을 때 이런 식으로 결과를 구별할 수 있습니다 자세한 내용은 설명서를 참조하세요
다음, 언어 지원에 관해 설명하겠습니다 오늘 설명한 API는 여기 있는 모든 언어를 지원합니다 번역 앱에서 지원하는 언어와 동일하죠
올해 새로 힌디어 지원이 추가되었습니다 따라서 훨씬 더 많은 사용자가 번역 기능을 활용할 수 있습니다 번역 앱과 이제는 여러분의 앱에서도 말이죠
새로운 LanguageAvailability 클래스를 사용해 번역 기능에서 지원되는 언어를 확인할 수 있습니다 지원되는 언어가 더 많아지면 이 목록은 업데이트될 수 있습니다
지원되는 출발어와 도착어 쌍도 확인할 수 있습니다 프레임워크에서 모든 언어 조합을 지원하지는 않습니다
예를 들어 미국 영어와 영국 영어가 힌디어로 번역되는지 확인하면 이 쌍은 지원된다고 표시됩니다 두 언어가 이미 다운로드되었다면 설치되어 있다고 표시됩니다
반면에 영어 변형들 간에 또는 어떤 언어를 같은 언어로 번역할 수 있는지 확인해 보면 항상 이 언어 쌍은 지원되지 않는다고 표시됩니다 지원되지 않는 언어 쌍으로 TranslationSession을 만들 수는 있겠지만 번역을 시도할 때마다 오류가 반환될 것입니다 출발어 대신 소스 텍스트 스니펫으로 상태를 확인하는 함수도 있습니다
번역 기능 작업 시 모범 사례 몇 가지를 살펴보겠습니다 먼저 iPhone, iPad 또는 Mac에서 개발해야 합니다 이런 번역 API들은 시뮬레이터에서 작동하지 않습니다
.translationPresentation과 .translationTask 한정자를 모두 콘텐츠 자체에 첨부해야 합니다 .translationPresentation()은 iPad와 Mac에서 팝오버라 올바른 보기를 가리키도록 해야 합니다 이 코드는 팝오버가 버튼 자체를 가리키도록 해서 원래 보기를 가립니다
대신 한정자를 콘텐츠나 해당 컨테이너에 첨부합니다 이제 팝오버가 번역될 콘텐츠를 정확히 가리키고 콘텐츠를 가리지 않습니다
여러 언어로 된 콘텐츠를 번역할 때는 각별한 주의를 기울여야 합니다
요청 묶음의 소스 텍스트가 모두 같은 언어여야 합니다 같은 묶음에 다른 언어를 섞으면 조악한 결과를 얻게 됩니다 독일어와 스페인어 텍스트를 같은 요청 묶음에 포함하면 터무니없는 결과를 얻을 겁니다
그 대신에 각 언어를 번역하는 호출을 별도로 작성해야 합니다 여기처럼 같은 세션에 별도의 묶음으로 말이죠
코드 작성 시 단일 요청에 여러 언어의 콘텐츠를 포함하면 안 된다는 뜻입니다 여기 독일어와 스페인어 텍스트가 같은 요청 어레이에 있습니다
대신에 단일 세션에서 각 언어에 대해 함수 호출을 별도로 해야 합니다 독일어 텍스트를 번역한 후 스페인어 텍스트를 번역합니다 이렇게 할 때 중요한 점은 세션의 출발어가 nil이어야 합니다 이 세션에서 먼저 각 묶음의 언어를 식별하기 위해서죠
또한 지원되는 언어만 지정해야 합니다 그렇지 않으면 이 세션의 모든 번역에서 오류가 발생합니다
콘텐츠가 어떤 언어인지 또는 어떤 언어로 번역할 것인지 확실하지 않으면 nil을 사용해 프레임워크에서 언어를 선택하도록 합니다 사용자에게 어떤 언어가 필요한지 미리 안다면 번역하기 전에 TranslationSession.prepareTranslation()으로 다운로드 승인을 요청할 수 있습니다
이는 사용자가 오프라인 상태에서 번역 기능을 사용하려는 경우 미리 다운로드를 시작하도록 할 때 유용합니다 앱에서 시간이 흐르면서 변경되는 콘텐츠를 번역해야 하는 경우 이 API를 사용해 미리 다운로드 승인을 받으면 화면을 가리지 않습니다
TranslationSession 인스턴스를 저장하는 방법에 주의하세요 TranslationSession은 내부에서 많은 작업을 수행하지만 이렇게 하려면 가끔 사용자에게 UI를 표시해야 합니다 앱에서 보기에 고정되어 있어야 이것이 가능합니다 TranslationSession 인스턴스는 각각 고정된 보기에 연결되어서 바탕이 되는 보기가 사라지면 작동하지 않습니다
보기의 수명이 끝난 인스턴스를 예를 들면 영구적 모델 객체에 저장해서는 안 된다는 뜻입니다 나중에 세션을 사용하지 못할 수 있기 때문이죠
마지막으로, 이제 번역에 새로운 SF Symbol를 사용할 수 있습니다 번역 API를 트리거하거나 오늘 설명한 번역 기능을 참조하는 UI의 어느 곳에서든 이것을 사용할 수 있습니다
요약하자면 앱의 시스템 UI에 번역문을 표시하는 방법으로 `.translationPresentation()`을 사용해야 합니다 유연한 번역 API도 있는데 앱의 UI 내에 더 심도 있는 통합을 원하면 사용할 수 있습니다
저희는 피드백 지원을 통한 여러분의 피드백을 환영합니다 문제가 발생하거나 제안하고 싶은 개선 사항이 있으면 저희에게 알려 주세요 앱에 번역 기능을 사용해 사용자층을 넓혀 보세요 감사합니다!
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.