
CI를 돌리는데 사진과 같은 오류가 발생했다.CI에서는 Build, Test Job을 분리한 상태였는데, Test는 성공했지만 Build Job에서의 Test가 실패했다.로컬에서 빌드를 해봐도 Test는 제대로 돌아가는데, Build Job에서만 Test가 실패하는게 이상했다. 첨부한 사진 가장 상단에 testReleaseUnitTest라고 적혀있는 것을 보면, debug 모드가 아닌 release 모드로 빌드하고 있다는 것을 알 수 있다. - name: Build with Gradle run: ./gradlew buildCI 스크립트를 보니 이렇게 작성되어 있었다../gradlew build는 release 모드로 빌드를 한다. 반면에 ./gradlew assembleDebug는 ..
UnconfinedTestDispatcherfun main() { CoroutineScope(StandardTestDispatcher()).launch { print("A") delay(1) print("B") } CoroutineScope(UnconfinedTestDispatcher()).launch { print("C") delay(1) print("D") }}C테스트 디스패처는 StandardTestDispatcher 외에 UnconfinedTestDispatcher도 있다. StandardTestDispatcher는 스케줄러를 사용하기 전까지 어떤 연산도 수행하지 않는다.반면에 UnconfinedTes..

더보기class FetchUserUseCase( private val repo: UserDataRepository,) { suspend fun fetchUserData(): User = coroutineScope { val name = async { repo.getName() } val friends = async { repo.getFriends() } val profile = async { repo.getProfile() } User( name 三 name.await(), friends = friends.await(), profile = profile.await(), ) ..
class UserDownloader( private val api: NetworkService,) { private val users = mutableListOf() fun downloaded(): List = users.toList() suspend fun fetchUser(id: Int) { val newUser = api.fetchUser(id) users.add(newUser) }}시작하기 전에 위 코드를 살펴보자.이 클래스는 두 개 이상의 스레드가 동시에 사용할 경우에 대한 대비가 되어있지 않다.fetchUser()에서 users를 변경하고 있기 때문에, users는 공유 상태에 해당한다.따라서 users는 보호되어야 한다.두 개 이상의 스레..
이전 포스팅에서 코루틴 스코프를 적절하게 만드는 방법에 대해 배웠다.이번에는 스코프에 대해 배운 것들을 요약해 보고 일반적으로 사용하는 예시 상황에 대해 알아보자. CoroutineScope 팩토리 함수interface CoroutineScope { val coroutineContext: CoroutineContext}CoroutineScope는 coroutineContext를 유일한 프로퍼티로 가지고 있는 인터페이스이다. class SomeClass : CoroutineScope { override val coroutineContext: CoroutineContext = Job() fun onStart() { launch { // ... } ..

코루틴에서는 디스패처를 통해 코루틴이 실행되어야 할 스레드(또는 스레드 풀)를 결정한다.영어 사전에서 디스패처는 '사람이나 긴급 차량을 필요한 곳에 보내는 사람'이라 정의한다. 기본 디스패처디스패처를 설정하지 않으면 Dispatchers.Default가 기본적으로 설정된다.Dispatchers.Default는 프로그램이 실행되는 컴퓨터의 CPU 개수와 동일한 수(최소 두 개 이상)의 스레드 풀을 가지고 있다.이는 스레드를 효율적으로 사용한다고 가정했을 때, 이론적으로 가장 최적의 스레드 수다.따라서 Dispatchers.Default는 CPU 집약적인 연산을 수행하기에 적합하다. suspend fun main() = coroutineScope { repeat(1000) { launch..
여러 비동기 함수에서 데이터를 동시에 얻어야 하는 경우를 생각해 보자. 코루틴 스코프 함수가 소개되기 전에 사용한 방법들 suspend fun getUserProfile(): UserProfileData { val user = getUserData() // 1초 후 val notifications = getNotifications() // 1초 후 return UserProfileData( user = user, notifications = notifications, )}먼저 중단 함수에서 중단 함수를 호출하는 방법이 있다. 하지만 이런 방식은 작업이 동시에 진행되지 않는다.하나의 함수에서 데이터를 얻는 데 1초씩 걸리기 때문에 총 2초가 걸린다. susp..

코루틴은 잡히지 않은 예외가 발생했을 때 종료된다스레드도 동일한 경우에 종료되지만, 차이점이 있다.코루틴 빌더는 부모도 종료시키고, 종료된 부모는 자식들까지 모두 취소시킨다는 것이다. fun main(): Unit = runBlocking { launch { launch { delay(1000) throw Error("Some error") } launch { delay(2000) println("Will not be printed") } launch { delay(500) println("W..