SSM 기반 애플리케이션에서 Kafka 메시지 큐 통합 가이드

Kafka를 활용한 고성능 SSM 아키텍처 설계

분산 마이크로서비스 환경에서 안정적인 비동기 처리를 구현하기 위해 메시지 큐는 필수 요소다. Spring + Spring MVC + MyBatis(SM)로 구성된 전통적인 웹 애플리케이션도 카프카와의 통합을 통해 초고속 트래픽 환경, 예를 들어 플래시 세일(초대박 할인)과 같은 시나리오에 대응할 수 있다. 본 문서에서는 SM 기반 프로젝트에서 카프카를 효과적으로 도입하는 방법을 단계별로 설명한다.

왜 카프카인가?

카프카는 높은 처리량과 지속성, 메시지 순서 보장을 제공하는 분산 스트리밍 플랫폼이다. 특히 수천 건 이상의 요청이 몰리는 이벤트 기반 시스템에서 데이터 유실 없이 안정적인 처리를 가능하게 한다. SM 애플리케이션은 카프카를 통해 주문 생성과 재고 차감 과정을 비동기화하여 응답 지연을 줄이고 데이터베이스 부하를 완화할 수 있다.

주문 처리 파이프라인에서의 역할

예를 들어, 사용자가 상품을 주문하면 즉시 DB에 삽입하는 대신, 주문 정보를 order-events 토픽으로 발행한다. 이후 별도의 소비자 서비스가 해당 메시지를 수신하여 실제 주문 로직을 실행한다. 이를 통해 요청-응답 사이클을 최소화하고, 일시적인 장애 발생 시에도 메시지를 재처리할 수 있는 유연성을 확보한다.

카프카 프로듀서 설정

스프링 환경에서 카프카 프로듀서를 구성하기 위해 아래와 같은 자바 기반 설정 클래스를 작성할 수 있다.

@Configuration
@EnableKafka
public class MessageQueueConfig {

    @Value("${kafka.bootstrap-servers}")
    private String bootstrapServers;

    @Bean
    public ProducerFactory<String, OrderPayload> orderProducerFactory() {
        Map<String, Object> configProps = new HashMap<>();
        configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JacksonSerializer.class);
        return new DefaultKafkaProducerFactory<>(configProps);
    }

    @Bean
    public KafkaTemplate<String, OrderPayload> kafkaTemplate() {
        return new KafkaTemplate<>(orderProducerFactory());
    }
}

위 코드는 KafkaTemplate을 빈으로 등록하여 애플리케이션 어디서든 주문 메시지를 손쉽게 전송할 수 있도록 한다. 직렬화에는 JSON 기반 커스텀 직렬화기가 사용되며, 복잡한 객체도 안전하게 전달 가능하다.

메시지 발행 실습

서비스 계층에서 카프카를 활용하는 예시는 다음과 같다.

@Service
public class PurchaseService {

    @Autowired
    private KafkaTemplate<String, OrderPayload> messageSender;

    @Autowired
    private InventoryChecker inventoryChecker;

    public boolean initiatePurchase(int productId) {
        if (!inventoryChecker.hasStock(productId)) {
            return false;
        }

        OrderPayload payload = new OrderPayload();
        payload.setProductId(productId);
        payload.setTimestamp(System.currentTimeMillis());

        // 비동기 메시지 전송
        messageSender.send("order-events", payload);

        return true;
    }
}

이 방식은 사용자에게 빠른 응답을 제공하면서도, 백엔드에서 안정적인 주문 처리를 보장한다.

독립형 컨슈머 설계

메시지 소비는 별도의 스탠드얼론 애플리케이션 또는 모듈에서 수행하는 것이 바람직하다. 다음은 스프링 캡스톤 기반의 컨슈머 예제다.

@Component
public class OrderEventConsumer {

    @KafkaListener(topics = "order-events", groupId = "purchase-group")
    public void handleOrder(OrderPayload payload) {
        try {
            processOrderLogic(payload);
        } catch (Exception e) {
            // 재시도 또는 DLQ(Dead Letter Queue) 처리
            sendToDeadLetterQueue(payload, e);
        }
    }

    private void processOrderLogic(OrderPayload payload) {
        // 재고 감소, 주문 저장 등 비즈니스 로직
    }

    private void sendToDeadLetterQueue(OrderPayload payload, Exception e) {
        // 에러 로깅 및 별도 토픽으로 전달
    }
}

컨슈머는 자체적인 오류 처리 및 재시도 전략을 가지며, 장애 상황에서도 데이터 무결성을 유지할 수 있다.

성능 및 운영 최적화 전략

  • 커넥션 풀링: KafkaTemplate은 내부적으로 프로듀서 인스턴스를 재사용하여 오버헤드를 줄인다.
  • 직렬화 최적화: Jackson 기반 직렬화기를 사용해 성능과 호환성을 동시에 확보한다.
  • 에러 리커버리: 실패한 메시지는 별도의 DLQ 토픽으로 전달되어 추후 분석 및 재처리가 가능하다.
  • 모니터링: JMX, Prometheus 연동을 통해 오프셋 지연, 처리율 등을 실시간으로 모니터링할 수 있다.

테스트 전략

통합 테스트 시에는 임베디드 카프카를 사용하여 외부 의존성을 제거할 수 있다.

@SpringBootTest
@TestPropertySource(properties = {"kafka.bootstrap-servers=localhost:9092"})
@EmbeddedKafka(partitions = 1, topics = "order-events")
class OrderFlowTest {

    @Autowired
    private KafkaTemplate<String, OrderPayload> sender;

    @Test
    public void shouldProcessOrderMessage() {
        OrderPayload testEvent = new OrderPayload(1001, System.currentTimeMillis());
        sender.send("order-events", testEvent);

        // 컨슈머 동작 검증 로직
        await().atMost(Duration.ofSeconds(5)).until(messageReceived());
    }
}

이 방식은 개발 및 CI/CD 환경에서 신뢰성 있는 테스트를 가능하게 한다.

마무리 및 향후 방향

SM 기반 애플리케이션에 카프카를 도입함으로써, 시스템의 확장성과 안정성을 크게 향상시킬 수 있다. 앞으로는 카프카 스트림을 활용해 실시간 재고 집계, 사용자 행동 분석 등의 고급 기능을 추가하는 것도 고려할 만하다. 또한 컨테이너 기반 배포(Kubernetes)와 결합하면 더욱 탄력적인 운영 인프라를 구축할 수 있다.

태그: kafka Spring MyBatis 메시지 큐 비동기 처리

6월 10일 21:30에 게시됨