[Jetpack Compose] 코루틴과 KTOR

mi-fasol·2023년 1월 17일
0

Compose

목록 보기
4/6

해당 게시물은 과거에 작성한 블로그 내용을 옮겨 온 것으로, 가독성이 떨어지고 내용이 부정확할 수 있습니다.

코루틴 (Coroutine)

Coroutine의 개념

  • Coroutine은 경량 스레드로 비유 가능
  • 스레드는 아니지만 비동기적인 프로그래밍이 가능
  • 비동기적으로 실행되는 코드를 간소화하기 위하여 사용 가능한 동시 실행 설계 패턴
  • 서로 협력하는 함수로, 여러 함수가 번갈아 가며 실행
  • 사용 전 dependencies에 코루틴 추가 필요
dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
}

Coroutine의 기능

  • 경량: suspend 기능을 지원하여 단일 스레드에서 많은 코루틴 실행 가능
  • 메모리 누수 감소: 구조화 된 동시 실행을 사용해 범위 내에서 작업 실행
  • 취소 지원: 실행 중인 코루틴의 계층 구조를 통하여 자동으로 캔슬 가능
  • Jetpack 동합: 대다수의 Jetpack 라이브러리에 코루틴을 완전히 지원하는 확장 프로그램 포함

Coroutine 실행 명령어

  • launch와 async 명령어를 통해 코루틴 실행
  • launch: 반환 값이 없는 명령어
    • launch 블록 안에 다시 launch를 써서 다른 코루틴 실행 가능
  • async: Deferred < T > 객체 반환
    • Deferred< T > 클래스: await() 메소드를 제공하여 작업 완료까지 대기 후 T 타입 객체를 반환
GlobalScope.launch{
 launch{
     Log.d(TAG, "Launch")
 }

 val value: Int = async{
     1 + 3
 }.await()

 Log.d(TAG, "Async - value: $value")
}
  • Global.launch: launch로 코루틴 실행
  • async{…}: async로 코루틴 실행
  • 1 + 3의 결과를 value에 삽입
  • .await: async의 코루틴 종료 시까지 대기 후 value return

Coroutine의 functions

  • suspend function: 코루틴의 실행을 잠시 정지 후 resume
    • 함수 생성 시 suspend를 적으면 사용 가능
private suspend fun example(){
    GlobalScope.launch{
        sleep(1000)
    Log.d(TAG, "suspend")
}
  • withContext(): 코루틴 실행을 다른 스레드로 이동
    • async와 동일한 기능
    • await()을 호출하지 않아도 된다는 차이점이 존재
class LoginRepository(...) {
    ...
    suspend fun makeLoginRequest(
        jsonBody: String
    ): Result<LoginResponse> {

        // 코루틴 실행을 IO 디스패처로 이동
  		// 해당 코루틴을 I/O 작업용으로 예약된 스레드에서 실행해야 함을 나타냄
        return withContext(Dispatchers.IO) {
            // Blocking network request code
        }
    }
}

Coroutine의 Dispatchers

  • Dispathcers.Main: 안드로이드 내의 메인 스레드
    • UI와 상호작용 및 빠른 작업 실행 가능
  • Dispatchers.IO: 기본 스레드 외부에서 디스크 또는 네트워크 I/O를 실행하도록 최적화된 디스패처
    • 파일 읽기, AAC의 Room 등
  • Dispatchers.Default: CPU를 많이 사용하는 작업을 기본 스레드 외부에서 실행하도록 최적화 된 디스패처
    • 목록을 정렬하거나 JSON 파싱 등

Coroutine Scope

  • Scope: 코루틴이 동작하는 범위
  • GlobalScope: 어플리케이션 종료 시까지 코루틴 실행 가능
    • 액티비티가 종료되어도 코루틴 작업이 끝날 때까지 코루틴이 동작
  • CoroutineScope: launch 또는 async를 사용하여 만든 코루틴을 추적
    • 동작 중인 코루틴을 scope.cancle()로 취소 가능
    • 안드로이드의 특정 KTX 라이브러리 중에는 특정 생명 주기 클래스에 viewModelScope나 lifecycleScope 등 자체 CoroutineScope를 제공

CoroutineContext

  • 일련의 요소를 사용해 코루틴의 동작 정의
  • Job: 코루틴의 생명 주기 제어
  • CoroutineDispatcher: 적절한 스레드로 작업을 전달
  • CoroutineName: 디버깅에 유용한 코루틴의 이름
  • CoroutineExceptionHandle: 예외 처리

. . . . . . . .

KTOR 통신

KTOR의 개념

  • 웹 어플리케이션, HTTP 서비스, 모바일 및 브라우저 어플리케이션 등의 연결된 앱을 쉽게 구축 가능한 프레임워크
  • KTOR를 사용하여 코틀린으로 비동기 클라이언트 및 서버 어플리케이션 작성을 가능하게 하는 코틀린 프레임워크
  • KTOR 사용 시 앱 수준의 gradle에 의존성 추가 필요
    - 필요한 의존성만 추가하는 것을 권장
dependencies{
  implementation "io.ktor:ktor-client-cio:1.6.3"
  implementation "io.ktor:ktor-client-core:1.6.3"
  implementation "io.ktor:ktor-client-android:1.6.3"
  implementation "io.ktor:ktor-client-serialization:1.6.3"
  implementation "io.ktor:ktor-client-logging:1.6.3"
  implementation "io.ktor:ktor-client-gson:1.6.3"
}

KTOR 적용 순서

  1. gradle에 의존성 추가
  2. request를 보내고 response를 받을 data class 정의
  3. HTTP 통신을 위한 클래스 추가
  4. 클래스 내에 HttpClient 객체 추가
class HttpRequestHelper {
	// CIO: HttpClientEngineFactory로, Coroutine based I/O
  private val client: HttpClient = HttpClient(CIO)
}
  1. 매니페스트에 INTERNET permission 추가
<uses-permission android:name="android.permission.INTERNET" />
  1. Http request 진행

HTTP 통신 방법

  • get(): 클라이언트에 get() 호출 시 바로 통신 결과 가져올 수 있음
withContext(Dispatchers.IO){
  val url = "https://cat-fact.herokuapp.com/facts/random"
  val response: HttpResponse = client.get(url)
}

Request, Response 제어

  • call.parameters[“paramName”]: 인덱스 접근자 함수
  • call.receive: 제네릭 변수를 사용해 request body를 코틀린 객체로 역직렬화
  • call.respond(): 코틀린 객체를 가져와서 해당 객체의 지정 형식으로 직렬화해서 http 응답 반환
  • call.respondText(): 텍스트를 응답으로 보낼 시의 respond를 구현한 함수
    • 문자열 응답 반환
profile
정위블

0개의 댓글