{"id":230339,"date":"2022-02-17T07:40:08","date_gmt":"2022-02-17T06:40:08","guid":{"rendered":"https:\/\/blog.jetbrains.com\/kotlin\/2022\/01\/the-new-aws-sdk-for-kotlin-with-coroutines-support\/"},"modified":"2022-02-17T08:01:33","modified_gmt":"2022-02-17T07:01:33","slug":"the-new-aws-sdk-for-kotlin-with-coroutines-support","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/ko\/kotlin\/2022\/02\/the-new-aws-sdk-for-kotlin-with-coroutines-support\/","title":{"rendered":"\ucf54\ub8e8\ud2f4\uc744 \uc9c0\uc6d0\ud558\ub294 \uc0c8\ub85c\uc6b4 Kotlin\uc6a9 AWS SDK"},"content":{"rendered":"<p>\uc0c8\ub85c\uc6b4 Kotlin\uc6a9 AWS SDK\uac00 2021\ub144 12\uc6d4 AWS re:Invent\uc5d0\uc11c \ubc1c\ud45c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \uc774 SDK\ub97c \uc0ac\uc6a9\ud558\uba74 Amazon S3, Amazon EC2, DynamoDB \ub4f1\uacfc \ud568\uaed8 \uc791\ub3d9\ud558\ub294 Kotlin \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube4c\ub4dc\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774 SDK\ub294 \ud604\uc7ac \ud14c\uc2a4\ud2b8 \uc911\uc774\uba70 \uace7 \uc548\uc815\ud654 \ubc84\uc804\uc73c\ub85c \uc81c\uacf5\ub420 \uc608\uc815\uc785\ub2c8\ub2e4.<\/p>\n<p>\uc774 SDK\ub294 \ucc98\uc74c\ubd80\ud130 Kotlin \uc5b8\uc5b4 \ubc0f \ubaa8\ubc94 \uc0ac\ub840\ub97c \uc9c0\uc6d0\ud558\ub3c4\ub85d \uc124\uacc4\ub418\uc5b4 Kotlin \uac1c\ubc1c\uc790\uc5d0\uac8c \uc775\uc219\ud558\uace0 \uad00\ub840\uc801\uc778 AWS \uc0c1\ud638\uc791\uc6a9 \uacbd\ud5d8\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \uc774 SDK\ub294 \ube44\ub3d9\uae30 \uad6c\ud604\uc744 \uc704\ud574 Kotlin \ucf54\ub8e8\ud2f4\uc744 \ud65c\uc6a9\ud558\uba70 Kotlin \uba40\ud2f0\ud50c\ub7ab\ud3fc \ud504\ub85c\uc81d\ud2b8\uc640 \ud638\ud658\ub418\ub3c4\ub85d \ud560 \uacc4\ud68d\uc785\ub2c8\ub2e4.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-221785\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2022\/01\/AWS-SDK-for-Kotlin_Twitter-Blog.png\" alt=\"\" width=\"800\" height=\"418\"><\/figure>\n<p>Kotlin \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc0c8 SDK\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ud504\ub85c\uc81d\ud2b8\uc5d0 \ud574\ub2f9 \uc885\uc18d \uc694\uc18c\ub97c \ucd94\uac00\ud574\uc57c \ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4 DynamoDB\uc640 \ud1b5\uc2e0\ud558\ub824\uba74 <code>aws.sdk.kotlin:dynamodb<\/code> \ubaa8\ub4c8\uc774 \ud544\uc694\ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" style=\"visibility: hidden; padding: 36px 0;\" data-highlight-only=\"true\">repositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0\")\n    \n    \/\/ The following line adds a dependency on the dynamodb client.\n    \/\/ For demonstration purposes, we use 0.+ to get the latest version\n    implementation(\"aws.sdk.kotlin:dynamodb:0.+\")\n}\n<\/pre>\n<p>\uc9c0\uc6d0\ub418\ub294 \ubaa8\ub4c8\uc758 \uc804\uccb4 \ubaa9\ub85d\uc740 <a href=\"https:\/\/docs.aws.amazon.com\/sdk-for-kotlin\/latest\/reference\/\" target=\"_blank\" rel=\"noopener\">AWS SDK \ubb38\uc11c<\/a>\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc885\uc18d \uc694\uc18c\ub97c \ub2e4\uc6b4\ub85c\ub4dc\ud558\uba74 API\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"kotlin-code\" style=\"visibility: hidden; padding: 36px 0;\" data-highlight-only=\"true\">import kotlinx.coroutines.runBlocking\nimport aws.sdk.kotlin.services.dynamodb.DynamoDbClient\n\/\/sampleStart \nfun main() = runBlocking {\n    val client = DynamoDbClient { region = \"us-east-2\" }\n    val resp = client.listTables { limit = 10 }\n\n    println(\"Current DynamoDB tables: \")\n    resp.tableNames?.forEach { println(it) }\n\n    client.close()\n}\n\/\/sampleEnd \n<\/pre>\n<p>\uc774 \ud504\ub85c\uadf8\ub7a8\uc740 \ub2e8\uc21c\ud788 \ud14c\uc774\ube14 \ubaa9\ub85d\uc744 \uac80\uc0c9\ud558\uace0 \ud14c\uc774\ube14 \uc774\ub984\uc744 \ud45c\uc900 \ucd9c\ub825\uc73c\ub85c \uc778\uc1c4\ud569\ub2c8\ub2e4. \uc704\uc758 \uc608\uc2dc\uc5d0\uc11c <code>listTables<\/code>\ub294 \uc77c\uc2dc \uc911\uc9c0 \ud568\uc218\uc774\ubbc0\ub85c \ucf54\ub4dc\ub294 <code>runBlocking<\/code> \ud638\ucd9c\ub85c \ub798\ud551\ub429\ub2c8\ub2e4.<\/p>\n<p>\ud398\uc774\uc9c0 \uc9c0\uc815\ub41c \uc561\uc138\uc2a4, \ub3d9\uc2dc \ud750\ub984 \ubc0f \ubc14\uc774\ud2b8 \uc2a4\ud2b8\ub9ac\ubc0d \uc751\ub2f5\uc744 \uc544\uc6b8\ub7ec \ubaa8\ub4e0 S3 \uac1d\uccb4\ub97c \ud558\ub098\uc758 \ubc84\ud0b7\uc5d0 \ub2f4\uc544 \ub85c\uceec \uc784\uc2dc \ub514\ub809\ud130\ub9ac\ub85c \ub2e4\uc6b4\ub85c\ub4dc\ud558\ub294 \ubc29\ubc95\uc744 \ubcf4\uc5ec\uc8fc\ub294 \uc57d\uac04 \ub354 \ubcf5\uc7a1\ud55c \uc608\uc2dc\ub294 \uc5b4\ub5a8\uae4c\uc694?<\/p>\n<pre class=\"kotlin-code\" style=\"visibility: hidden; padding: 36px 0;\" data-highlight-only=\"true\">import aws.sdk.kotlin.services.s3.S3Client\nimport aws.sdk.kotlin.services.s3.model.GetObjectRequest\nimport aws.sdk.kotlin.services.s3.model.ListObjectsV2Request\nimport aws.sdk.kotlin.services.s3.paginators.listObjectsV2Paginated\nimport aws.smithy.kotlin.runtime.content.writeToFile\nimport kotlinx.coroutines.flow.asFlow\nimport kotlinx.coroutines.flow.filter\nimport kotlinx.coroutines.flow.flatMapConcat\nimport kotlinx.coroutines.flow.flowOf\nimport java.nio.file.Paths\nimport kotlin.io.path.createDirectories\n\/\/sampleStart \nsuspend fun downloadAllS3Objects(bucketName: String) {\n   val s3 = S3Client.fromEnvironment()\n   val listReq = ListObjectsV2Request {\n       bucket = bucketName\n   }\n   s3.listObjectsV2Paginated(listReq)\n       .flatMapConcat { it.contents?.asFlow() ?: flowOf() }\n       .filter { it.size &gt; 0 }\n       .collect { obj -&gt;                     \n           val getReq = GetObjectRequest {\n               bucket = bucketName\n               key = obj.key\n           }\n           s3.getObject(getReq) {\n               val path = Paths.get(System.getProperty(\"java.io.tmpdir\"), obj.key)\n               path.parent.createDirectories()\n               it.body?.writeToFile(path)\n           }\n       }\n}\n\/\/sampleEnd\n<\/pre>\n<p>\uc704\uc758 \uc608\uc2dc\uc5d0\uc11c\ub294 SDK\uc758 \uc77c\uc2dc \uc911\uc9c0 \ud568\uc218\uc758 \uc6a9\ub840\ub97c \ub2e4\uc2dc \ud55c \ubc88 \ud655\uc778\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc5ec\uae30\uc11c <code>getObject<\/code> \ubc0f <code>writeToFile<\/code> \ud568\uc218\ub294 \ubaa8\ub450 <code>suspend<\/code> \ud0a4\uc6cc\ub4dc\ub85c \ud45c\uc2dc\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc0c8\ub85c\uc6b4 Kotlin\uc6a9 AWS SDK\uc758 \uacf5\uc2dd \ubb38\uc11c\uc5d0\uc11c <a href=\"https:\/\/docs.aws.amazon.com\/sdk-for-kotlin\/latest\/developer-guide\/get-started.html\" target=\"_blank\" rel=\"noopener\">\uc2dc\uc791\ud558\ub294 \ubc29\ubc95<\/a>\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \ub2e8\uacc4\ubcc4 \uc9c0\uce68\uc744 \ucc3e\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ub610\ud55c Amazon DynamoDB, S3, Rekognition, Amazon Simple Notification Service \ubc0f AWS Key Management Service\uc640 \uac19\uc740 \uc5ec\ub7ec AWS \uc11c\ube44\uc2a4\uc5d0\uc11c API\uc758 \uc0ac\uc6a9\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud765\ubbf8\ub85c\uc6b4 <a href=\"https:\/\/docs.aws.amazon.com\/sdk-for-kotlin\/latest\/developer-guide\/examples.html\" target=\"_blank\" rel=\"noopener\">\uc608\uc2dc<\/a>\ub3c4 \ub9ce\uc774 \ucc3e\uc544\ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc0c8\ub85c\uc6b4 Kotlin\uc6a9 AWS SDK\ub294 \ud604\uc7ac \uac1c\ubc1c \uc911\uc774\uba70 <a href=\"https:\/\/github.com\/awslabs\/aws-sdk-kotlin\/projects\/2\" target=\"_blank\" rel=\"noopener\">\ub85c\ub4dc\ub9f5<\/a>\uc5d0\uc11c \uc5b4\ub5a4 \uae30\ub2a5\ub4e4\uc774 \uacc4\ud68d\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc9c0\uae08 \uc0ac\uc6a9\ud574 \ubcf4\uace0 \uc758\uacac\uc744 \uacf5\uc720\ud574 \uc8fc\uc138\uc694!<\/p>\n<p><em>\uac8c\uc2dc\ubb3c \uc6d0\ubb38 \uc791\uc131\uc790<\/em><\/p>\n\n    <div class=\"about-author \">\n        <div class=\"about-author__box\">\n            <div class=\"row\">\n                <div class=\"about-author__box-img\">\n                    <img decoding=\"async\" src=\"https:\/\/secure.gravatar.com\/avatar\/?s=200&#038;r=g\" width=\"200\" height=\"200\" alt=\"\" loading=\"lazy\"  class=\"avatar avatar-200 wp-user-avatar wp-user-avatar-200 photo avatar-default\">\n                <\/div>\n                <div class=\"about-author__box-text\">\n                                                        <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n","protected":false},"author":964,"featured_media":221802,"comment_status":"closed","ping_status":"closed","template":"","categories":[89],"tags":[1041,6850,21,4975],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/kotlin\/230339"}],"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=230339"}],"version-history":[{"count":5,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/kotlin\/230339\/revisions"}],"predecessor-version":[{"id":230347,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/kotlin\/230339\/revisions\/230347"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/media\/221802"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/media?parent=230339"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/categories?post=230339"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/tags?post=230339"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ko\/wp-json\/wp\/v2\/cross-post-tag?post=230339"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}