0Pricing
Advanced Spring Boot 4: Event-Driven Architecture (Kafka) · 강의

KStream 및 KTable을 활용한 스트림 처리

불변 이벤트 스트림에는 KStream을, 상태를 유지하며 업데이트할 수 있는 데이터 뷰에는 KTable을 사용하는 방법을 배우고, 필터링과 매핑 같은 연산을 수행합니다.

KStream 및 KTable을 활용한 스트림 처리은(는) CoddyKit의 무료 Advanced Spring Boot 4: Event-Driven Architecture (Kafka) 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Advanced Spring Boot 4: Event-Driven Architecture (Kafka) 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Advanced Spring Boot 4: Event-Driven Architecture (Kafka) 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

KStream & KTable Unveiled

Welcome! In Kafka Streams, KStream and KTable are your primary tools for processing data. They represent different views of your data in motion.

Think of them as two sides of the same coin, each suited for distinct stream processing tasks. Understanding their differences is key to building powerful stream applications.

KStream: Immutable Events

A KStream represents an infinite, immutable sequence of events. Each record in a KStream is a self-contained fact, an independent event that happened at a specific point in time.

  • It's like a transaction log: once an event is added, it's never changed.
  • Operations on a KStream produce new KStreams, leaving the original untouched.
  • It's ideal for processing individual events like clicks, sensor readings, or log entries.

Filtering KStream Events

One common KStream operation is filtering. You can selectively keep records that match certain criteria, creating a new KStream with only the relevant events.

Here's a simple example filtering messages that contain 'hello'.

import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.kstream.KStream;

import java.util.Properties;

public class Main {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.put(StreamsConfig.APPLICATION_ID_CONFIG, "filter-app");
        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_BY_DEFAULT, Serdes.String().getClass());
        props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_BY_DEFAULT, Serdes.String().getClass());

        StreamsBuilder builder = new StreamsBuilder();
        KStream<String, String> sourceStream = builder.stream("input-topic");

        KStream<String, String> filteredStream = sourceStream.filter(
            (key, value) -> value.contains("hello")
        );

        filteredStream.to("output-topic");

        KafkaStreams streams = new KafkaStreams(builder.build(), props);
        // In a real app, you'd start and manage this lifecycle:
        // streams.start();
        // Runtime.getRuntime().addShutdownHook(new Thread(streams::close));
        System.out.println("KStream filter setup complete. Send 'hello world' to input-topic!");
    }
}

Transforming KStream Values

The mapValues operation transforms the value of each record in a KStream, producing a new KStream with the modified values. The key remains unchanged.

This is useful for cleaning data, changing formats, or enriching information without altering the message's key.

import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.kstream.KStream;

import java.util.Properties;

public class Main {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.put(StreamsConfig.APPLICATION_ID_CONFIG, "mapvalues-app");
        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_BY_DEFAULT, Serdes.String().getClass());
        props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_BY_DEFAULT, Serdes.String().getClass());

        StreamsBuilder builder = new StreamsBuilder();
        KStream<String, String> sourceStream = builder.stream("input-topic");

        KStream<String, String> uppercasedStream = sourceStream.mapValues(
            value -> value.toUpperCase()
        );

        uppercasedStream.to("output-topic");

        KafkaStreams streams = new KafkaStreams(builder.build(), props);
        System.out.println("KStream mapValues setup complete. Send 'test' to input-topic!");
    }
}

KTable: A Materialized View

A KTable represents a changelog stream, where each record is an update to a specific key. It's essentially a materialized view of a table, reflecting the latest state for each key.

  • It's like a database table: keys have associated values, and new records for a key overwrite previous ones.
  • KTable is stateful, maintaining the latest value for each key over time.
  • It's perfect for aggregating data, maintaining counts, or storing user profiles.

KTable's Stateful Nature

The core idea behind a KTable is that it keeps track of the latest value for each unique key. When a new record with an existing key arrives, the KTable updates its internal state.

