IVS 챗 클라이언트 메시징 SDK: Kotlin 코루틴 자습서 1부: 채팅룸
본 문서는 두 파트로 구성된 자습서 중 첫 번째 파트에 해당하는 자습서입니다. Kotlin
모듈을 시작하기 전에 몇 분 정도 시간을 내어 사전 조건, 채팅 토큰의 주요 개념, 채팅룸 생성에 필요한 백엔드 서버를 숙지해 두세요.
이 자습서는 IVS 챗 메시징 SDK를 처음 사용하는 숙련된 Android 개발자를 위해 만들어졌습니다. Kotlin 프로그래밍 언어와 Android 플랫폼에서 UI를 만드는 데 익숙해야 합니다.
이 자습서의 첫 번째 부분은 여러 섹션으로 나뉩니다.
전체 SDK 설명서를 보려면 우선 Amazon IVS 챗 클라이언트 메시징 SDK(Amazon IVS 챗 사용 설명서에서 참조) 및 Chat Client Messaging: SDK for Android Reference
사전 조건
-
Kotlin과 Android 플랫폼에서 애플리케이션을 만드는 데 익숙해야 합니다. Android용 애플리케이션을 만드는 데 익숙하지 않은 경우 Android 개발자를 위한 첫 앱 빌드
가이드에서 기본 사항을 배워 보세요. -
Amazon IVS 챗 시작하기를 읽고 이해합니다.
-
기존 IAM 정책에 정의된
CreateChatToken
및CreateRoom
기능을 사용하여 AWS IAM 사용자를 생성합니다. (Amazon IVS 챗 시작하기를 참조하세요.) -
이 사용자의 비밀/액세스 키가 AWS 보안 인증 파일에 저장되어 있는지 확인합니다. 지침은 AWS CLI 사용 설명서(특히 구성 및 보안 인증 파일 설정)를 참조합니다.
-
채팅룸을 생성하고 ARN을 저장합니다. Amazon IVS 챗 시작하기를 참조하세요. (ARN을 저장하지 않은 경우 나중에 콘솔이나 Chat API를 사용하여 조회할 수 있습니다.)
로컬 인증/권한 부여 서버 설정
백엔드 서버는 채팅룸을 생성하고 IVS 챗 Android SDK가 채팅룸의 클라이언트를 인증하고 권한을 부여하는 데 필요한 채팅 토큰을 생성하는 일을 맡습니다.
Amazon IVS 채팅 시작하기에서 채팅 토큰 생성을 참조하세요. 플로우차트에서 볼 수 있듯이 서버 측 코드는 채팅 토큰 생성을 담당합니다 즉, 앱은 서버 측 애플리케이션에서 채팅 토큰을 요청하여 채팅 토큰을 생성하는 자체 수단을 제공해야 합니다.
저희는 Ktor
이제 AWS 보안 인증 정보가 올바르게 설정되었을 것입니다. 단계별 지침은 Set up AWS temporary credentials and AWS Region for development를 참조하세요.
chatterbox
라는 새 디렉터리를 생성하고 그 안에서 또 다른 디렉토리 auth-server
를 생성합니다.
서버 폴더는 다음과 같은 구조를 갖습니다.
- auth-server - src - main - kotlin - com - chatterbox - authserver - Application.kt - resources - application.conf - logback.xml - build.gradle.kts
참고: 여기에서 코드를 참조된 파일에 직접 복사하거나 붙여넣을 수 있습니다.
다음으로 인증 서버가 작동하는 데 필요한 모든 종속 항목과 플러그인을 추가합니다.
Kotlin 스크립트:
// ./auth-server/build.gradle.kts plugins { application kotlin("jvm") kotlin("plugin.serialization").version("1.7.10") } application { mainClass.set("io.ktor.server.netty.EngineMain") } dependencies { implementation("software.amazon.awssdk:ivschat:2.18.1") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20") implementation("io.ktor:ktor-server-core:2.1.3") implementation("io.ktor:ktor-server-netty:2.1.3") implementation("io.ktor:ktor-server-content-negotiation:2.1.3") implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.3") implementation("ch.qos.logback:logback-classic:1.4.4") }
이제 인증 서버의 로깅 기능을 설정해야 합니다. (자세한 정보는 로거 구성
XML:
// ./auth-server/src/main/resources/logback.xml <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="trace"> <appender-ref ref="STDOUT"/> </root> <logger name="org.eclipse.jetty" level="INFO"/> <logger name="io.netty" level="INFO"/> </configuration>
Ktorresources
디렉터리의 application.*
파일에서 자동으로 로드되는 구성 설정이 필요하므로 구성 설정도 추가합니다. (자세한 정보는 파일으로 구성
HOCON:
// ./auth-server/src/main/resources/application.conf ktor { deployment { port = 3000 } application { modules = [ com.chatterbox.authserver.ApplicationKt.main ] } }
마지막으로 서버를 구현해 보겠습니다.
Kotlin:
// ./auth-server/src/main/kotlin/com/chatterbox/authserver/Application.kt package com.chatterbox.authserver import io.ktor.http.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import software.amazon.awssdk.services.ivschat.IvschatClient import software.amazon.awssdk.services.ivschat.model.CreateChatTokenRequest @Serializable data class ChatTokenParams(var userId: String, var roomIdentifier: String) @Serializable data class ChatToken( val token: String, val sessionExpirationTime: String, val tokenExpirationTime: String, ) fun Application.main() { install(ContentNegotiation) { json(Json) } routing { post("/create_chat_token") { val callParameters = call.receive<ChatTokenParams>() val request = CreateChatTokenRequest.builder().roomIdentifier(callParameters.roomIdentifier) .userId(callParameters.userId).build() val token = IvschatClient.create() .createChatToken(request) call.respond( ChatToken( token.token(), token.sessionExpirationTime().toString(), token.tokenExpirationTime().toString() ) ) } } }
Chatterbox 프로젝트 생성
Android 프로젝트를 생성하려면 Android 스튜디오
공식 Android 프로젝트 생성 가이드
-
프로젝트 선택
에서 Chatterbox 앱을 위한 빈 활동 프로젝트 템플릿을 선택합니다.
-
프로젝트 구성
에서 다음 구성 필드 값을 선택합니다. -
이름: My App
-
패키지 이름: com.chatterbox.myapp
-
저장 위치: 이전 단계에서 만든
chatterbox
디렉터리를 지정합니다. -
언어: Kotlin
-
최소 API 레벨: API 21: Android 5.0(Lollipop)
-
모든 구성 매개 변수를 올바르게 지정한 후 chatterbox
폴더 내의 파일 구조는 다음과 같아야 합니다.
- app - build.gradle ... - gradle - .gitignore - build.gradle - gradle.properties - gradlew - gradlew.bat - local.properties - settings.gradle - auth-server - src - main - kotlin - com - chatterbox - authserver - Application.kt - resources - application.conf - logback.xml - build.gradle.kts
이제 작동하는 안드로이드 프로젝트가 있으므로 build.gradle
종속 항목에 com.amazonaws:ivs-chat-messaging
참고: 모든 코드 조각의 맨 위에는 프로젝트에서 변경해야 하는 파일의 경로가 있습니다. 경로는 프로젝트 루트의 상대 경로입니다.
Kotlin:
// ./app/build.gradle plugins { // ... } android { // ... } dependencies { implementation 'com.amazonaws:ivs-chat-messaging:1.1.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4' // ... }
새 종속 항목이 추가된 후 Android 스튜디오에서 Gradle 파일과 프로젝트 동기화를 실행하여 프로젝트를 새 종속 항목과 동기화합니다. (자세한 정보는 빌드 종속 항목 추가
이전 섹션에서 생성한 인증 서버를 프로젝트 루트에서 편리하게 실행하기 위해 이 서버를 settings.gradle
에 새 모듈로 포함시킵니다. (자세한 정보는 Gradle을 사용하여 소프트웨어 구성 요소 구조화 및 빌드
Kotlin 스크립트:
// ./settings.gradle // ... rootProject.name = "My App" include ':app' include ':auth-server'
이제부터 auth-server
가 Android 프로젝트에 포함되므로 프로젝트 루트에서 다음 명령으로 인증 서버를 실행할 수 있습니다.
쉘:
./gradlew :auth-server:run
채팅룸에 연결 및 연결 업데이트 관찰
채팅룸 연결을 열기 위해 활동이 처음 생성될 때 실행되는 onCreate() 활동 수명 주기 콜백region
및 tokenProvider
를 제공해야 합니다.
참고: 아래 조각의 fetchChatToken
함수는 다음 섹션에서 구현됩니다.
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... // AWS region of the room that was created in Getting Started with Amazon IVS Chat const val REGION = "us-west-2" class MainActivity : AppCompatActivity() { private var room: ChatRoom? = null // ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create room instance room = ChatRoom(REGION, ::fetchChatToken) } // ... }
채팅룸 연결의 변화를 표시하고 대응하는 것은 chatterbox
와 같은 채팅 앱을 만드는 데 필수적인 부분입니다. 룸과 상호작용을 시작하기 전에 채팅룸 연결 상태 이벤트를 구독하여 업데이트를 받아야 합니다.
코루틴용 챗 SDK에서 ChatRoom
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... const val TAG = "Chatterbox-MyApp" class MainActivity : AppCompatActivity() { // ... override fun onCreate(savedInstanceState: Bundle?) { // ... // Create room instance room = ChatRoom(REGION, ::fetchChatToken).apply { lifecycleScope.launch { stateChanges().collect { state -> Log.d(TAG, "state change to $state") } } lifecycleScope.launch { receivedMessages().collect { message -> Log.d(TAG, "messageReceived $message") } } lifecycleScope.launch { receivedEvents().collect { event -> Log.d(TAG, "eventReceived $event") } } lifecycleScope.launch { deletedMessages().collect { event -> Log.d(TAG, "messageDeleted $event") } } lifecycleScope.launch { disconnectedUsers().collect { event -> Log.d(TAG, "userDisconnected $event") } } } } }
이 다음으로 룸 연결 상태를 읽을 수 있는 기능을 제공해야 합니다. MainActivity.kt
속성ChatRoom
state
참조). 로컬 상태를 최신 상태로 유지하려면 state-updater 함수를 구현해야 합니다. 이 함수를 updateConnectionState
라고 해 보겠습니다.
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... class MainActivity : AppCompatActivity() { private var connectionState = ChatRoom.State.DISCONNECTED // ... private fun updateConnectionState(state: ChatRoom.State) { connectionState = state when (state) { ChatRoom.State.CONNECTED -> { Log.d(TAG, "room connected") } ChatRoom.State.DISCONNECTED -> { Log.d(TAG, "room disconnected") } ChatRoom.State.CONNECTING -> { Log.d(TAG, "room connecting") } } }
다음으로 state-updater 함수를 ChatRoom.Listener
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... class MainActivity : AppCompatActivity() { // ... override fun onCreate(savedInstanceState: Bundle?) { // ... // Create room instance room = ChatRoom(REGION, ::fetchChatToken).apply { lifecycleScope.launch { stateChanges().collect { state -> Log.d(TAG, "state change to $state") updateConnectionState(state) } } // ... } } }
이제 ChatRoom
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... class MainActivity : AppCompatActivity() { // ... private fun connect() { try { room?.connect() } catch (ex: Exception) { Log.e(TAG, "Error while calling connect()", ex) } } // ... }
토큰 공급자 구축
이제 애플리케이션에서 채팅 토큰을 생성하고 관리하는 함수를 만들 차례입니다. 이 예에서는 Android용 Retrofit HTTP 클라이언트
네트워크 트래픽을 보내려면 먼저 Android용 네트워크 보안 구성을 설정해야 합니다. (자세한 정보는 네트워크 보안 구성user-permission
태그와 networkSecurityConfig
속성에 유의하세요. 아래 코드에서 <version>
을 챗 Android SDK의 현재 버전 번호(예: 1.1.0)로 대체하세요.
XML:
// ./app/src/main/AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.chatterbox.myapp"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:fullBackupContent="@xml/backup_rules" android:label="@string/app_name" android:networkSecurityConfig="@xml/network_security_config" // ... // ./app/build.gradle dependencies { implementation("com.amazonaws:ivs-chat-messaging:<version>") // ... implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") }
로컬 IP 주소(예:10.0.2.2
및 localhost
도메인)를 신뢰할 수 있는 것으로 선언하여 백엔드와 메시지 교환을 시작합니다.
XML:
// ./app/src/main/res/xml/network_security_config.xml <?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">10.0.2.2</domain> <domain includeSubdomains="true">localhost</domain> </domain-config> </network-security-config>
다음으로 HTTP 응답 구문 분석을 위한 Gson 변환기 추가<version>
을 챗 Android SDK의 현재 버전 번호(예: 1.1.0)로 대체하세요.
Kotlin 스크립트:
// ./app/build.gradle dependencies { implementation("com.amazonaws:ivs-chat-messaging:<version>") // ... implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") }
채팅 토큰을 검색하려면 chatterbox
앱에서 POST HTTP 요청을 해야 합니다. Retrofit이 구현할 수 있도록 요청을 인터페이스로 정의합니다. (Retrofit 설명서
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/network/ApiService.kt package com.chatterbox.myapp.network import com.amazonaws.ivs.chat.messaging.ChatToken import retrofit2.Call import retrofit2.http.Body import retrofit2.http.POST data class CreateTokenParams(var userId: String, var roomIdentifier: String) interface ApiService { @POST("create_chat_token") fun createChatToken(@Body params: CreateTokenParams): Call<ChatToken> } // ./app/src/main/java/com/chatterbox/myapp/network/RetrofitFactory.kt package com.chatterbox.myapp.network import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory object RetrofitFactory { private const val BASE_URL = "http://10.0.2.2:3000" fun makeRetrofitService(): ApiService { return Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build().create(ApiService::class.java) } }
이제 네트워킹을 설정했으므로 채팅 토큰을 생성하고 관리하는 함수를 추가할 차례입니다. 프로젝트가 생성되었을 때 자동으로 생성된 MainActivity.kt
에 함수를 추가합니다.
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.launch import com.amazonaws.ivs.chat.messaging.* import com.amazonaws.ivs.chat.messaging.coroutines.* import com.chatterbox.myapp.network.CreateTokenParams import com.chatterbox.myapp.network.RetrofitFactory import retrofit2.Call import java.io.IOException import retrofit2.Callback import retrofit2.Response // custom tag for logging purposes const val TAG = "Chatterbox-MyApp" // any ID to be associated with auth token const val USER_ID = "test user id" // ID of the room the app wants to access. Must be an ARN. See Amazon Resource Names(ARNs) const val ROOM_ID = "arn:aws:..." // AWS region of the room that was created in Getting Started with Amazon IVS Chat const val REGION = "us-west-2" class MainActivity : AppCompatActivity() { private val service = RetrofitFactory.makeRetrofitService() private var userId: String = USER_ID // ... private fun fetchChatToken(callback: ChatTokenCallback) { val params = CreateTokenParams(userId, ROOM_ID) service.createChatToken(params).enqueue(object : Callback<ChatToken> { override fun onResponse(call: Call<ChatToken>, response: Response<ChatToken>) { val token = response.body() if (token == null) { Log.e(TAG, "Received empty token response") callback.onFailure(IOException("Empty token response")) return } Log.d(TAG, "Received token response $token") callback.onSuccess(token) } override fun onFailure(call: Call<ChatToken>, throwable: Throwable) { Log.e(TAG, "Failed to fetch token", throwable) callback.onFailure(throwable) } }) } }
다음 단계
이제 채팅룸 연결을 설정했으므로 이 Kotlin 코루틴 자습서의 2부인 메시지 및 이벤트로 이동하세요.