본문 바로가기
Project example/번역 앱

[2. API 호출, 모듈] RxJava+MVVM+Hilt+Papago API를 이용한 번역 앱 만들기 (feat.Kotlin)

by 안솝우화 2022. 4. 14.
반응형

저번 시간에 이어서 글을 작성하도록 하겠습니다, 안 보신 분은 아래 이전 글을 확인해 주세요

2022.04.14 - [Project example/번역 앱] - [1. 화면, 종속성] RxJava+MVVM+Hilt+Papago API를 이용한 번역 앱 만들기 (feat.Kotlin)

 

[1. 화면, 종속성] RxJava+MVVM+Hilt+Papago API를 이용한 번역 앱 만들기 (feat.Kotlin)

안녕하세요 이번 주제는 바로 RxJava로 비동기 처리를 하여 Papago API를 호출하는 번역 앱을 만들기입니다 그럼 바로 시작하겠습니다! 우선 종속성부터 추가하겠습니다 Gradle Project 단위 buildscript { r

asuhdevstory.tistory.com

 

전체 코드는 이곳에서 확인할 수 있습니다

https://github.com/ParkSangSun1/RxAppExample

 

GitHub - ParkSangSun1/RxAppExample: RxJava + Papago API + MVVM + Hilt

RxJava + Papago API + MVVM + Hilt. Contribute to ParkSangSun1/RxAppExample development by creating an account on GitHub.

github.com

 

이 예제에서는 파파고 api를 사용해 번역을 하기 때문에 아래 사이트에 들어가서 key 등을 발급받아야 합니다

https://developers.naver.com/main/

 

NAVER Developers

네이버 오픈 API들을 활용해 개발자들이 다양한 애플리케이션을 개발할 수 있도록 API 가이드와 SDK를 제공합니다. 제공중인 오픈 API에는 네이버 로그인, 검색, 단축URL, 캡차를 비롯 기계번역, 음

developers.naver.com

애플리케이션을 만들고 해당하는 id 등을 발급받았다면 이어서 진행해 보겠습니다

우선 API를 호출하기 전에 Response(받아올 값)를 받기 위한 data class를 만들어 줍니다

data class PapagoTranslationResponse(
    val message: Message
)
data class Message(
    val result: Result
)
data class Result(
    val translatedText: String
)

response data class는 총 3개입니다

그리고 request를 보낼 때 Body에 담을 정보를 담는 data class를 만들어 줍니다

data class TranslationDataDelivery(
    val text : String,
    val languageState : Boolean
)

 

 이제 api 호출을 위한 인터페이스를 만들어 줍니다

interface PapagoApi {
    @POST("/v1/papago/n2mt")
    fun papagoTranslationService(
        @Header("X-Naver-Client-Id") X_Naver_Client_Id : String,
        @Header("X-Naver-Client-Secret") X_Naver_Client_Secret : String,
        @Body papagoTranslationRequest : PapagoTranslationRequest
    ) : Single<PapagoTranslationResponse>
}

 

실제로 사용해보기 전에 di 모듈을 만들어 줍니다

@HiltAndroidApp
class App : Application() {
    private var instance: App? = null

    override fun onCreate() {
        super.onCreate()
        instance = this
    }
}

 

manifest에 name으로 app을 추가해 주고 internet 퍼미션을 허용해 줍니다

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.pss.rx_app_example">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        //추가
        android:name="com.pss.rx_app_example.di.App"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Quick_Setup">
        <activity
            android:name="com.pss.rx_app_example.view.MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

그리고 Network 모듈을 만들어 줍니다

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    @Singleton
    fun provideHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .readTimeout(10, TimeUnit.SECONDS)
            .connectTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .addInterceptor(getLoggingInterceptor())
            .build()
    }

    @Singleton
    @Provides
    fun provideRetrofitInstance(
        okHttpClient: OkHttpClient,
        gsonConverterFactory: GsonConverterFactory
    ): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .client(provideHttpClient())
            .addConverterFactory(gsonConverterFactory)
            .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
            .build()
    }

    @Provides
    @Singleton
    fun provideConverterFactory(): GsonConverterFactory {
        return GsonConverterFactory.create()
    }


    private fun getLoggingInterceptor(): HttpLoggingInterceptor =
        HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }

    @Provides
    @Singleton
    fun providePapagoTranslationService(retrofit: Retrofit): PapagoApi {
        return retrofit.create(PapagoApi::class.java)
    }
}

 

이제 정말로 실제로 API 호출을 사용해볼 차례입니다!

class MainDataSource @Inject constructor(
    private val papagoApi: PapagoApi
) {
    fun getPapagoTranslationText(text : String, source : String, target : String) = papagoApi.papagoTranslationService(Utils.X_NAVER_CLIENT_ID, Utils.X_NAVER_CLIENT_SECRET, PapagoTranslationRequest(source = source, target = target, text = text))
}
class MainRepository @Inject constructor(
    private val mainDataSource: MainDataSource
){
    fun getPapagoTranslationText(text : String, source : String, target : String) = mainDataSource.getPapagoTranslationText(text = text, source = source, target = target)
}
@HiltViewModel
class MainViewModel @Inject constructor(
    private val mainRepository: MainRepository
) : ViewModel() {
    //true : 영어 -> 한국어 (기본), false : 한국어 -> 영어
    var language = true


    fun getPapagoTranslationText(text : String, source : String, target : String) = mainRepository.getPapagoTranslationText(text = text, source = source, target = target)
}

 

다음 글에서 실제 observable을 받아 구독하고 화면에서 보여주는 방법에 대해 알아보겠습니다

반응형