This makes KTable ideal for scenarios where you care about the current state of an entity, rather than every single event that led to that state.

KStream to KTable: Counting

You can transform a KStream into a KTable, typically to perform aggregations. A common example is counting occurrences of keys using groupByKey().count().

Each time a message arrives, the count for its key is updated, and the KTable emits the new total.

import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.KTable;
import org.apache.kafka.streams.kstream.Materialized;

import java.util.Properties;

public class Main {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.put(StreamsConfig.APPLICATION_ID_CONFIG, "kstream-to-ktable-app");
        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_BY_DEFAULT, Serdes.String().getClass());
        props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_BY_DEFAULT, Serdes.String().getClass());

        StreamsBuilder builder = new StreamsBuilder();
        KStream<String, String> sourceStream = builder.stream("input-topic");

        KTable<String, Long> wordCounts = sourceStream
            .groupByKey() // Group by the existing key
            .count(Materialized.as("counts-store")); // Count occurrences, store in state

        wordCounts.toStream().to("output-topic"); // Convert back to stream to send out

        KafkaStreams streams = new KafkaStreams(builder.build(), props);
        System.out.println("KStream to KTable count setup. Send 'word' with key 'A' to input-topic!");
    }
}

KTable for Aggregation

KTables are excellent for continuous aggregation. Beyond simple counts, you can use operations like aggregate to maintain sums, averages, or custom aggregates over time.

This allows your application to always have an up-to-date summary of data for specific keys.

When to Use Which?

The choice between KStream and KTable depends on your processing needs:

  • Use KStream when you need to process individual events, react to every occurrence, or build a pipeline of transformations that don't depend on historical state. Think real-time alerts or event logging.
  • Use KTable when you need to maintain a current state, aggregate data over time, or join with other data sources based on the latest value. Think user profiles, stock prices, or aggregated metrics.

KStream vs. KTable Check

You've learned about KStream and KTable. Let's test your understanding.

KStream & KTable Recap

Great job! You've explored the core differences and uses of KStream and KTable.

  • KStream handles individual, immutable events, perfect for event-by-event processing.
  • KTable maintains a materialized view, tracking the latest state for each key, ideal for aggregations and stateful processing.

These two primitives are the foundation for building powerful and flexible stream processing applications with Kafka Streams.

자주 묻는 질문

“KStream 및 KTable을 활용한 스트림 처리” 강의는 무료인가요?

네 — “KStream 및 KTable을 활용한 스트림 처리” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Advanced Spring Boot 4: Event-Driven Architecture (Kafka) 강의 전체를 잠금 해제할 수 있습니다. Advanced Spring Boot 4: Event-Driven Architecture (Kafka) 강의에는 총 4개의 강의가 포함되어 있습니다.

“KStream 및 KTable을 활용한 스트림 처리”에서 뭘 배우나요?

불변 이벤트 스트림에는 KStream을, 상태를 유지하며 업데이트할 수 있는 데이터 뷰에는 KTable을 사용하는 방법을 배우고, 필터링과 매핑 같은 연산을 수행합니다. 브라우저에서 직접 실행하는 실습 코드로 Advanced Spring Boot 4: Event-Driven Architecture (Kafka)을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Advanced Spring Boot 4: Event-Driven Architecture (Kafka)을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Advanced Spring Boot 4: Event-Driven Architecture (Kafka)은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“KStream 및 KTable을 활용한 스트림 처리” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Advanced Spring Boot 4: Event-Driven Architecture (Kafka) 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Advanced Spring Boot 4: Event-Driven Architecture (Kafka) 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Kafka Streams 소개
  2. KStream 및 KTable을 활용한 스트림 처리
  3. 간단한 스트림 애플리케이션 구축
  4. Kafka Streams의 윈도잉과 상태 저장 집계
← Advanced Spring Boot 4: Event-Driven Architecture (Kafka)(으)로 돌아가기