Community

๐Ÿ•Š๏ธ Kafka Streams: ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ๋„๊ตฌ

Kafka Streams๋Š” Apache Kafka์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ถ„์‚ฐ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉฐ ๋ฐ์ดํ„ฐ ๋ถ„์„, ๋ณ€ํ™˜, ์ง‘๊ณ„ ๊ฐ™์€ ์ž‘์—…์„ ์†์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ย  ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” Kafka Streams์˜ ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ์ž‘๋™ ๋ฐฉ์‹์„ ์ดˆ๋ณด์ž๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ย  Kafka Streams๋ž€ ๋ฌด์—‡์ธ๊ฐ€? Kafka Streams๋Š” ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ Apache Kafka์˜ ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์˜ ์„ธ๋ถ€์‚ฌํ•ญ์„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ด€๋ฆฌํ•˜์ง€ ์•Š์•„๋„, ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋•์Šต๋‹ˆ๋‹ค. Kafka Streams๋Š” ๋ฐ์ดํ„ฐ์˜ ํ•„ํ„ฐ๋ง, ๋ณ€ํ™˜, ์ง‘๊ณ„ ๊ฐ™์€ ์ž‘์—…์„ ์‰ฝ๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ย  [์ฃผ์š” ํŠน์ง•] * ์‚ฌ์šฉ ํŽธ์˜์„ฑ Kafka Streams๋Š” Java ๋ฐ Scala ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ, ๋ณ„๋„์˜ ํด๋Ÿฌ์Šคํ„ฐ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. * ํ™•์žฅ์„ฑ Kafka Streams๋Š” ์ž๋™์œผ๋กœ ์ž‘์—…์„ ๋ถ„์‚ฐ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋„ ์•ˆ์ •์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. * ์‹ค์‹œ๊ฐ„ ์ฒ˜๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜์ž๋งˆ์ž ํ•„ํ„ฐ๋ง, ๋ณ€ํ™˜, ์ง‘๊ณ„ ๊ฐ™์€ ์ž‘์—…์„ ์ฆ‰์‹œ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. * ๋‚ด๊ฒฐํ•จ์„ฑ Kafka์˜ ๋‚ด์žฅ๋œ ๋‚ด๊ฒฐํ•จ์„ฑ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ™œ์šฉํ•ด ์žฅ์•  ๋ฐœ์ƒ ์‹œ์—๋„ ์•ˆ์ •์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ย  ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ Kafka Streams ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฃผ์š” ๊ฐœ๋…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ย  [Stream] Stream์€ Kafka ํ† ํ”ฝ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. Kafka Streams์—์„œ Stream์€ ๋์—†์ด ๋ณ€ํ™”ํ•˜๋Š” ๋ ˆ์ฝ”๋“œ์˜ ํ๋ฆ„์œผ๋กœ, ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž ํด๋ฆญ ๋กœ๊ทธ๋‚˜ ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ย  [Stream Processing Topology] Topology๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์ •์˜ํ•˜๋Š” ์—ฐ์‚ฐ์˜ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ , ๋ณ€ํ™˜ํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๋Š” ์ฒ˜๋ฆฌ ํ๋ฆ„์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. * Source Processor: Kafka ํ† ํ”ฝ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. * Stream Processor: ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. * Sink Processor: ์ฒ˜๋ฆฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅธ Kafka ํ† ํ”ฝ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. [KStream๊ณผ KTable] Kafka Streams์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์ฃผ์š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. * KStream: ๋ ˆ์ฝ”๋“œ์˜ ์—ฐ์†์ ์ธ ์ŠคํŠธ๋ฆผ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์˜ˆ: Order ์ด๋ฒคํŠธ ์ŠคํŠธ๋ฆผ * KTable: ์ŠคํŠธ๋ฆผ์—์„œ ์ง‘๊ณ„๋œ ์ƒํƒœ ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์˜ˆ: ํ˜„์žฌ ์žฌ๊ณ  ์ƒํƒœ, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ย  ์ž‘๋™ ๋ฐฉ์‹ Kafka Streams ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ย  1. Kafka ํ† ํ”ฝ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด๋“ค์ž…๋‹ˆ๋‹ค. StreamsBuilder builder = new StreamsBuilder(); KStream inputStream = builder.stream("input-topic"); * StreamsBuilder๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์ •์˜ํ•˜๋Š” ์‹œ์ž‘์ ์ž…๋‹ˆ๋‹ค. * ์œ„ ์ฝ”๋“œ์—์„œ input-topic์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ Kafka ํ† ํ”ฝ์ž…๋‹ˆ๋‹ค. ย  2. ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. KStream filteredStream = inputStream.filter( (key, value) -> value.contains("important") ); * filter ์—ฐ์‚ฐ์€ ํŠน์ • ์กฐ๊ฑด์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋งŒ ๋‚จ๊น๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ’์— "important"๊ฐ€ ํฌํ•จ๋œ ๋ฐ์ดํ„ฐ๋งŒ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. 3. ์ง‘๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. KTable wordCounts = inputStream .flatMapValues(value -> Arrays.asList(value.split(" "))) .groupBy((key, word) -> word) .count(); * ์œ„ ์ฝ”๋“œ์—์„œ๋Š” ๊ฐ ๋‹จ์–ด์˜ ๋ฐœ์ƒ ํšŸ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„ํ•ด(flatMap)ํ•˜๊ณ , ๊ทธ๋ฃนํ™”ํ•œ ํ›„, ์ง‘๊ณ„ํ•˜๋Š” ๊ณผ์ •์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. 4. ์ฒ˜๋ฆฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒˆ๋กœ์šด Kafka ํ† ํ”ฝ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. filteredStream.to("output-topic"); * to ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ output-topic์œผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. 5. Kafka Streams ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. KafkaStreams streams = new KafkaStreams(builder.build(), props); streams.start(); ย  ์‹ค์ œ ํ™œ์šฉ ์‚ฌ๋ก€ Kafka Streams๋Š” ๋‹ค์–‘ํ•œ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ž‘์—…์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. 1. ๋กœ๊ทธ ๋ถ„์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋กœ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๊ฑฐ๋‚˜ ์„ฑ๋Šฅ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. 2. IoT ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ , ์ด๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์•Œ๋ฆผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: ์˜จ๋„ ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€ ์ „์†ก. 3. ์‹ค์‹œ๊ฐ„ ์ถ”์ฒœ ์‹œ์Šคํ…œ ์‚ฌ์šฉ์ž ํ–‰๋™ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฆ‰๊ฐ์ ์ธ ์ถ”์ฒœ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: ํŠน์ • ์ƒํ’ˆ์„ ํด๋ฆญํ•˜๋ฉด ๊ด€๋ จ ์ƒํ’ˆ ์ถ”์ฒœ. 4. ๊ธˆ์œต ๊ฑฐ๋ž˜ ๋ชจ๋‹ˆํ„ฐ๋ง ๊ธˆ์œต ๊ฑฐ๋ž˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ์‚ฌ๊ธฐ ํ–‰์œ„๋ฅผ ํƒ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: ๋น„์ •์ƒ์ ์œผ๋กœ ํฐ ๊ฑฐ๋ž˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ฒฝ๊ณ ๋ฅผ ์ƒ์„ฑ. ย  ์žฅ๋‹จ์  [์žฅ์ ] * ๊ฐ„๋‹จํ•œ API: ๋ณต์žกํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅ * ํ™•์žฅ์„ฑ: ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์—๋„ ์ ํ•ฉ * Kafka์™€์˜ ํ†ตํ•ฉ: Kafka์™€ ๊ธด๋ฐ€ํžˆ ํ†ตํ•ฉ๋˜์–ด ๋†’์€ ์„ฑ๋Šฅ์„ ๋ณด์žฅ [๋‹จ์ ] * ์ดˆ๊ธฐ ํ•™์Šต ๊ณก์„ : ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ ๊ฐœ๋…๊ณผ Kafka์˜ ์ž‘๋™ ๋ฐฉ์‹์„ ์ดํ•ดํ•ด์•ผ ํ•จ * Java ๊ธฐ๋ฐ˜: ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ๊ฐœ๋ฐœ์„ ์›ํ•˜๋Š” ๊ฒฝ์šฐ ์ œ์•ฝ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Œ ย  ๊ฒฐ๋ก  Kafka Streams๋Š” ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์˜ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ์•ˆ์ •์ ์ด๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ๋กœ๊ทธ ๋ถ„์„, IoT ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ, ์‹ค์‹œ๊ฐ„ ์ถ”์ฒœ ์‹œ์Šคํ…œ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ถ„์•ผ์—์„œ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค. ย  ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ๋Š” KStream๊ณผ KTable์„ ํ™œ์šฉํ•œ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ ๊ฐ„์˜ ์กฐ์ธ(Join) ๋ฐฉ์‹์— ๋Œ€ํ•ด ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค. Inner Join, Left Join, Outer Join ๊ฐ™์€ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์ด ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ์‚ดํŽด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ๋ณธ๋ฌธ: [https://ducktopia.tistory.com/140]

์•Œ๋ฆผ

์•Œ๋ฆผ์ด ์—†์Šต๋‹ˆ๋‹ค