[JAVA] Spring Boot와 Kafka 연동하기 - 실무 개발자를 위한 가이드

대용량 실시간 데이터 처리를 위해 Kafka를 사용하는 시스템이 점점 많아지고 있습니다.
Spring Boot는 Kafka와의 연동을 위한 풍부한 기능과 설정을 제공하며, 간단한 설정만으로 메시지 생산/소비 로직을 구현할 수 있습니다.
Spring Boot에서 Kafka를 연동하는 방법과, 실무에서 자주 사용하는 패턴을 알려드리겠습니다.

 


Kafka란 무엇인가?

Kafka는 분산형 스트리밍 플랫폼으로, 대용량 로그나 이벤트 데이터를 처리하는 데 최적화된 메시지 큐 시스템입니다.
Producer → Kafka Topic → Consumer 구조로 작동하며, 고가용성(HA), 확장성(Scalability), 내결함성(Fault-Tolerance)을 보장합니다.

 

 

Kafka 설치 (Docker)

개발 환경에서는 Docker Compose를 사용하는 것이 가장 간편합니다.

# docker-compose.yml
version: '2'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.3.2
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181

  kafka:
    image: confluentinc/cp-kafka:7.3.2
    ports:
      - 9092:9092
    environment:
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1

 

 

Gradle 의존성 추가

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.kafka:spring-kafka'
}

 

 

application.yml 설정

spring:
  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      group-id: my-group
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

 

 

Kafka Producer 구현

@Service
public class KafkaProducerService {

    private final KafkaTemplate<String, String> kafkaTemplate;

    public KafkaProducerService(KafkaTemplate<String, String> kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }

    public void sendMessage(String topic, String message) {
        kafkaTemplate.send(topic, message);
    }
}

 

 

Kafka Consumer 구현

@Service
public class KafkaConsumerService {

    @KafkaListener(topics = "my-topic", groupId = "my-group")
    public void listen(String message) {
        System.out.println("Received message: " + message);
    }
}

 

 

테스트용 Controller 작성

@RestController
@RequestMapping("/kafka")
public class KafkaController {

    private final KafkaProducerService producerService;

    public KafkaController(KafkaProducerService producerService) {
        this.producerService = producerService;
    }

    @PostMapping("/send")
    public String send(@RequestParam String message) {
        producerService.sendMessage("my-topic", message);
        return "Sent: " + message;
    }
}

 

 

실무에서의 팁

  • KafkaTemplate은 싱글톤으로 관리되므로, 의존성 주입이 안정적
  • @KafkaListenerconcurrency 옵션을 주면 병렬 처리 가능
  • 역직렬화 예외는 종종 장애를 유발하므로, DTO 사용 시 정확한 타입 매핑 필요
  • 실제 운영에서는 retry, dead-letter topic, commit 정책 설정이 중요

 

Kafka 연동 구조 요약

Spring Boot 애플리케이션에서 Kafka 연동은 비교적 간단하지만, 분산 시스템의 특성상 장애 대응과 메시지 처리 신뢰성 설계가 중요합니다.
비동기 메시징 환경을 안정적으로 운용하려면 ACK 정책, 재처리 전략, Consumer 모니터링도 함께 고려해야 합니다.

 

 


 

Kafka는 로그 수집, 이벤트 처리, 마이크로서비스 간 통신 등에서 핵심적인 역할을 합니다.
Spring Boot와 Kafka는 기본 의존성과 설정만으로도 충분한 기능을 제공하며, 이를 바탕으로 강력한 실시간 시스템을 만들 수 있습니다.
프로젝트에 Kafka를 도입한다면, 운영 환경에서는 메시지 유실, 순서 보장, 병렬 처리 전략 등도 함께 고민해야 진짜 “실무”입니다.