{"id":3939,"date":"2026-07-29T07:30:00","date_gmt":"2026-07-28T22:30:00","guid":{"rendered":"https:\/\/www.litcoder.com\/?p=3939"},"modified":"2026-07-26T13:31:45","modified_gmt":"2026-07-26T04:31:45","slug":"grpc-streaming%ec%9c%bc%eb%a1%9c-%ec%83%81%ed%83%9c-%ec%a0%84%ec%86%a1-%eb%b0%9b%ea%b8%b0-%ec%98%88%ec%a0%9c","status":"publish","type":"post","link":"https:\/\/litcoder.com\/?p=3939","title":{"rendered":"gRPC Streaming\uc73c\ub85c \uc0c1\ud0dc \uc804\uc1a1 \ubc1b\uae30 \uc608\uc81c"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">gRPC\uc5d0\uc11c Observer pattern\uc744 \uad6c\ud604\ud558\ub294 \uc608\uc81c\ub97c \uace0\ubbfc\ud588\ub358 \uc801\uc774 \uc788\uc5c8\ub294\ub370(<a href=\"https:\/\/litcoder.com\/?p=3509\" data-type=\"link\" data-id=\"https:\/\/litcoder.com\/?p=3509\">gRPC\ub97c \uc774\uc6a9\ud55c Observer Pattern<\/a>) \uc54c\uace0\ubcf4\ub2c8 gRPC\uc5d0\uc11c\ub294 ReadReactor \/ WriteReactor \ubcf4\ub2e4 \uac04\ub2e8\ud558\uac8c object\uc758 \uc0c1\ud0dc \ubcc0\uacbd\uc744 \uac10\uc9c0\ud560 \uc218 \uc788\ub294 \uba54\ucee4\ub2c8\uc998\uc744 \uc81c\uacf5\ud558\uace0 \uc788\uc5c8\ub2e4. gRPC\ub97c \uc774\uc6a9\ud55c Observer pattern \uad6c\ud604 \uc608\uc81c\ub97c \ucc3e\uae30 \uc5b4\ub824\uc6e0\ub358 \uc774\uc720\uac00 \uc5b4\uca4c\uba74 \uadf8\ub7f0 \ubcf5\uc7a1\ud55c \ud328\ud134 \uc5c6\uc774\ub3c4 \uad6c\ud604\uc774 \uac00\ub2a5\ud558\uae30 \ub54c\ubb38\uc774\uc5c8\ub294\uc9c0\ub3c4 \ubaa8\ub974\uaca0\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 Stream\uc744 \ud1b5\ud574 \ubcc0\uacbd\ub418\ub294 \uac12\ub4e4\uc744 subscribe\ud558\ub294 \uac04\ub2e8\ud55c \uc608\uc81c\ub97c Rust\ub85c \uad6c\ud604\ud574 \ubcf8\ub2e4. gRPC\uc758 Rust \uad6c\ud604\uccb4\uc778 <code>tonic<\/code>\uacfc proto compiler\uc778 <code>prost<\/code>, \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uc704\ud574 <code>tokio<\/code>\ub97c \uc0ac\uc6a9\ud588\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Proto file &#8211; stockprice.proto<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\ub79c\ub364\ud558\uac8c \uc0dd\uc131\ub41c \uc8fc\uac00 \uc815\ubcf4\ub97c gRPC\ub85c \uad6c\ub3c5\ud558\ub294 \uac04\ub2e8\ud55c \uc11c\ube44\uc2a4 \uc608\uc81c\ub97c \uac00\uc815\ud574 \ubcf4\uc790. Proto file\uc740 <code>UpdateStockPrice()<\/code>\ub97c \uc815\uc758\ud558\uace0 \ud638\ucd9c\ub418\uba74 <code>StockPriceResponse<\/code>\uc758 stream\uc744 \ubc1b\uc544\uc624\ub3c4\ub85d \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\uc131\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">syntax = \"proto3\";\npackage stockservice;\n\nimport \"google\/protobuf\/empty.proto\";\n\nmessage StockPriceResponse {\n    string symbol = 1;\n    double price = 2;\n    uint64 sequence = 3;\n}\n\nservice StockService {\n    rpc UpdateStockPrice(google.protobuf.Empty) returns (stream StockPriceResponse);\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Server<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><code>StockServiceImpl<\/code> \uad6c\uc870\uccb4\ub97c \uc120\uc5b8\ud558\uace0 \uc11c\ube44\uc2a4\ub97c \uc81c\uacf5\ud558\uae30 \uc704\ud55c <code>StockService<\/code>\ub97c \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud604\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"false\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ Server \uad6c\ud604\uccb4\nstruct StockServiceImpl;\n\n\/\/ tokio_stream\uc744 \uc774\uc6a9\ud574\uc11c gRPC stream\uc744 \uad6c\ud604.\ntype StockStream = Pin&lt;Box&lt;dyn Stream&lt;Item = Result&lt;StockPriceResponse, Status>> + Send>>;\n\n#[tonic::async_trait]\nimpl StockService for StockServiceImpl {\n    type UpdateStockPriceStream = StockStream;\n\n    async fn update_stock_price(\n        &amp;self,\n        _request: Request&lt;()>,\n    ) -> Result&lt;Response&lt;Self::UpdateStockPriceStream>, Status> {\n\n        \/\/ 1\ucd08 \uac04\uaca9\uc73c\ub85c stock price \uc0dd\uc131\n        let mut interval = tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(\n            Duration::from_secs(1),\n        ));\n\n        \/\/ Stream\uc73c\ub85c \uc804\uc1a1\ud560 \ub370\uc774\ud130\ub97c \uc0dd\uc131\ud558\uace0 yield\ub85c \ubc18\ud658.\n        let output = async_stream::stream! {\n            let mut rng = SmallRng::from_os_rng();\n            let mut sequence: u64 = 0;\n\n            \/\/ \ub9e4 interval\ub9c8\ub2e4 \uc21c\ubc88\uc744 \uc99d\uac00\uc2dc\ud0a4\uace0 \ub79c\ub364 \uc8fc\uac00\ub97c \uc0dd\uc131\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\ub85c \uc804\uc1a1\n            while interval.next().await.is_some() {\n                sequence += 1;\n                let p = generate_stock_price(&amp;mut rng, sequence);\n                yield Ok(p);\n            }\n        };\n\n        Ok(Response::new(\n            Box::pin(output) as Self::UpdateStockPriceStream\n        ))\n    }\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \ucf54\ub4dc\uc5d0\uc11c \ud575\uc2ec\uc740 <code>async_stream::stream!()<\/code> \ub9e4\ud06c\ub85c\ub85c \ub370\uc774\ud130\ub97c \uc804\uc1a1\ud560 \ub370\uc774\ud130\uc784\uc744 \uc815\uc758\ud558\uace0, <code>while \/ yeild<\/code>\ub85c data\ub97c \uc804\uc1a1\ud558\ub294 \ub2e4\uc74c\uc758 \ubd80\ubd84\uc774\ub2e4. \uc774 \ubd80\ubd84\uc5d0\uc11c \ub370\uc774\ud130\ub97c \uac31\uc2e0\ud558\uace0 stream\uc5d0 \uc9c0\uc18d\uc801\uc73c\ub85c update \uc2dc\ud0a8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"false\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">        let output = async_stream::stream! {\n           ...\n\n            \/\/ \ub9e4 interval\ub9c8\ub2e4 \uc21c\ubc88\uc744 \uc99d\uac00\uc2dc\ud0a4\uace0 \ub79c\ub364 \uc8fc\uac00\ub97c \uc0dd\uc131\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\ub85c \uc804\uc1a1\n            while interval.next().await.is_some() {\n                \/\/ Data \uc0dd\uc131 \ubc0f \uc804\uc1a1\n                ...\n                yield Ok(p);\n            }\n        };<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Client<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Server\uc5d0 \ube44\ud574 Client \ucabd\uc740 \ube44\uad50\uc801 \uad6c\ud604\uc774 \uac04\ub2e8\ud55c\ub370, <code>prost<\/code>\uac00 proto file\ub85c \ubd80\ud130 \uc0dd\uc131\ud574 \uc900 <code>StockServiceClient<\/code>\ub97c \uc774\uc6a9\ud574\uc11c stream\uc744 \uc0dd\uc131\ud558\uace0, \uc774 \ub54c \ubc18\ud658\ubc1b\uc740 <code>stream<\/code>\uc73c\ub85c \ubd80\ud130 \uacc4\uc18d \ub370\uc774\ud130\ub97c \uc77d\uc5b4 \uc8fc\uba74\ub41c\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"false\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#[tokio::main]\nasync fn main() -> Result&lt;(), Box&lt;dyn Error>> {\n    let mut client = StockServiceClient::connect(\"http:\/\/[::1]:50051\").await?;\n\n    \/\/ grpc \uc11c\ube44\uc2a4 stream \uc0dd\uc131.\n    let mut stream = client\n        .update_stock_price(Request::new(()))\n        .await?\n        .into_inner();\n\n    \/\/ stream\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubc1b\uc544\uc11c \ud654\uba74\uc5d0 \ucd9c\ub825.\n    while let Some(update) = stream.message().await? {\n        println!(\n            \"[{}] {}: {:.2}\",\n            update.sequence, update.symbol, update.price\n        );\n    }\n\n    Ok(())\n}\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\ucf54\ub4dc \uc704\uce58 \ubc0f \uc218\ud589\uacb0\uacfc<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uc804\uccb4 \uad6c\ud604 \ucf54\ub4dc\ub294 \ub2e4\uc74c \uc704\uce58\uc5d0 \uc788\ub2e4. <a href=\"https:\/\/github.com\/litcoder\/grpcobsr\/tree\/stream_rust\">https:\/\/github.com\/litcoder\/grpcobsr\/tree\/stream_rust<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"865\" height=\"636\" src=\"https:\/\/litcoder.com\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-10-at-6.34.33-PM.png\" alt=\"\" class=\"wp-image-4622\" srcset=\"https:\/\/litcoder.com\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-10-at-6.34.33-PM.png 865w, https:\/\/litcoder.com\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-10-at-6.34.33-PM-300x221.png 300w, https:\/\/litcoder.com\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-10-at-6.34.33-PM-768x565.png 768w, https:\/\/litcoder.com\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-10-at-6.34.33-PM-624x459.png 624w\" sizes=\"auto, (max-width: 865px) 100vw, 865px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>gRPC\uc5d0\uc11c Observer pattern\uc744 \uad6c\ud604\ud558\ub294 \uc608\uc81c\ub97c \uace0\ubbfc\ud588\ub358 \uc801\uc774 \uc788\uc5c8\ub294\ub370(gRPC\ub97c \uc774\uc6a9\ud55c Observer Pattern) \uc54c\uace0\ubcf4\ub2c8 gRPC\uc5d0\uc11c\ub294 ReadReactor \/ WriteReactor \ubcf4\ub2e4 \uac04\ub2e8\ud558\uac8c object\uc758 \uc0c1\ud0dc \ubcc0\uacbd\uc744 \uac10\uc9c0\ud560 \uc218 \uc788\ub294 \uba54\ucee4\ub2c8\uc998\uc744 \uc81c\uacf5\ud558\uace0 \uc788\uc5c8\ub2e4. gRPC\ub97c \uc774\uc6a9\ud55c Observer pattern \uad6c\ud604 \uc608\uc81c\ub97c \ucc3e\uae30 \uc5b4\ub824\uc6e0\ub358 \uc774\uc720\uac00 \uc5b4\uca4c\uba74 \uadf8\ub7f0 \ubcf5\uc7a1\ud55c \ud328\ud134 \uc5c6\uc774\ub3c4 \uad6c\ud604\uc774 \uac00\ub2a5\ud558\uae30 \ub54c\ubb38\uc774\uc5c8\ub294\uc9c0\ub3c4 \ubaa8\ub974\uaca0\ub2e4. \uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 Stream\uc744 \ud1b5\ud574 \ubcc0\uacbd\ub418\ub294 \uac12\ub4e4\uc744 subscribe\ud558\ub294 \uac04\ub2e8\ud55c \uc608\uc81c\ub97c Rust\ub85c [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[5],"tags":[330,423,456],"class_list":["post-3939","post","type-post","status-publish","format-standard","hentry","category-programming","tag-grpc","tag-rust","tag-stream"],"jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":3509,"url":"https:\/\/litcoder.com\/?p=3509","url_meta":{"origin":3939,"position":0},"title":"gRPC\ub97c \uc774\uc6a9\ud55c Observer Pattern","author":"litcoder","date":"2024\ub144 10\uc6d4 14\uc77c","format":false,"excerpt":"Remote\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uae30\ub2a5\uc744 \ub9c8\uce58 local system\uc758 function call \ucc98\ub7fc \uc81c\uacf5 \ud55c\ub2e4\ub294 gRPC\uc758 \uac1c\ub150 \uc790\uccb4\ub294 1990\ub144\ub300\uc5d0\ub3c4 \uc788\uc5c8\ub358 \uac83\uc774\uae30\uc5d0 \uc0c8\ub85c\uc6b8 \uac83\uc740 \uc5c6\uc9c0\ub9cc, \uadf8 \uc704\uc5d0\uc11c \"Subject\uc758 \ubcc0\uacbd\uc774 \uc788\uc744 \ub54c subscriber\uc5d0\uac8c notify \ud574\uc8fc\ub294 Observer Pattern\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604 \ud560 \uc218 \uc788\uc744\uae4c?\"\ud558\ub294 \uc758\ubb38\uc774 \ub4e4\uc5c8\ub2e4. \uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 gRPC\ub97c \uc774\uc6a9\ud55c observer pattern\uc758 \uc608\uc81c\ub85c server\uc5d0\uc11c \uc784\uc758\uc758 \uc8fc\uc2dd\uacfc \uadf8 \ubcc0\ub3d9\u2026","rel":"","context":"&quot;Programming&quot;\uc5d0\uc11c","block_context":{"text":"Programming","link":"https:\/\/litcoder.com\/?cat=5"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2024\/10\/grpc_observer.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2024\/10\/grpc_observer.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2024\/10\/grpc_observer.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2024\/10\/grpc_observer.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":4673,"url":"https:\/\/litcoder.com\/?p=4673","url_meta":{"origin":3939,"position":1},"title":"Rust: pbjson crate\uc5d0\uc11c &#8220;redundant reference&#8221; \uacbd\uace0","author":"litcoder","date":"2026\ub144 8\uc6d4 26\uc77c","format":false,"excerpt":"\ub85c\uceec\uc5d0\uc11c lint \uac80\uc0ac \uae4c\uc9c0 \ub9c8\uce58\uace0 \uc11c\ubc84\ub85c push \ud588\ub294\ub370, \ub85c\uceec\uc5d0\uc11c \ubcf4\uc774\uc9c0 \uc54a\uc558\ub358 \"redundant referece\" \uacbd\uace0\uac00 \ub728\uba74\uc11c clippy\ub97c \uc218\ud589\ud558\ub294 Rust\uc6a9 CI\uac00 \uc2e4\ud328 \ud588\ub2e4. \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c Rust\uc6a9 CI\ub294 \uacbd\uace0\ub9cc \ub5a0\ub3c4 \uc2e4\ud328\ub85c \uac04\uc8fc\ud558\ub294 -D warnings \ud30c\ub77c\ubbf8\ud130\ub97c \uc124\uc815\ud558\uace0 \uc788\ub294\ub370 \uc774\uac83 \ub54c\ubb38\uc5d0 CI \uc804\uccb4\uac00 \uc2e4\ud328\ud558\ub294 \ubb38\uc81c\uac00 \uc0dd\uacbc\ub2e4. \ub85c\uceec\uacfc\uc758 \ucc28\uc774\uc810\uc744 \uc0b4\ud3b4 \ubcf4\ub2c8, local\uc5d0\uc11c\ub294 Cargo 1.94.1 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud558\ub294\ub370\u2026","rel":"","context":"&quot;Programming&quot;\uc5d0\uc11c","block_context":{"text":"Programming","link":"https:\/\/litcoder.com\/?cat=5"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/sc_rust_redundant_reference.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/sc_rust_redundant_reference.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/sc_rust_redundant_reference.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/sc_rust_redundant_reference.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":3457,"url":"https:\/\/litcoder.com\/?p=3457","url_meta":{"origin":3939,"position":2},"title":"CMake FetchContent\uc758 target\uc774 \uc911\ubcf5\ub418\ub294 \ubb38\uc81c","author":"litcoder","date":"2024\ub144 9\uc6d4 8\uc77c","format":false,"excerpt":"CMake\uc758 FetchContent\ub294 \ube4c\ub4dc \uacfc\uc815\uae4c\uc9c0 \ucc98\ub9ac\ud574 \uc8fc\uae30\uc5d0 git-submodule \ubcf4\ub2e4 \ud3b8\ub9ac\ud55c \ubc29\uc2dd\uc778 \uac83 \uac19\ub2e4. \ub2e4\ub9cc, version 3.22.1 \uae30\uc900\uc73c\ub85c \uc5ec\ub7ec \ud504\ub85c\uc81d\ud2b8 \ub4e4\uc774 \ub3d9\uc77c\ud55c target\uc774\ub984\uc744 \uc911\ubcf5\ud574\uc11c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \uc774\ub97c \uc798 \ucc98\ub9ac \ud558\uc9c0 \ubabb\ud558\uace0 \uc704\uc640 \uac19\uc740 \uc5d0\ub7ec\ub97c \ubc49\uace0 \uc885\ub8cc\ub418\ub294 \ubb38\uc81c\uac00 \uc788\ub2e4. -- Found systemd via pkg-config. CMake Error at build\/_deps\/grpc-src\/CMakeLists.txt:667 (add_custom_target): add_custom_target cannot create target\u2026","rel":"","context":"&quot;Tools &amp; Tips&quot;\uc5d0\uc11c","block_context":{"text":"Tools &amp; Tips","link":"https:\/\/litcoder.com\/?cat=6"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4654,"url":"https:\/\/litcoder.com\/?p=4654","url_meta":{"origin":3939,"position":3},"title":"PyO3\ub85c Rust code\uc5d0\uc11c Python module \uc0ac\uc6a9\ud558\uae30","author":"litcoder","date":"2026\ub144 8\uc6d4 19\uc77c","format":false,"excerpt":"PyO3\ub97c \uc774\uc6a9\ud558\uba74 Rust\uc5d0\uc11c Python\uc744 \ud638\ucd9c\ud558\uac70\ub098 \ubc18\ub300\ub85c Python\uc5d0\uc11c Rust\ub97c \ud638\ucd9c\ud558\ub294 \ubc14\uc778\ub529\uc744 \uad6c\ud604\ud560 \uc218 \uc788\ub2e4. \uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 \uc608\uc804\uc5d0 \ud574\ubd24\ub358 Datumaro\ub85c \ub370\uc774\ud130\uc14b\uc744 detect\ud558\ub294 Python\ud568\uc218\ub97c Rust\ub85c \ud638\ucd9c\ud558\ub294 \uc608\uc81c\ub97c \uad6c\ud604\ud574 \ubcf8\ub2e4. Python \uc758\uc874\uc124 \uc124\uce58 Python \uad00\ub828\ud55c \uc758\uc874\uc131\uc740 \uc608\uc804\uacfc \uac19\uc774 Datumaro\ub97c \uc0ac\uc6a9\ud558\ub294\ub370 \ud544\uc694\ud55c \uac83\ub4e4\uc744 \uc124\uce58\ud574 \uc900\ub2e4. pip install 'datumaro[tf,tfds]' \\ tensorboardX \\ tensorflow-dataset \\ importlib_resources \\\u2026","rel":"","context":"&quot;Programming&quot;\uc5d0\uc11c","block_context":{"text":"Programming","link":"https:\/\/litcoder.com\/?cat=5"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/07\/sc_dsdetect_rust.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/07\/sc_dsdetect_rust.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/07\/sc_dsdetect_rust.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/07\/sc_dsdetect_rust.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":4281,"url":"https:\/\/litcoder.com\/?p=4281","url_meta":{"origin":3939,"position":4},"title":"Rust: comparison is useless due to type limits","author":"litcoder","date":"2026\ub144 6\uc6d4 17\uc77c","format":false,"excerpt":"\"\ud0c0\uc785 \uc81c\ud55c \ub54c\ubb38\uc5d0 \uc774 \ube44\uad50\uc5f0\uc0b0\uc740 \uc4f8.\ubaa8.\uc5c6.\ub2e4.\" IndexSet\uc774 \ud558\ub098 \uc788\ub2e4\uace0 \ud560 \ub54c, \uadf8 \uc548\uc5d0 \ud558\ub098\ub77c\ub3c4 \uc544\uc774\ud15c\uc774 \uc788\uc73c\uba74 true\ub97c \ubc18\ud658\ud558\uace0 \uc544\ub2c8\uba74 false\ub97c \ubc18\ud658\ud558\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 Rust code\ub97c \uc0dd\uac01\ud574 \ubcf4\uc790. use indexmap::IndexSet; fn has_item(item_set: &IndexSet<String>) -> bool { item_set.iter().count() >= 0 } \uac04\ub2e8\ud558\uac8c unittest\uc5d0 \ub123\uc5b4\uc11c \uc0c8\ub85c \uc0dd\uc131\ud574\uc11c \uc544\ubb34 \uc6d0\uc18c\ub3c4 \uc5c6\ub294 IndexSet\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c\u2026","rel":"","context":"&quot;Programming&quot;\uc5d0\uc11c","block_context":{"text":"Programming","link":"https:\/\/litcoder.com\/?cat=5"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/05\/rust_unused_comparisons.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":4528,"url":"https:\/\/litcoder.com\/?p=4528","url_meta":{"origin":3939,"position":5},"title":"Rust unittest\ub97c \uc704\ud55c \uc758\uc874\uc131 \uaca9\ub9ac","author":"litcoder","date":"2026\ub144 9\uc6d4 2\uc77c","format":false,"excerpt":"\ub2e4\ud589\ud788\ub3c4 \uc6b0\ub9ac\ub294 unittest\uc758 \uc720\uc6a9\ud568 \uc798 \uc54c\ub824\uc9c4 \uc2dc\ub300\uc5d0 \uc0b4\uace0 \uc788\uae30\uc5d0 \ub354 \uc774\uc0c1 unittest\ub97c \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\ub97c \ud2b9\ubcc4\ud558\uac8c \ubc1b\uc544\ub4e4\uc774\uc9c0 \uc54a\ub294\ub2e4. Rust\ub294 \ube44\uad50\uc801 \ucd5c\uc2e0 \uc5b8\uc5b4\uc778 \ub9cc\ud07c \uc774\ub7ec\ud55c \uc694\uad6c\uc0ac\ud56d\ub4e4\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ubc1b\uc544\ub4e4\uc5ec \ubd80\uac00\uc801\uc778 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ub3c4\uc6c0 \uc5c6\uc774\ub3c4 \uc5b8\uc5b4 \uc790\uccb4\uc5d0\uc11c \uae30\ubcf8\uc801\uc778 unittest\uac00 \uc798 \uc9c0\uc6d0\ub41c\ub2e4. \ub2e4\ub9cc, Rust\ub294 \uc0c1\uc18d\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 Python, Java, C++ \uac19\uc740 \uac1d\uccb4\uc9c0\ud5a5 \uc5b8\uc5b4\uc5d0\uc11c \uc758\uc874\uc131\uc744\u2026","rel":"","context":"&quot;Programming&quot;\uc5d0\uc11c","block_context":{"text":"Programming","link":"https:\/\/litcoder.com\/?cat=5"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/posts\/3939","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/litcoder.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3939"}],"version-history":[{"count":16,"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/posts\/3939\/revisions"}],"predecessor-version":[{"id":4640,"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/posts\/3939\/revisions\/4640"}],"wp:attachment":[{"href":"https:\/\/litcoder.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3939"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/litcoder.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3939"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/litcoder.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3939"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}