{"id":151612,"date":"2021-06-07T16:44:09","date_gmt":"2021-06-07T15:44:09","guid":{"rendered":"https:\/\/blog.jetbrains.com\/kotlin\/2021\/05\/kotlin-coroutines-1-5-0-released\/"},"modified":"2021-06-07T17:10:34","modified_gmt":"2021-06-07T16:10:34","slug":"kotlin-coroutines-1-5-0-released","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/ko\/kotlin\/2021\/06\/kotlin-coroutines-1-5-0-released\/","title":{"rendered":"Kotlin Coroutines 1.5: \uc12c\uc138\ud558\uace0 \uac1c\uc120\ub41c \ucc44\ub110 API\ub85c \ud45c\uc2dc\ub418\ub294 GlobalScope\uc744 \ube44\ub86f\ud55c \ub9ce\uc740 \uac1c\uc120 \uc0ac\ud56d"},"content":{"rendered":"<p><em>\uacf5\ub3d9 \uc791\uc131\uc790: <a href=\"https:\/\/blog.jetbrains.com\/author\/svetlana-isakova\/\" class=\"ek-link\">Svetlana Isakova<\/a><\/em><\/p>\n<p>Kotlin Coroutines 1.5.0\uc774 \ucd9c\uc2dc\ub418\uc5c8\uc2b5\ub2c8\ub2e4! \uc0c8 \ubc84\uc804\uc5d0 \ud3ec\ud568\ub41c \uae30\ub2a5\uc744 \uc544\ub798\uc5d0\uc11c \uc0b4\ud3b4\ubcf4\uc138\uc694.<\/p>\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/05\/kotlin-coroutines-1-5-0-released\/#globalscope\" class=\"ek-link\">GlobalScope\ub294 \uc774\uc81c \uc12c\uc138\ud55c API\ub85c \ud45c\uc2dc\ub429\ub2c8\ub2e4.<\/a> GlobalScope\ub294 \uc624\uc6a9\ud558\uae30 \uc26c\uc6b4 \uace0\uae09 API\uc785\ub2c8\ub2e4. \ucef4\ud30c\uc77c\ub7ec\uac00 \uc774\uc81c \uc624\uc6a9 \uac00\ub2a5\uc131\uc5d0 \ub300\ud574 \uacbd\uace0\ud558\uace0 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc774 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc635\ud2b8\uc778\uc744 \uc694\uad6c\ud569\ub2c8\ub2e4.<\/li>\n<\/ul>\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/05\/kotlin-coroutines-1-5-0-released\/#junit\" class=\"ek-link\">JUnit \ud655\uc7a5 \uae30\ub2a5<\/a>. \uc774\uc81c JUnit 5\uc5d0\uc11c CoroutinesTimeout\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ul>\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/05\/kotlin-coroutines-1-5-0-released\/#channels\" class=\"ek-link\">\uac1c\uc120\ub41c \ucc44\ub110 API.<\/a> \ub77c\uc774\ube0c\ub7ec\ub9ac \ud568\uc218\uc5d0 \ub300\ud55c \uc0c8\ub85c\uc6b4 \uba85\uba85 \uccb4\uacc4\uc640 \ud568\uaed8 <code>offer<\/code> \ubc0f <code>poll<\/code>\uc5d0 \ub300\ud55c \ub354 \ub098\uc740 \ub300\uc548\uc73c\ub85c \ube44\uc911\ub2e8 \ud568\uc218 <code>trySend<\/code> \ubc0f <code>tryReceive<\/code>\uac00 \ub3c4\uc785\ub418\uc5c8\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ul>\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/05\/kotlin-coroutines-1-5-0-released\/#reactive\" class=\"ek-link\">\ubc18\uc751\ud615 \ub77c\uc774\ube0c\ub7ec\ub9ac \ud1b5\ud569\uc758 \uc548\uc815\ud654.<\/a> Reactive Streams \uc720\ud615\uc5d0\uc11c Kotlin Flow\ub85c \ubcc0\ud658\ud558\uae30 \uc704\ud55c \ub354 \ub9ce\uc740 \ud568\uc218\ub97c \ucd94\uac00\ud558\uace0 \uae30\uc874\uc758 \ub9ce\uc740 \ud568\uc218\uc640 ReactiveContext API\ub97c \uc548\uc815\ud654\ud588\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ul>\n<p>\uc774 \ube14\ub85c\uadf8 \uac8c\uc2dc\ubb3c\uc5d0\uc11c\ub294 \uc0c8 \ubc84\uc804\uc73c\ub85c \ub9c8\uc774\uadf8\ub808\uc774\uc158\ud558\uae30 \uc704\ud55c \uad8c\uc7a5 \uc0ac\ud56d\ub3c4 \uc18c\uac1c\ud569\ub2c8\ub2e4.<\/p>\n<p><span id=\"more-142622\"><\/span><\/p>\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\">\n<div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Kotlin Coroutines 1.5: \uc12c\uc138\ud558\uace0 \uc815\uc81c\ub41c \ucc44\ub110 API \ub4f1\uc73c\ub85c \ud45c\uc2dc\ub41c GlobalScope\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/EVLnWOcR0is?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen=\"\"><\/iframe><\/div>\n<\/figure>\n<p align=\"center\"><a class=\"ek-link jb-download-button\" title=\"Coroutines 1.5.0 \uc0ac\uc6a9\" href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/05\/kotlin-coroutines-1-5-0-released\/#use-coroutines-1-5-0\">Coroutines 1.5.0 \uc0ac\uc6a9 \uc2dc\uc791\ud558\uae30<\/a><\/p>\n<h1 id=\"globalscope\">\uc12c\uc138\ud55c API\ub85c \ud45c\uc2dc\ub418\ub294 GlobalScope<\/h1>\n<p><code>GlobalScope<\/code> \ud074\ub798\uc2a4\ub294 \uc774\uc81c <code>@DelicateCoroutinesApi<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc73c\ub85c \ud45c\uc2dc\ub429\ub2c8\ub2e4. \uc774\uc81c\ubd80\ud130 <code>GlobalScope<\/code>\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 <code>@OptIn(DelicateCoroutinesApi::class)<\/code>\ub97c \uc774\uc6a9\ud55c \uba85\uc2dc\uc801 \uc635\ud2b8\uc778\uc774 \ud544\uc694\ud569\ub2c8\ub2e4.<\/p>\n<p><code>GlobalScope<\/code>\uc758 \uc0ac\uc6a9\uc740 \ub300\ubd80\ubd84\uc758 \uacbd\uc6b0 \uad8c\uc7a5\ub418\uc9c0 \uc54a\uc9c0\ub9cc <a href=\"https:\/\/kotlinlang.org\/docs\/coroutines-basics.html#your-first-coroutine\" target=\"_blank\" rel=\"noopener\">\uacf5\uc2dd \ubb38\uc11c<\/a>\ub294 \uc5ec\uc804\ud788 \uc774 \uc12c\uc138\ud55c API\ub97c \ud1b5\ud574 \uac1c\ub150\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4.<\/p>\n<p>\uc804\uc5ed <code>CoroutineScope<\/code>\ub294 \uc7a1(job)\uc5d0 \ubc14\uc778\ub529\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc804\uc5ed \ubc94\uc704\ub294 \uc804\uccb4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc218\uba85 \uae30\uac04 \ub3d9\uc548 \uc791\ub3d9\ud558\uace0 \uc870\uae30\uc5d0 \ucde8\uc18c\ub418\uc9c0 \uc54a\ub294 \ucd5c\uc0c1\uc704 \ucf54\ub8e8\ud2f4\uc744 \uc2dc\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9\ub429\ub2c8\ub2e4. <code>GlobalScope<\/code>\uc5d0\uc11c \uc2dc\uc791\ub41c \ud65c\uc131\ud654\ub41c \ucf54\ub8e8\ud2f4\uc740 \ud504\ub85c\uc138\uc2a4 \uc911\uc9c0\ub97c \ub9c9\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \ub370\ubaac \uc2a4\ub808\ub4dc\uc640 \ube44\uc2b7\ud569\ub2c8\ub2e4.<\/p>\n<p>\uc774\uac83\uc740 \uc12c\uc138\ud55c API\uc774\uba70 <code>GlobalScope<\/code>\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc2e4\uc218\ub85c \ub9ac\uc18c\uc2a4 \ub610\ub294 \uba54\ubaa8\ub9ac \ub204\uc218\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uae30 \uc27d\uc2b5\ub2c8\ub2e4. <code>GlobalScope<\/code>\uc5d0\uc11c \uc2dc\uc791\ub41c \ucf54\ub8e8\ud2f4\uc740 \uad6c\uc870\ud654\ub41c \ub3d9\uc2dc\uc131 \uc6d0\uce59\uc758 \uc801\uc6a9\uc744 \ubc1b\uc9c0 \uc54a\uc73c\ubbc0\ub85c \ubb38\uc81c(\uc608: \ub290\ub9b0 \ub124\ud2b8\uc6cc\ud06c\ub85c \uc778\ud574)\uac00 \ubc1c\uc0dd\ud558\uc5ec \uc911\ub2e8\ub418\uac70\ub098 \uc9c0\uc5f0\ub418\ub294 \uacbd\uc6b0, \uc791\ub3d9\uc744 \uba48\ucd94\uc9c0 \uc54a\uace0 \ub9ac\uc18c\uc2a4\ub97c \uc18c\ube44\ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \ub2e4\uc74c \ucf54\ub4dc\ub97c \uc0dd\uac01\ud574 \ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">fun loadConfiguration() {\n    GlobalScope.launch {\n        val config = fetchConfigFromServer() \/\/ network request\n        updateConfiguration(config)\n    }\n}\n<\/pre>\n<p><code>loadConfiguration<\/code>\uc744 \ud638\ucd9c\ud558\uba74 <code>GlobalScope<\/code>\uc5d0 \ucf54\ub8e8\ud2f4\uc774 \uc0dd\uc131\ub418\uc5b4 \ucde8\uc18c\ud558\uac70\ub098 \uc644\ub8cc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\uae30 \uc704\ud55c \uc5b4\ub5a4 \ud504\ub85c\ube44\uc804\ub3c4 \uc5c6\uc774 \ubc31\uadf8\ub77c\uc6b4\ub4dc\uc5d0\uc11c \uc791\ub3d9\ud569\ub2c8\ub2e4. \ub124\ud2b8\uc6cc\ud06c\uac00 \ub290\ub9ac\uba74 \ucf54\ub8e8\ud2f4\uc774 \ubc31\uadf8\ub77c\uc6b4\ub4dc\uc5d0\uc11c \uacc4\uc18d \ub300\uae30\ud558\uba74\uc11c \ub9ac\uc18c\uc2a4\ub97c \uc18c\ube44\ud569\ub2c8\ub2e4. <code>loadConfiguration<\/code>\uc5d0 \ubc18\ubcf5\uc801\uc73c\ub85c \ud638\ucd9c\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74 \uc810\uc810 \ub354 \ub9ce\uc740 \ub9ac\uc18c\uc2a4\uac00 \uc18c\ube44\ub429\ub2c8\ub2e4.<\/p>\n<h2>\uac00\ub2a5\ud55c \ub300\uccb4<\/h2>\n<p>\ub300\ubd80\ubd84\uc758 \uacbd\uc6b0 <code>GlobalScope<\/code> \uc0ac\uc6a9\uc744 \ud53c\ud574\uc57c \ud558\uba70 <code>GlobalScope<\/code>\ub97c \ud3ec\ud568\ud558\ub294 \uc791\uc5c5\uc740 &lt;0&gt;suspend<!--0-->\ub85c \ud45c\uc2dc\ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">suspend fun loadConfiguration() {\n    val config = fetchConfigFromServer() \/\/ network request\n    updateConfiguration(config)\n}\n<\/pre>\n<p><code>GlobalScope.launch<\/code>\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \uc791\uc5c5\uc744 \ub3d9\uc2dc\uc5d0 \uc2dc\uc791\ud558\ub294 \uacbd\uc6b0, \ud574\ub2f9 \uc791\uc5c5\uc744 \ub300\uc2e0 <code>coroutineScope<\/code>\ub85c \uadf8\ub8f9\ud654\ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\/\/ concurrently load configuration and data\nsuspend fun loadConfigurationAndData() {\n    coroutineScope {\n        launch { loadConfiguration() }\n        launch { loadData() }\n    }\n}\n<\/pre>\n<p>\ucd5c\uc0c1\uc704 \ucf54\ub4dc\uc5d0\uc11c \ube44\uc911\ub2e8 \ucee8\ud14d\uc2a4\ud2b8\ub85c \ub3d9\uc2dc \uc791\uc5c5\uc744 \uc2dc\uc791\ud560 \ub54c\ub294 <code>GlobalScope<\/code> \ub300\uc2e0 \uc801\uc808\ud558\uac8c \uc81c\ud55c\ub41c <code>CoroutineScope<\/code> \uc778\uc2a4\ud134\uc2a4\ub97c \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<h2>\uc801\ud569\ud55c \uc0ac\uc6a9 \uc0ac\ub840<\/h2>\n<p><code>GlobalScope<\/code>\ub97c \uc801\ud569\ud558\uace0 \uc548\uc804\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc81c\ud55c\ub41c \uc0c1\ud669\uc774 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uba74, \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc804\uccb4 \uc218\uba85 \uae30\uac04 \ub3d9\uc548 \ud65c\uc131 \uc0c1\ud0dc\ub85c \uc720\uc9c0\ub418\uc5b4\uc57c \ud558\ub294 \ucd5c\uc0c1\uc704 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ud504\ub85c\uc138\uc2a4\uac00 \uadf8\ub807\uc2b5\ub2c8\ub2e4. \ub530\ub77c\uc11c <code>GlobalScope<\/code>\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 <code>@OptIn(DelicateCoroutinesApi::class)<\/code>\ub97c \uc0ac\uc6a9\ud55c \uba85\uc2dc\uc801 \uc635\ud2b8\uc778\uc774 \ud544\uc694\ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\/\/ A global coroutine to log statistics every second, \n\/\/ must be always active\n@OptIn(DelicateCoroutinesApi::class)\nval globalScopeReporter = GlobalScope.launch {\n    while (true) {\n        delay(1000)\n        logStatistics()\n    }\n}\n<\/pre>\n<p><code>GlobalScope<\/code>\uc758 \ubaa8\ub4e0 \uc0ac\uc6a9\uc744 \uc8fc\uc758 \uae4a\uac8c \uac80\ud1a0\ud558\uace0 &#8220;\uc801\ud569\ud55c \uc0ac\uc6a9 \uc0ac\ub840&#8221; \ubc94\uc8fc\uc5d0 \ud574\ub2f9\ud558\ub294 \uacbd\uc6b0\uc5d0\ub9cc \uc5b4\ub178\ud14c\uc774\uc158\uc744 \ucd94\uac00\ud558\ub294 \uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4. \ub2e4\ub978 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ud558\uba74 \ucf54\ub4dc\uc5d0 \ubc84\uadf8\uac00 \uc0dd\uae30\ub294 \uc6d0\uc778\uc774 \ub420 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc704\uc758 \uc124\uba85\uc5d0 \ub530\ub77c <code>GlobalScope<\/code> \uc0ac\uc6a9\uc744 \ubc14\uafb8\ub294 \uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4.<\/p>\n<h1 id=\"junit\">JUnit 5 \ud655\uc7a5 \uae30\ub2a5<\/h1>\n<p>\ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\uc5ec \uc81c\uacf5\ub41c \uc2dc\uac04 \uc81c\ud55c \ud6c4\uc5d0 \uc2e4\ud328\ud558\uace0 \uc2a4\ub808\ub4dc\ub97c \uc911\ub2e8\ud560 \uc218 \uc788\ub294 <code>CoroutinesTimeout<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc744 \ucd94\uac00\ud588\uc2b5\ub2c8\ub2e4. \uc774\uc804\uc5d0\ub294 JUnit 4\uc5d0\uc11c <code>CoroutinesTimeout<\/code>\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\uc2b5\ub2c8\ub2e4. \uc774 \ub9b4\ub9ac\uc2a4\uc5d0\uc11c\ub294 JUnit 5\uc5d0 \ub300\ud55c \ud1b5\ud569\uc744 \ucd94\uac00\ud588\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc0c8 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\ub824\uba74 \ud504\ub85c\uc81d\ud2b8\uc5d0 \ub2e4\uc74c \uc885\uc18d\uc131\uc744 \ucd94\uac00\ud558\uc138\uc694.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">dependencies {\n  \u2026\n  testImplementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-debug:$coroutinesVersion\")\n}\n<\/pre>\n<p>\ub2e4\uc74c\uc740 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0c8\ub85c\uc6b4 <code>CoroutinesTimeout<\/code>\uc744 \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud55c \uac04\ub2e8\ud55c \uc608\uc785\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">import kotlinx.coroutines.debug.junit5.CoroutinesTimeout\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.runBlocking\nimport org.junit.Test\n\n@CoroutinesTimeout(100)\nclass CoroutinesTimeoutSimpleTest {\n\n     @CoroutinesTimeout(300)\n     @Test\n     fun firstTest() {\n         runBlocking {\n             delay(200)  \/\/ succeeds\n         }\n     }\n\n     @Test\n     fun secondTest() {\n         runBlocking {\n             delay(200)  \/\/ fails\n         }\n     }\n }\n<\/pre>\n<p>\uc774 \uc608\uc5d0\uc11c \ucf54\ub8e8\ud2f4 \uc2dc\uac04 \uc81c\ud55c\uc740 \ud074\ub798\uc2a4 \uc218\uc900\uc5d0\uc11c, \ud2b9\ud788 <code>firstTest<\/code>\uc5d0 \ub300\ud574 \uc815\uc758\ub429\ub2c8\ub2e4. \ud568\uc218\uc758 \uc5b4\ub178\ud14c\uc774\uc158\uc774 \ud074\ub798\uc2a4 \uc218\uc900 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc7ac\uc815\uc758\ud558\ubbc0\ub85c \uc5b4\ub178\ud14c\uc774\uc158\uc774 \ucd94\uac00\ub41c \ud14c\uc2a4\ud2b8\ub294 \uc2dc\uac04\uc774 \ucd08\uacfc\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. <code>secondTest<\/code>\ub294 \ud074\ub798\uc2a4 \uc218\uc900 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\ubbc0\ub85c \uc2dc\uac04\uc774 \ucd08\uacfc\ub429\ub2c8\ub2e4.<\/p>\n<p>\uc5b4\ub178\ud14c\uc774\uc158\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\uc2dd\uc73c\ub85c \uc120\uc5b8\ub429\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">package kotlinx.coroutines.debug.junit5\n\npublic annotation class CoroutinesTimeout(\n    val testTimeoutMs: Long,\n    val cancelOnTimeout: Boolean = false\n)\n<\/pre>\n<p>\uccab \ubc88\uc9f8 \ub9e4\uac1c\ubcc0\uc218\uc778 <code>testTimeoutMs<\/code>\ub294 \uc2dc\uac04 \ucd08\uacfc \uae30\uac04\uc744 \ubc00\ub9ac\ucd08 \ub2e8\uc704\ub85c \uc9c0\uc815\ud569\ub2c8\ub2e4. \ub450 \ubc88\uc9f8 \ub9e4\uac1c\ubcc0\uc218\uc778 <code>cancelOnTimeout<\/code>\uc740 \uc2dc\uac04\uc774 \ucd08\uacfc\ub418\ub294 \uc2dc\uc810\uc5d0 \uc2e4\ud589 \uc911\uc778 \ubaa8\ub4e0 \ucf54\ub8e8\ud2f4\uc744 \ucde8\uc18c\ud574\uc57c \ud558\ub294\uc9c0 \uc5ec\ubd80\ub97c \uacb0\uc815\ud569\ub2c8\ub2e4. <code>true<\/code>\ub85c \uc124\uc815\ud558\uba74 \ubaa8\ub4e0 \ucf54\ub8e8\ud2f4\uc774 \uc790\ub3d9\uc73c\ub85c \ucde8\uc18c\ub429\ub2c8\ub2e4.<\/p>\n<p><code>CoroutinesTimeout<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud560 \ub54c\ub9c8\ub2e4 \uc790\ub3d9\uc73c\ub85c <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2020\/07\/kotlin-1-4-rc-debugging-coroutines\/\">\ucf54\ub8e8\ud2f4 \ub514\ubc84\uac70<\/a>\ub97c \uc2e4\ud589\ud558\uace0 \uc2dc\uac04 \ucd08\uacfc \uc2dc\uc810\uc5d0 \ubaa8\ub4e0 \ucf54\ub8e8\ud2f4\uc744 \ub364\ud504\ud569\ub2c8\ub2e4. \ub364\ud504\uc5d0\ub294 \ucf54\ub8e8\ud2f4 \uc0dd\uc131 \uc2a4\ud0dd \ucd94\uc801\uc774 \ud3ec\ud568\ub429\ub2c8\ub2e4. \ud14c\uc2a4\ud2b8 \uc18d\ub3c4\ub97c \ub192\uc774\uae30 \uc704\ud574 \uc0dd\uc131 \uc2a4\ud0dd \ucd94\uc801\uc744 \ube44\ud65c\uc131\ud654\ud574\uc57c \ud558\ub294 \uacbd\uc6b0, \uc774 \uad6c\uc131\uc744 \uac00\ub2a5\ud558\uac8c \ud558\ub294 <code><a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/blob\/master\/kotlinx-coroutines-debug\/src\/junit\/junit5\/CoroutinesTimeoutExtension.kt\" class=\"ek-link\" target=\"_blank\" rel=\"noopener\">CoroutinesTimeoutExtension<\/a><\/code>\ub97c \uc9c1\uc811 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4.<\/p>\n<p><a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/issues\/2197\" class=\"ek-link\" target=\"_blank\" rel=\"noopener\">JUnit 5\uc6a9 CoroutinesTimeout<\/a>\uc744 \uc704\ud574 \uc720\uc6a9\ud55c PoC\ub97c \ub9cc\ub4e4\uc5b4\uc900 <a href=\"https:\/\/github.com\/asarkar\" target=\"_blank\" rel=\"noopener\">Abhijit Sarkar<\/a>\uc5d0\uac8c \uac10\uc0ac\ub4dc\ub9bd\ub2c8\ub2e4. \uc774 \uc544\uc774\ub514\uc5b4\ub294 1.5 \ub9b4\ub9ac\uc2a4\uc5d0 \ucd94\uac00\ub41c \uc0c8\ub85c\uc6b4 <code>CoroutinesTimeout<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc73c\ub85c \uad6c\ud604\ub418\uc5c8\uc2b5\ub2c8\ub2e4.<\/p>\n<h1 id=\"channels\">\ucc44\ub110 API \uac1c\uc120<\/h1>\n<p>\ucc44\ub110\uc740 \uc11c\ub85c \ub2e4\ub978 \ucf54\ub8e8\ud2f4\uacfc \ucf5c\ubc31 \uc0ac\uc774\uc5d0 \ub370\uc774\ud130\ub97c \uc804\ub2ec\ud560 \uc218 \uc788\ub294 \uc911\uc694\ud55c \ud1b5\uc2e0 \uae30\ubcf8 \uc694\uc18c\uc785\ub2c8\ub2e4. \uc774 \ub9b4\ub9ac\uc2a4\uc5d0\uc11c\ub294 \ud63c\ub3d9\uc744 \uc77c\uc73c\ud0a4\ub294 <code>offer<\/code> \ubc0f <code>poll<\/code> \ud568\uc218\ub97c \ub354 \ub098\uc740 \ub300\uc548\uc73c\ub85c \ub300\uccb4\ud558\uc5ec \ucc44\ub110 API\ub97c \uc870\uae08 \uc190 \ubcf4\uc558\uc2b5\ub2c8\ub2e4. \uadf8 \uacfc\uc815\uc5d0\uc11c \uc911\ub2e8 \ubc0f \ube44\uc911\ub2e8 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \uba85\uba85 \uccb4\uacc4\ub97c \uc0c8\ub86d\uac8c \uac1c\ubc1c\ud588\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>\uc0c8\ub85c\uc6b4 \uba85\uba85 \uccb4\uacc4<\/h2>\n<p>\ub2e4\ub978 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 Coroutines API\uc5d0\uc11c \ub354 \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub3c4\ub85d \ud558\uae30 \uc704\ud574 \uc77c\uad00\ub41c \uba85\uba85 \uccb4\uacc4\ub97c \uc218\ub9bd\ud558\ub294 \ub370 \ub178\ub825\uc744 \uae30\uc6b8\uc600\uc2b5\ub2c8\ub2e4. \ud568\uc218\uc758 \uc774\ub984\uc774 \ud574\ub2f9 \ub3d9\uc791\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uc804\ub2ec\ud560 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ub370 \uc2e0\uacbd\uc744 \uc37c\uc2b5\ub2c8\ub2e4. \uadf8\ub798\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \uacb0\uacfc\ub97c \uc5bb\uc5c8\uc2b5\ub2c8\ub2e4.<\/p>\n<ul>\n<li>\uc77c\ubc18\uc801\uc778 \uc911\ub2e8 \uba54\uc11c\ub4dc\ub294 \uadf8\ub300\ub85c \uc720\uc9c0\ub429\ub2c8\ub2e4(\uc608: <code>send<\/code>, <code>receive<\/code>).<\/li>\n<li>\uc624\ub958 \ucea1\uc290\ud654\ub97c \uc0ac\uc6a9\ud558\ub294 \ube44\uc911\ub2e8 \uba54\uc11c\ub4dc \uc55e\uc5d0\ub294 \uacc4\uc18d\ud574\uc11c \uc608\uc804\uc758 <code>offer<\/code> \ubc0f <code>poll<\/code> \ub300\uc2e0\uc5d0 &#8220;try&#8221;: <code>trySend<\/code> \ubc0f <code>tryReceive<\/code>\uac00 \ubd99\uc2b5\ub2c8\ub2e4.<\/li>\n<li>\uc0c8\ub85c\uc6b4 \uc624\ub958 \ucea1\uc290\ud654 \uc911\ub2e8 \uba54\uc11c\ub4dc \ub05d\uc5d0\ub294 &#8220;Catching&#8221;\uc774 \ubd99\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ul>\n<p>\uc774\ub7ec\ud55c \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud574 \uc790\uc138\ud788 \uc0b4\ud3b4\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h2> <code>Try<\/code> \ud568\uc218: <code>send<\/code> \ubc0f <code>receive<\/code>\uc5d0 \ub300\ud55c \ube44 \uc77c\uc2dc \uc911\ub2e8 \ub300\uc751 \ud56d\ubaa9<\/h2>\n<p>\uc5b4\ub5a4 \ucf54\ub8e8\ud2f4\uc740 \uc77c\ubd80 \uc815\ubcf4\ub97c \ucc44\ub110\ub85c \ubcf4\ub0bc \uc218 \uc788\uace0, \ub610 \ub2e4\ub978 \ucf54\ub8e8\ud2f4\uc740 \uc5ec\uae30\uc11c \uc815\ubcf4\ub97c \ubc1b\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4. <code>send<\/code> \ubc0f <code>receive<\/code> \ud568\uc218 \ubaa8\ub450\uac00 \uc77c\uc2dc \uc911\ub2e8\ub429\ub2c8\ub2e4. <code>send<\/code>\ub294 \ucc44\ub110\uc774 \uac00\ub4dd \ucc28\uc11c \uc0c8 \uc694\uc18c\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \uacbd\uc6b0 \ucf54\ub8e8\ud2f4\uc744 \uc77c\uc2dc \uc911\ub2e8\ud558\uace0, <code>receive<\/code>\ub294 \ucc44\ub110\uc5d0 \ubc18\ud658\ud560 \uc694\uc18c\uac00 \uc5c6\ub294 \uacbd\uc6b0 \ucf54\ub8e8\ud2f4\uc744 \uc77c\uc2dc \uc911\ub2e8\ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">import kotlinx.coroutines.channels.Channel\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\n\nfun main() = runBlocking&lt;Unit&gt; {\n    val channel = Channel&lt;String&gt;()\n    launch {\n        \/\/ Suspends until the element can be sent\n        println(\"Sending...\")\n        channel.send(\"Element\")\n     }\n     \/\/ Suspends until the element can be received\n     println(\"Receiving...\")\n     println(channel.receive())\n}\n<\/pre>\n<p>\uc774\ub7ec\ud55c \ud568\uc218\uc5d0\ub294 \ub3d9\uae30 \ucf54\ub4dc\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \uc704\ud55c \ube44\uc911\ub2e8 \ub300\uc751 \ud568\uc218\uc778 <code>offer<\/code> \ubc0f <code>poll<\/code>\uc774 \uc788\uc2b5\ub2c8\ub2e4. \uc774\ub7ec\ud55c \ud568\uc218\ub294 \uace7 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uac8c \ub418\uace0 \ud604\uc7ac\ub294 <code>trySend<\/code> \ubc0f <code>tryReceive<\/code>\uac00 \ub300\uc2e0 \uc0ac\uc6a9\ub429\ub2c8\ub2e4. \uc774\ub807\uac8c \ubcc0\uacbd\ud55c \uc774\uc720\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<p><code>offer<\/code> \ubc0f <code>poll<\/code>\uc740 <code>send<\/code> \ubc0f <code>receive<\/code>\uc640 \ub3d9\uc77c\ud55c \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub3c4\ub85d \uc758\ub3c4\ub418\uc5c8\uc9c0\ub9cc \uc77c\uc2dc \uc911\ub2e8\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. \uc774\uac83\uc774 \uc774\ud574\ud558\uae30 \uc27d\uace0, \uc694\uc18c\ub97c \ubcf4\ub0b4\uac70\ub098 \ubc1b\uc744 \uc218 \uc788\uc744 \ub54c \ubaa8\ub4e0 \uac83\uc774 \uc798 \uc791\ub3d9\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uba74 \uc5b4\ub5bb\uac8c \ub420\uae4c\uc694? <code>send<\/code> \ubc0f <code>receive<\/code>\ub294 \uc791\uc5c5\uc744 \uc218\ud589\ud560 \uc218 \uc788\uc744 \ub54c\uae4c\uc9c0 \uc77c\uc2dc \uc911\ub2e8\ud569\ub2c8\ub2e4. <code>offer<\/code> \ubc0f <code>poll<\/code>\uc740 \ucc44\ub110\uc774 \uac00\ub4dd \ucc28\uc11c \uc694\uc18c\ub97c \ucd94\uac00\ud560 \uc218 \uc5c6\ub294 \uacbd\uc6b0, \ub610\ub294 \ucc44\ub110\uc774 \ube44\uc5b4 \uc788\uc5b4 \uc694\uc18c\ub97c \uac00\uc838\uc62c \uc218 \uc5c6\ub294 \uacbd\uc6b0\uc5d0 \uac01\uac01 <code>false<\/code> \ubc0f <code>null<\/code>\uc744 \ubc18\ud658\ud558\uae30\ub9cc \ud588\uc2b5\ub2c8\ub2e4. \ub458 \ubaa8\ub450 \ub2eb\ud78c \ucc44\ub110\ub85c \uc791\uc5c5\ud558\ub824\uace0 \uc608\uc678\ub97c \ub358\uc84c\uc73c\uba70, \uc774 \ub9c8\uc9c0\ub9c9 \ub3d9\uc791\uc774 \ud63c\ub780\uc744 \uc77c\uc73c\ucf30\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">import kotlinx.coroutines.channels.Channel\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\n\nfun main() = runBlocking&lt;Unit&gt; {\n    val channel = Channel&lt;String&gt;()\n    launch {\n        println(\"Sending...\")\n        \/\/ Doesn't suspend\n        \/\/ Returns 'false' if the channel is full\n        \/\/ Or throws an exception if it's closed\n        channel.offer(\"Element\")\n    }\n    println(\"Receiving...\")\n    \/\/ Doesn't suspend\n    \/\/ Returns 'null' if the channel is empty\n    println(channel.poll())\n\/\/  channel.close()\n}\n<\/pre>\n<p>\uc774 \uc608\uc5d0\uc11c <code>poll<\/code>\uc740 \uc694\uc18c\uac00 \ucd94\uac00\ub418\uae30 \uc804\uc5d0 \ud638\ucd9c\ub418\ubbc0\ub85c \uc989\uc2dc <code>null<\/code>\uc744 \ubc18\ud658\ud569\ub2c8\ub2e4. \uc774\ub7ec\ud55c \uc0ac\uc6a9 \ubc29\uc2dd\uc740 \uc6d0\ub798 \uc758\ub3c4\ud55c \uac83\uc774 \uc544\ub2cc \uc810\uc744 \uc720\uc758\ud574 \uc8fc\uc138\uc694. \ub300\uc2e0, \uc694\uc18c\ub97c \uacc4\uc18d\ud574\uc11c \uc815\uae30\uc801\uc73c\ub85c \ud3f4\ub9c1\ud574\uc57c \ud558\uc9c0\ub9cc \uc774 \uc124\uba85\uc5d0\uc11c\ub294 \uc774\ud574\ub97c \ub3d5\uae30 \uc704\ud574 \uc9c1\uc811 \ud638\ucd9c\ud558\uaca0\uc2b5\ub2c8\ub2e4. \ub610\ud55c, \uc6b0\ub9ac\uac00 \uc0ac\uc6a9\ud558\ub294 \ucc44\ub110\uc740 \ub791\ub370\ubdf0 \ucc44\ub110\uc774\uace0 \ubc84\ud37c \uc6a9\ub7c9\uc774 \uc5c6\uae30 \ub54c\ubb38\uc5d0 <code>offer<\/code> \ud638\ucd9c\uc774 \uc2e4\ud328\ud569\ub2c8\ub2e4. \uacb0\uacfc\uc801\uc73c\ub85c, \uc21c\uc804\ud788 \uc798\ubabb\ub41c \uc21c\uc11c\ub85c \ud638\ucd9c\ub418\uc5c8\ub2e4\ub294 \uc774\uc720\ub85c <code>offer<\/code>\ub294 <code>false<\/code>\ub97c \ubc18\ud658\ud558\uace0 <code>poll<\/code>\uc740 <code>null<\/code>\uc744 \ubc18\ud658\ud569\ub2c8\ub2e4.<\/p>\n<p>\uc704\uc758 \uc608\uc5d0\uc11c <code>channel.close()<\/code> \ubb38\uc758 \uc8fc\uc11d \ucc98\ub9ac\ub97c \uc81c\uac70\ud558\uc5ec \uc608\uc678\uac00 \ub358\uc838\uc9c0\ub294\uc9c0 \ud655\uc778\ud574 \ubcf4\uc138\uc694. \uc774 \uacbd\uc6b0 <code>poll<\/code>\uc740 \uc774\uc804\uacfc \uac19\uc774 <code>false<\/code>\ub97c \ubc18\ud658\ud569\ub2c8\ub2e4. \uadf8\ub7ec\ub098 <code>offer<\/code>\ub294 \uc774\ubbf8 \ub2eb\ud78c \ucc44\ub110\uc5d0 \uc694\uc18c\ub97c \ucd94\uac00\ud558\ub824\uace0 \ud558\uc9c0\ub9cc \uc2e4\ud328\ud558\uace0 \uc608\uc678\ub97c \ub358\uc9d1\ub2c8\ub2e4. \uc800\ud76c\ub294 \uc774\ub7ec\ud55c \ub3d9\uc791\uc5d0 \uc624\ub958\uac00 \ub9ce\ub2e4\ub294 \ubd88\ub9cc\uc744 \ub9ce\uc774 \ubc1b\uc558\uc2b5\ub2c8\ub2e4. \uc774 \uc608\uc678\ub294 \uac04\uacfc\ud558\uae30 \uc26c\uc6b0\uba70 \ubb34\uc2dc\ud558\uac70\ub098 \ub2e4\ub974\uac8c \ucc98\ub9ac\ud558\uba74 \ud504\ub85c\uadf8\ub7a8\uc774 \ucda9\ub3cc\ud569\ub2c8\ub2e4.<\/p>\n<p>\uc0c8\ub85c\uc6b4 <code>trySend<\/code> \ubc0f <code>tryReceive<\/code>\ub294 \uc774 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uace0 \ub354 \uc0c1\uc138\ud55c \uacb0\uacfc\ub97c \ubc18\ud658\ud569\ub2c8\ub2e4. \uac01\uac01\uc774 <code>ChannelResult<\/code> \uc778\uc2a4\ud134\uc2a4\ub97c \ubc18\ud658\ud558\ub294\ub370, \uc774\ub294 \uc131\uacf5\ud55c \uacb0\uacfc, \uc2e4\ud328 \ub610\ub294 \ucc44\ub110\uc774 \ub2eb\ud614\uc74c\uc744 \ub098\ud0c0\ub0b4\ub294 \uc138 \uac00\uc9c0 \uc911 \ud558\ub098\uc785\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">import kotlinx.coroutines.channels.Channel\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\n\nfun main() = runBlocking&lt;Unit&gt; {\n    val channel = Channel&lt;String&gt;()\n    launch {\n        println(\"Sending...\")\n        \/\/ Doesn't suspend\n        \/\/ Returns 'Failed' if the channel is full\n        \/\/ Or 'Channel was closed' result if it's closed\n        val result = channel.trySend(\"Element\")\n        println(result)\n\n        \/\/We can verify the result\n        if(result.isClosed){\n            println(\"Sending failed. The channel is closed.\")\n        }\n    }\n    println(\"Receiving...\")\n    println(channel.tryReceive())\n\/\/  channel.close()\n}\n<\/pre>\n<p>\uc774 \uc608\uc81c\ub294 <code>tryReceive<\/code> \ubc0f <code>trySend<\/code>\uac00 \ub354 \uc0c1\uc138\ud55c \uacb0\uacfc\ub97c \ubc18\ud658\ud55c\ub2e4\ub294 \uc810\ub9cc \uc81c\uc678\ud558\uba74 \uc774\uc804 \uc608\uc81c\uc640 \ub3d9\uc77c\ud55c \ubc29\uc2dd\uc73c\ub85c \uc791\ub3d9\ud569\ub2c8\ub2e4. \ucd9c\ub825\uc5d0\uc11c <code>false<\/code> \ubc0f <code>null<\/code> \ub300\uc2e0 <code>Value(Failed)<\/code>\ub97c \ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ucc44\ub110\uc744 \ub2eb\ub294 \uc904\uc758 \uc8fc\uc11d \ucc98\ub9ac\ub97c \ub2e4\uc2dc \uc81c\uac70\ud558\uace0 <code>trySend<\/code>\uac00 \uc774\uc81c \uc608\uc678\ub97c \ucea1\ucc98\ud558\ub294 <code>Closed<\/code> \uacb0\uacfc\ub97c \u200b\u200b\ubc18\ud658\ud558\ub294\uc9c0 \ud655\uc778\ud569\ub2c8\ub2e4.<\/p>\n<p><a href=\"https:\/\/kotlinlang.org\/docs\/inline-classes.html\" target=\"_blank\" rel=\"noopener\">inline value \ud074\ub798\uc2a4<\/a> \ub355\ubd84\uc5d0 <code>ChannelResult<\/code>\ub97c \uc0ac\uc6a9\ud574\ub3c4 \uc544\ub798\uc5d0 \ucd94\uac00 \ub798\ud37c\uac00 \uc0dd\uc131\ub418\uc9c0 \uc54a\uc73c\uba70, \uac12\uc774 \uc131\uacf5\uc801\uc73c\ub85c \ubc18\ud658\ub418\uba74 \uc624\ubc84\ud5e4\ub4dc \uc5c6\uc774 \uc788\ub294 \uadf8\ub300\ub85c \ubc18\ud658\ub429\ub2c8\ub2e4.<\/p>\n<h2>Catching \ud568\uc218: \uc624\ub958\ub97c \ucea1\uc290\ud654\ud558\ub294 \uc77c\uc2dc \uc911\ub2e8 \ud568\uc218<\/h2>\n<p>\uc774\ubc88 \ub9b4\ub9ac\uc2a4\ubd80\ud130 \uc624\ub958 \ucea1\uc290\ud654 \uc77c\uc2dc \uc911\ub2e8 \uba54\uc11c\ub4dc \ub05d\uc5d0\ub294 &#8220;Catching&#8221;\uc774 \ubd99\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \uc0c8\ub85c\uc6b4 <code>receiveCatching<\/code> \ud568\uc218\ub294 \ub2eb\ud78c \ucc44\ub110\uc758 \uacbd\uc6b0 \uc608\uc678\ub97c \ucc98\ub9ac\ud569\ub2c8\ub2e4. \ub2e4\uc74c\uc758 \uac04\ub2e8\ud55c \uc608\ub97c \uc0dd\uac01\ud574 \ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">import kotlinx.coroutines.channels.Channel\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\n\nfun main() = runBlocking&lt;Unit&gt; {\n    val channel = Channel&lt;String&gt;()\n    channel.close()\n    println(channel.receiveCatching())\n}\n<\/pre>\n<p>\ucc44\ub110\uc740 \uac12\uc744 \uac80\uc0c9\ud558\uae30 \uc804\uc5d0 \ub2eb\ud799\ub2c8\ub2e4. \uadf8\ub7ec\ub098, \ud504\ub85c\uadf8\ub7a8\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub418\uc5b4 \ucc44\ub110\uc774 \ub2eb\ud78c \uac83\uc73c\ub85c \ub098\ud0c0\ub0a9\ub2c8\ub2e4. <code>receiveCatching<\/code>\uc744 \uc77c\ubc18 <code>receive<\/code> \ud568\uc218\ub85c \ubc14\uafb8\uba74 <code>ClosedReceiveChannelException<\/code>\uc744 \ub358\uc9d1\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">import kotlinx.coroutines.channels.Channel\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\n\nfun main() = runBlocking&lt;Unit&gt; {\n    val channel = Channel&lt;String&gt;()\n    channel.close()\n    println(channel.receive())\n}\n<\/pre>\n<p>\uc9c0\uae08\uc740 <code>receiveCatching<\/code> \ubc0f <code>onReceiveCatching<\/code>\ub9cc \uc81c\uacf5\ud558\uc9c0\ub9cc(\uc774\uc804\uc758 \ub0b4\ubd80 <code>receiveOrClosed<\/code> \ub300\uc2e0) \ub354 \ub9ce\uc740 \ud568\uc218\ub97c \ucd94\uac00\ud560 \uacc4\ud68d\uc785\ub2c8\ub2e4.<\/p>\n<h2>\ucf54\ub4dc\ub97c \uc0c8 \ud568\uc218\ub85c \ub9c8\uc774\uadf8\ub808\uc774\uc158<\/h2>\n<p>\ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c <code>offer<\/code> \ubc0f <code>poll<\/code> \ud568\uc218\uc758 \ubaa8\ub4e0 \uc778\uc2a4\ud134\uc2a4\ub97c \uc790\ub3d9\uc73c\ub85c \uc0c8 \ud638\ucd9c\ub85c \ubc14\uafc0 \uc218 \uc788\uc2b5\ub2c8\ub2e4. <code>offer<\/code>\uac00 <code>Boolean<\/code>\uc744 \ubc18\ud658\ud588\uae30 \ub54c\ubb38\uc5d0 \uc774\uc5d0 \uc0c1\uc751\ud558\ub294 \ub300\uccb4\ub294 <code>channel.trySend(\"Element\").isSuccess<\/code>\uc785\ub2c8\ub2e4.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"800\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/05\/cor15-offer-deprecated.png\" alt=\"\" class=\"wp-image-142625\"><\/figure>\n<p>\ub9c8\ucc2c\uac00\uc9c0\ub85c, <code>poll<\/code> \ud568\uc218\ub294 null \uac00\ub2a5 \uc694\uc18c\ub97c \ubc18\ud658\ud558\ubbc0\ub85c \uadf8 \ub300\uccb4\ub294 <code>channel.tryReceive().getOrNull()<\/code>\uc774 \ub429\ub2c8\ub2e4.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1440\" height=\"440\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/05\/cor15-poll-deprecated.png\" alt=\"\" class=\"wp-image-142636\"><\/figure>\n<p>\ud638\ucd9c \uacb0\uacfc\uac00 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc740 \uacbd\uc6b0, \uc9c1\uc811 \uc0c8 \ud638\ucd9c\ub85c \ubc14\uafc0 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc774\uc81c \uc608\uc678 \ucc98\ub9ac\uc5d0 \ub300\ud55c \ub3d9\uc791\uc774 \ub2e4\ub974\ubbc0\ub85c \ud544\uc694\ud55c \uc5c5\ub370\uc774\ud2b8\ub97c \uc218\ub3d9\uc73c\ub85c \ud574\uc57c \ud569\ub2c8\ub2e4. \ucf54\ub4dc\uac00 \ub2eb\ud78c \ucc44\ub110\uc5d0\uc11c \uc608\uc678\ub97c \ub358\uc9c0\ub294 &#8216;offer&#8217; \ubc0f &#8216;poll&#8217; \uba54\uc11c\ub4dc\uc5d0 \uc758\uc874\ud558\ub294 \uacbd\uc6b0, \ub2e4\uc74c \ub300\uccb4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<p><code>channel.offer(\"Element\")<\/code>\uc5d0 \ub300\ud55c \ub3d9\ub4f1\ud55c \ub300\uccb4 \uc694\uc18c\ub294 \ucc44\ub110\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub2eb\ud614\ub354\ub77c\ub3c4 \uc608\uc678\ub97c \ub358\uc838\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">channel\n  .trySend(\"Element\")\n  .onClosed { throw it ?: ClosedSendChannelException(\"Channel was closed\") }\n  .isSuccess\n<\/pre>\n<p><code>channel.poll()<\/code>\uc758 \ub3d9\ub4f1\ud55c \ub300\uccb4 \uc694\uc18c\ub294 \ucc44\ub110\uc774 \uc624\ub958\uc640 \ud568\uaed8 \ub2eb\ud614\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c0\uace0 \uc815\uc0c1\uc801\uc73c\ub85c \ub2eb\ud614\ub2e4\uba74 null\uc744 \ubc18\ud658\ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">channel.tryReceive()\n  .onClosed { if (it != null) throw it }\n  .getOrNull()\n<\/pre>\n<p>\uc774\ub7ec\ud55c \ubcc0\uacbd \uc0ac\ud56d\uc740 <code>offer<\/code> \ubc0f <code>poll<\/code> \ud568\uc218\uc758 \uc774\uc804 \ub3d9\uc791\uc744 \ubc18\uc601\ud569\ub2c8\ub2e4.<\/p>\n<p>\ub300\ubd80\ubd84\uc758 \uacbd\uc6b0, \ucf54\ub4dc\uac00 \ub2eb\ud78c \ucc44\ub110\uc5d0\uc11c \uc774\ub7ec\ud55c \ubbf8\ubb18\ud55c \ub3d9\uc791\uc5d0 \ub530\ub77c \uc88c\uc6b0\ub41c \uac83\uc774 \uc544\ub2c8\ub77c, \ubc84\uadf8\uc758 \uc6d0\uc778\uc774\uc5c8\ub2e4\uace0 \uac00\uc815\ud569\ub2c8\ub2e4. \uc774\uac83\uc774 IDE\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc790\ub3d9 \ub300\uccb4 \uae30\ub2a5\uc774 \uc758\ubbf8\ub97c \ub2e8\uc21c\ud654\ud558\ub294 \uc774\uc720\uc785\ub2c8\ub2e4. \uc2e4\uc81c\ub85c \uc5ec\uae30\uc5d0 \ud574\ub2f9\ub418\uc9c0 \uc54a\ub294 \uacbd\uc6b0, \uc0ac\uc6a9 \uc704\uce58\ub97c \uc218\ub3d9\uc73c\ub85c \uac80\ud1a0 \ubc0f \uc5c5\ub370\uc774\ud2b8\ud558\uace0, \uc608\uc678\ub97c \ub358\uc9c0\uc9c0 \uc54a\uace0 \ub2eb\ud78c \ucc44\ub110\uc744 \ub2e4\ub974\uac8c \ucc98\ub9ac\ud558\ub3c4\ub85d \ucf54\ub4dc\ub97c \uc644\uc804\ud788 \ub2e4\uc2dc \uc791\uc131\ud558\ub294 \uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4.<\/p>\n<h1 id=\"reactive\">\uc548\uc815\uc131\uc73c\ub85c \uac00\ub294 Reactive \ud1b5\ud569<\/h1>\n<p>Kotlin Coroutines \ubc84\uc804 1.5\ub294 \ubc18\uc751\ud615 \ud504\ub808\uc784\uc6cc\ud06c\uc640\uc758 \ud1b5\ud569\uc744 \ub2f4\ub2f9\ud558\ub294 \ub300\ubd80\ubd84\uc758 \ud568\uc218\ub97c \uc548\uc815\uc801\uc778 API\ub85c \uc2b9\uaca9\uc2dc\ucf30\uc2b5\ub2c8\ub2e4.<\/p>\n<p>JVM \uc5d0\ucf54\uc2dc\uc2a4\ud15c\uc5d0\ub294 <a href=\"https:\/\/www.reactive-streams.org\/\" target=\"_blank\" rel=\"noopener\">Reactive Streams<\/a> \ud45c\uc900\uc5d0 \ub530\ub77c \ube44\ub3d9\uae30 \uc2a4\ud2b8\ub9bc\uc744 \ucc98\ub9ac\ud558\ub294 \uba87 \uac00\uc9c0 \ud504\ub808\uc784\uc6cc\ud06c\uac00 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, <a href=\"https:\/\/projectreactor.io\/\" target=\"_blank\" rel=\"noopener\">Project Reactor<\/a> \ubc0f <a href=\"https:\/\/github.com\/ReactiveX\/RxJava\" target=\"_blank\" rel=\"noopener\">RxJava<\/a>\ub294 \uc774 \uc601\uc5ed\uc5d0\uc11c \ub110\ub9ac \uc0ac\uc6a9\ub418\ub294 \ub450 \uac00\uc9c0 Java \ud504\ub808\uc784\uc6cc\ud06c\uc785\ub2c8\ub2e4.<\/p>\n<p><a href=\"https:\/\/kotlinlang.org\/docs\/flow.html\" target=\"_blank\" rel=\"noopener\">Kotlin Flows<\/a>\ub294 \uc774\uc640 \ub2e4\ub974\uace0 \ud0c0\uc785\uc774 \ud45c\uc900\uc5d0 \uc9c0\uc815\ub41c \uac83\uacfc \uc77c\uce58\ud558\uc9c0\ub294 \uc54a\uc9c0\ub9cc \uac1c\ub150\uc801\uc73c\ub85c\ub294 \uc5ec\uc804\ud788 \uc2a4\ud2b8\ub9bc\uc785\ub2c8\ub2e4. <code>Flow<\/code>\ub97c \ubc18\uc751\ud615(\uc0ac\uc591 \ubc0f <a href=\"https:\/\/github.com\/reactive-streams\/reactive-streams-jvm\/tree\/master\/tck\" target=\"_blank\" rel=\"noopener\">TCK<\/a> \uc900\uc218) <code>Publisher<\/code>\ub85c \ubcc0\ud658\ud560 \uc218 \uc788\uace0 \uadf8 \ubc18\ub300\ub3c4 \ub9c8\ucc2c\uac00\uc9c0\uc785\ub2c8\ub2e4. \uc774\ub7ec\ud55c \ubcc0\ud658\uae30\ub294 <code>kotlinx.coroutines<\/code>\uc5d0\uc11c \uc989\uc2dc \uc81c\uacf5\ub418\uba70 \ud574\ub2f9 \ubc18\uc751\ud615 \ubaa8\ub4c8\uc5d0\uc11c \ucc3e\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc608\ub97c \ub4e4\uc5b4, Project Reactor \ud0c0\uc785\uacfc\uc758 \uc0c1\ud638 \uc6b4\uc6a9\uc131\uc774 \ud544\uc694\ud55c \uacbd\uc6b0 \ud504\ub85c\uc81d\ud2b8\uc5d0 \ub2e4\uc74c \uc885\uc18d\uc131\uc744 \ucd94\uac00\ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">dependencies {          \n    implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core:${coroutinesVersion}\")\n    implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-reactor:${coroutinesVersion}\")\n}\n<\/pre>\n<p>\uadf8\ub7ec\uba74 <em>Reactive Streams<\/em> \ud0c0\uc785\uc744 \uc0ac\uc6a9\ud558\ub824\ub294 \uacbd\uc6b0 <code>Flow&lt;T&gt;.asPublisher()<\/code>\ub97c \uc0ac\uc6a9\ud558\uac70\ub098, Project Reactor \ud0c0\uc785\uc744 \uc9c1\uc811 \uc0ac\uc6a9\ud574\uc57c \ud558\ub294 \uacbd\uc6b0 <code>Flow&lt;T&gt;.asFlux()<\/code>\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\/\/ acquire a Flow instance\nval flow: Flow&lt;event&gt; = flow { \u2026 }\n\n\/\/ Convert Flow to Publisher\nval publisher = flow.asPublisher()\n\n\/\/ Convert Flow to Reactor's Flux\nval flux = flow.asFlux()\n\n\/\/Convert back to Flow \nval anotherFlow = flux.asFlow()\n<\/pre>\n<p>\uc774\uac83\uc740 \uad00\ub828 \uc8fc\uc81c\ub97c \ub9e4\uc6b0 \uc555\ucd95\uc801\uc73c\ub85c \ubcf4\uc5ec\uc8fc\ub294 \ubdf0\uc785\ub2c8\ub2e4. \ub354 \uc790\uc138\ud788 \uc54c\uc544\ubcf4\ub824\uba74 <a href=\"https:\/\/elizarov.medium.com\/reactive-streams-and-kotlin-flows-bfd12772cda4\" target=\"_blank\" rel=\"noopener\">Reactive Streams \ubc0f Kotlin Flows\uc5d0 \ub300\ud55c Roman Elizarov\uc758 \uae00<\/a>\uc744 \uc77d\uc5b4\ubcf4\uc138\uc694.<\/p>\n<p>\ubc18\uc751\ud615 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc640\uc758 \ud1b5\ud569\uc774 API \uc548\uc815\ud654 \ubc29\ud5a5\uc73c\ub85c \uc774\ub8e8\uc5b4\uc9c0\uace0 \uc788\uc9c0\ub9cc \uae30\uc220\uc801\uc778 \ubaa9\ud45c\ub294 <code>@ExperimentalCoroutinesApi<\/code>\ub97c \uc5c6\uc560\uace0 \ub0a8\uc544\uc788\ub294 \uc774\uc288\ub97c \uc218\uc815\ud558\ub294 \uac83\uc785\ub2c8\ub2e4.<\/p>\n<h2>Reactive Streams\uc640\uc758 \ud1b5\ud569 \uac1c\uc120<\/h2>\n<p>\ud0c0\uc0ac \ud504\ub808\uc784\uc6cc\ud06c\uc640 Kotlin \ucf54\ub8e8\ud2f4 \uac04\uc758 \uc0c1\ud638 \uc6b4\uc6a9\uc131\uc744 \ubcf4\uc7a5\ud558\ub824\uba74 Reactive Streams \uc0ac\uc591\uacfc\uc758 \ud638\ud658\uc131\uc774 \uc911\uc694\ud569\ub2c8\ub2e4. \uadf8\ub7ec\uba74 \ubaa8\ub4e0 \ucf54\ub4dc\ub97c \ub2e4\uc2dc \uc791\uc131\ud560 \ud544\uc694\uc5c6\uc774 \uae30\uc874 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c Kotlin \ucf54\ub8e8\ud2f4\uc744 \ucc44\ud0dd\ud558\ub294 \ub370 \ub3c4\uc6c0\uc774 \ub429\ub2c8\ub2e4.<\/p>\n<p>\uc774\ubc88\uc5d0 \uc548\uc815\uc801\uc778 \uc0c1\ud0dc\ub85c \uc62c\ub824 \ub193\uc740 <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/commit\/47a063c0987177551bdbdf09a458998a30571ac2\" target=\"_blank\" rel=\"noopener\">\ud568\uc218\ub4e4\uc774 \ub9ce\uc774 \uc788\uc2b5\ub2c8\ub2e4<\/a>. \uc774\uc81c \ubaa8\ub4e0 Reactive Streams \uad6c\ud604\uc5d0\uc11c <code>Flow<\/code>\ub85c, \ub610\ub294 \uadf8 \ubc18\ub300\ub85c \uc720\ud615\uc744 \ubcc0\ud658\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \uc0c8\ub85c\uc6b4 \ucf54\ub4dc\ub294 \ucf54\ub8e8\ud2f4\uc73c\ub85c \uc791\uc131\ub420 \uc218 \uc788\uc9c0\ub9cc \ubc18\ub300 \ubcc0\ud658\uae30\ub97c \ud1b5\ud574 \uc774\uc804 \ubc18\uc751 \ucf54\ub4dc\ubca0\uc774\uc2a4\uc640 \ud1b5\ud569\ub429\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">fun legacyFunThatHaveToReturnObservable(): Observable&lt;int&gt; {\n  return flow&lt;int&gt; {\n    \/\/ Use the power of flow!\n  }\n  \/\/ various flow operations\n  .asObservable()\n}\n<\/pre>\n<p>\ub610\ud55c Reactor\uc758 <a href=\"https:\/\/projectreactor.io\/docs\/core\/release\/reference\/#context\" target=\"_blank\" rel=\"noopener\">Context<\/a>\ub97c <a href=\"https:\/\/kotlinlang.org\/docs\/coroutine-context-and-dispatchers.html\" target=\"_blank\" rel=\"noopener\">CoroutineContext<\/a>\ub85c \ub798\ud551\ud558\ub294 <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/blob\/master\/reactive\/kotlinx-coroutines-reactor\/src\/ReactorContext.kt\" target=\"_blank\" rel=\"noopener\"><code>ReactorContext<\/code><\/a>\uc5d0 \uc218 \ub9ce\uc740 <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/pull\/2622\" target=\"_blank\" rel=\"noopener\">\uac1c\uc120 \uc0ac\ud56d<\/a>\uc774 \uc801\uc6a9\ub418\uc5b4 Project Reactor\uc640 Kotlin \ucf54\ub8e8\ud2f4 \uc0ac\uc774\uc5d0\uc11c \uc644\ubcbd\ud55c \ud1b5\ud569\uc744 \uc9c0\uc6d0\ud569\ub2c8\ub2e4. \uc774 \ud1b5\ud569\uc73c\ub85c \ucf54\ub8e8\ud2f4\uc744 \ud1b5\ud574 Reactor\uc758 Context\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uc804\ud30c\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\ucee8\ud14d\uc2a4\ud2b8\ub294 <code>Mono<\/code>, <code>Flux<\/code>, <code>Publisher.asFlow<\/code>, <code>Flow.asPublisher<\/code> \ubc0f <code>Flow.asFlux<\/code>\uc640 \uac19\uc740 \ubaa8\ub4e0 Reactive \ud1b5\ud569\uc5d0 \uc758\ud574 subscriber\ub97c \ud1b5\ud574 \ubb35\uc2dc\uc801\uc73c\ub85c \uc804\ud30c\ub429\ub2c8\ub2e4. \ub2e4\uc74c\uc740 subscriber\uc758 <code>Context<\/code>\ub97c <code>ReactorContext<\/code>\uc5d0 \uc804\ud30c\ud558\ub294 \uac04\ub2e8\ud55c \uc608\uc785\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">import kotlinx.coroutines.currentCoroutineContext\nimport kotlinx.coroutines.flow.flow\nimport kotlinx.coroutines.reactor.ReactorContext\nimport kotlinx.coroutines.reactor.asFlux\n\nfun main() {\n    val flow = flow&lt;int&gt; {\n       println(\"Reactor context in Flow: \" +\n          currentCoroutineContext()[ReactorContext]?.context)\n    }\n\n    \/\/ No context\n    \/\/ prints \"Reactor context in Flow: null\"\n    flow.asFlux().subscribe() \n\n    \/\/ Add subscriber's context\n    \/\/ prints \"Reactor context in Flow: Context1{answer=42}\"\n    flow.asFlux()\n        .contextWrite { ctx -&gt; ctx.put(\"answer\", 42) }\n        .subscribe() \n}\n<\/pre>\n<p>\uc704\uc758 \uc608\uc5d0\uc11c\ub294 <code>Flow<\/code> \uc778\uc2a4\ud134\uc2a4\ub97c \uc0dd\uc131\ud55c \ub2e4\uc74c, \ucee8\ud14d\uc2a4\ud2b8 \uc5c6\uc774 \uc774\ub97c Reactor\uc758 Flux \uc778\uc2a4\ud134\uc2a4\ub85c \ubcc0\ud658\ud569\ub2c8\ub2e4. \uc778\uc218 \uc5c6\uc774 <code>subscribe()<\/code> \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\uba74 publisher\uc5d0\uac8c <em>\ubaa8\ub4e0<\/em> \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uc694\uccad\ud558\ub294 \ud6a8\uacfc\uac00 \uc788\uc2b5\ub2c8\ub2e4. \uacb0\uacfc\uc801\uc73c\ub85c, \ud504\ub85c\uadf8\ub7a8\uc740 &#8220;<em>Reactor context in Flow: null<\/em>&#8220;\uc774\ub77c\ub294 \ubb38\uad6c\ub97c \ucd9c\ub825\ud569\ub2c8\ub2e4.<\/p>\n<p>\ub2e4\uc74c \ud638\ucd9c \uccb4\uc778\ub3c4 <code>Flow<\/code>\ub97c <code>Flux<\/code>\ub85c \ubcc0\ud658\ud558\uc9c0\ub9cc, \uadf8 \ub2e4\uc74c\uc5d0 \uc774 \uccb4\uc778\uc5d0 \ub300\ud55c Reactor\uc758 \ucee8\ud14d\uc2a4\ud2b8\uc5d0 \ud0a4-\uac12 \uc30d <em>answer=42<\/em>\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. <code>subscribe()<\/code>\ub97c \ud638\ucd9c\ud558\uba74 \uccb4\uc778\uc774 \ud2b8\ub9ac\uac70\ub429\ub2c8\ub2e4. \uc774 \uacbd\uc6b0 \ucee8\ud14d\uc2a4\ud2b8\uac00 \ucc44\uc6cc\uc9c0\ubbc0\ub85c \ud504\ub85c\uadf8\ub7a8\uc740 \u201c<em>Reactor context in Flow: Context1{answer=42}<\/em>\u201d\ub97c \ucd9c\ub825\ud569\ub2c8\ub2e4.<\/p>\n<h2>\uc0c8\ub85c\uc6b4 \ud3b8\uc758 \ud568\uc218<\/h2>\n<p>\ucf54\ub8e8\ud2f4 \ucee8\ud14d\uc2a4\ud2b8\uc5d0\uc11c <code>Mono<\/code>\uc640 \uac19\uc740 \ubc18\uc751\ud615\uc73c\ub85c \uc791\uc5c5\ud560 \ub54c \uc2a4\ub808\ub4dc\ub97c \ucc28\ub2e8\ud558\uc9c0 \uc54a\uace0 \uac80\uc0c9\uc744 \ud5c8\uc6a9\ud558\ub294 \uba87 \uac00\uc9c0 \ud3b8\uc758 \ud568\uc218\uac00 \uc788\uc2b5\ub2c8\ub2e4. \uc774 \ub9b4\ub9ac\uc2a4\uc5d0\uc11c\ub294 \uc784\uc758\uc758 <code>Publisher<\/code>\uc5d0\uc11c <code>awaitSingleOr*<\/code> \ud568\uc218\ub97c <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/pull\/2628\" target=\"_blank\" rel=\"noopener\">\uc9c0\uc6d0 \uc911\ub2e8<\/a>\ud588\uc73c\uba70 <code>Mono<\/code> \ubc0f <code>Maybe<\/code>\uc5d0 \ub300\ud574 \uc77c\ubd80 <code>await*<\/code> \ud568\uc218\ub97c \ud2b9\uc218\ud654\ud588\uc2b5\ub2c8\ub2e4.<\/p>\n<p><code>Mono<\/code>\ub294 \ucd5c\ub300 \ud558\ub098\uc758 \uac12\uc744 \uc0dd\uc131\ud558\ubbc0\ub85c \ub9c8\uc9c0\ub9c9 \uc694\uc18c\ub294 \uccab \ubc88\uc9f8 \uc694\uc18c\uc640 \ub3d9\uc77c\ud569\ub2c8\ub2e4. \uc774 \uacbd\uc6b0 \ub098\uba38\uc9c0 \uc694\uc18c\ub97c \uc0ad\uc81c\ud560 \ub54c\uc758 \uc758\ubbf8\ub3c4 \uc720\uc6a9\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \ub530\ub77c\uc11c <code>Mono.awaitFirst()<\/code> \ubc0f <code>Mono.awaitLast()<\/code>\uc5d0 \ub300\ud55c \uc9c0\uc6d0\uc774 \uc911\ub2e8\ub418\uace0 <code>Mono.awaitSingle()<\/code>\uc774 \uc0ac\uc6a9\ub429\ub2c8\ub2e4.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"906\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/05\/cor15-reactive-streams-awaitFirst.png\" alt=\"\" class=\"wp-image-142647\"><\/figure>\n<h1 id=\"use-coroutines-1-5-0\">kotlinx.coroutines 1.5.0\uc744 \uc0ac\uc6a9\ud574 \ubcf4\uc138\uc694!<\/h1>\n<p>\uc0c8 \ub9b4\ub9ac\uc2a4\uc5d0\ub294 \ub180\ub77c\uc6b8 \uc815\ub3c4\ub85c \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc801\uc6a9\ub418\uc5c8\uc2b5\ub2c8\ub2e4. Channels API\ub97c \uac1c\uc120\ud558\ub294 \ub3d9\uc548 \uac1c\ubc1c\ub41c \uc0c8\ub85c\uc6b4 \uc774\ub984 \uc9c0\uc815 \uccb4\uacc4\ub294 \uc8fc\ubaa9\ud560 \ub9cc\ud55c \uc131\uacfc\uc785\ub2c8\ub2e4. \ud55c\ud3b8, Coroutines API\ub97c \ucd5c\ub300\ud55c \ub2e8\uc21c\ud558\uace0 \uc9c1\uad00\uc801\uc73c\ub85c \ub9cc\ub4dc\ub294 \ub370 \uc911\uc810\uc744 \ub450\uace0 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc0c8 \ubc84\uc804\uc758 Kotlin \ucf54\ub8e8\ud2f4 \uc0ac\uc6a9\uc744 \uc2dc\uc791\ud558\ub824\uba74 build.gradle.kts \ud30c\uc77c\uc758 \ucf58\ud150\uce20\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uae30\ub9cc \ud558\uba74 \ub429\ub2c8\ub2e4. \uba3c\uc800, \ucd5c\uc2e0 \ubc84\uc804\uc758 Kotlin Gradle \ud50c\ub7ec\uadf8\uc778\uc774 \uc788\ub294\uc9c0 \ud655\uc778\ud574 \uc8fc\uc138\uc694.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">plugins {\n   kotlin(\"jvm\") version \"1.5.0\"\n}\n<\/pre>\n<p>\uadf8\ub7f0 \ub2e4\uc74c Reactive Streams\uc5d0 \ub300\ud55c \ud2b9\uc815\ud55c \ud1b5\ud569\uc774 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \ud3ec\ud568\ud558\uc5ec \uc885\uc18d\uc131 \ubc84\uc804\uc744 \uc5c5\ub370\uc774\ud2b8\ud558\uc138\uc694.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">val coroutinesVersion = \"1.5.0\"\n\ndependencies { \n  implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:$coroutinesVersion\")\n  implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-reactive:$coroutinesVersion\")\n  implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$coroutinesVersion\")\n  implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-rx3:$coroutinesVersion\")\n  ...\n}\n<\/pre>\n<h1>\ub3d9\uc601\uc0c1 \ubc0f \uc77d\uc744\uac70\ub9ac<\/h1>\n<ul>\n<li><a href=\"https:\/\/youtu.be\/EVLnWOcR0is\" class=\"ek-link\" target=\"_blank\" rel=\"noopener\">Kotlin Coroutines 1.5.0 \ub3d9\uc601\uc0c1<\/a><\/li>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/coroutines-guide.html\" target=\"_blank\" rel=\"noopener\">\ucf54\ub8e8\ud2f4 \uac00\uc774\ub4dc<\/a><\/li>\n<li><a href=\"https:\/\/kotlin.github.io\/kotlinx.coroutines\/\" target=\"_blank\" rel=\"noopener\">API \ubb38\uc11c<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\" target=\"_blank\" rel=\"noopener\">Kotlin \ucf54\ub8e8\ud2f4 GitHub \uc800\uc7a5\uc18c<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2020\/10\/kotlinx-coroutines-1-4-0-introducing-stateflow-and-sharedflow\/\" class=\"ek-link\">\ucf54\ub8e8\ud2f4 1.4.0 \ube14\ub85c\uadf8 \uac8c\uc2dc\ubb3c<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/05\/kotlin-1-5-0-released\/\" class=\"ek-link\">Kotlin 1.5.0 \ube14\ub85c\uadf8 \uac8c\uc2dc\ubb3c<\/a><\/li>\n<\/ul>\n<h3>\ubb38\uc81c\uac00 \uc788\ub294 \uacbd\uc6b0,<\/h3>\n<ul>\n<li><a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/issues\" target=\"_blank\" rel=\"noopener\">GitHub \uc774\uc288 \ud2b8\ub798\ucee4<\/a>\uc5d0 \uc774\uc288\ub97c \ubcf4\uace0\ud574 \uc8fc\uc138\uc694.<\/li>\n<li>Kotlin Slack\uc758 #coroutines \ucc44\ub110\uc5d0\uc11c \ub3c4\uc6c0\uc744 \uc694\uccad\ud558\uc138\uc694(<a href=\"https:\/\/surveys.jetbrains.com\/s3\/kotlin-slack-sign-up\" target=\"_blank\" rel=\"noopener\">\ucd08\ub300 \ubc1b\uae30<\/a>).<\/li>\n<\/ul>\n<p><em>\uc774 \uac8c\uc2dc\ubb3c\uc740 <a href=\"https:\/\/blog.jetbrains.com\/author\/antonarhipov\/\">Anton Arhipov<\/a>\uac00 \uc791\uc131\ud55c <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/05\/kotlin-coroutines-1-5-0-released\/\">Kotlin Coroutines 1.5: GlobalScope Marked as Delicate, Refined Channels API, and More<\/a>\ub97c \ubc88\uc5ed\ud55c \uae00\uc785\ub2c8\ub2e4.<br \/>\n<\/em><\/p>\n","protected":false},"author":964,"featured_media":142996,"comment_status":"closed","ping_status":"closed","template":"","categories":[909],"tags":[],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/kotlin\/151612"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/users\/964"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/comments?post=151612"}],"version-history":[{"count":3,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/kotlin\/151612\/revisions"}],"predecessor-version":[{"id":151637,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/kotlin\/151612\/revisions\/151637"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/media\/142996"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/media?parent=151612"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/categories?post=151612"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/tags?post=151612"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/cross-post-tag?post=151612"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}