Kafka 역직렬화 설정

남순식·2026년 4월 30일

Kafka JsonDeserializer 설정 설명

value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties:
  spring.json.trusted.packages: "com.yeoljeong.tripmate.*"
  spring.json.type.headers: true

핵심 설정 분석

spring.json.type.headers: true 이 설정이 핵심이다. 이 옵션이 true이면 Kafka 메시지의 헤더에 포함된 타입 정보를 우선적으로 사용해서 역직렬화할 클래스를 결정한다.


동작 원리

메시지를 발행(produce)할 때 JsonSerializer는 자동으로 두 개의 헤더를 추가한다.

헤더 키예시 값설명
__TypeId__com.yeoljeong.tripmate.event.OrderEvent대상 클래스 FQCN
__KeyTypeId__java.lang.String키 타입 (optional)

소비(consume)할 때 JsonDeserializerspring.json.type.headers: true이므로 payload 자체를 분석하지 않고 __TypeId__ 헤더 값을 읽어서 해당 클래스로 역직렬화한다.


각 설정 옵션 상세 설명

spring.json.type.headers: true

공식 문서에 따르면, JsonDeserializer는 타입을 결정하는 두 가지 전략을 가진다. (공식 문서)

true  → 메시지 헤더의 __TypeId__ 를 보고 역직렬화 클래스 결정
false → 기본값으로 설정된 targetType 또는 제네릭 타입으로 역직렬화

true로 설정하면 같은 토픽에 여러 타입의 메시지를 혼재시킬 수 있다. 예를 들어 OrderEvent, PaymentEvent, UserEvent가 모두 같은 토픽을 통해 흐를 때 각각 올바른 클래스로 매핑된다.

spring.json.trusted.packages

보안 상 이유로 JsonDeserializer는 헤더에 명시된 클래스라고 해서 무조건 인스턴스화하지 않는다. 공격자가 헤더를 조작해 임의 클래스를 로드하는 것을 막기 위함이다.

spring.json.trusted.packages: "com.yeoljeong.tripmate.*"

* 와일드카드를 사용하면 해당 패키지 하위 모든 클래스를 신뢰한다. 전체를 허용하려면 "*"만 쓸 수 있지만 운영 환경에서는 권장하지 않는다.


Producer 쪽 대응 설정

Consumer 설정이 헤더에 의존하므로, Producer도 헤더를 올바르게 심어야 한다.

spring:
  kafka:
    producer:
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
      properties:
        spring.json.add.type.headers: true  # 기본값이 true이므로 생략 가능

JsonSerializer는 기본적으로 직렬화 시 __TypeId__ 헤더를 자동으로 추가한다. Producer와 Consumer가 서로 다른 서비스에 있을 경우 클래스 경로(FQCN)가 달라질 수 있는데, 이때는 타입 매핑 설정으로 해결한다.

# Producer 쪽 (서비스 A)
spring.json.type.mapping: "orderEvent:com.serviceA.event.OrderEvent"

# Consumer 쪽 (서비스 B)
spring.json.type.mapping: "orderEvent:com.serviceB.event.OrderEvent"

이렇게 하면 헤더에는 com.serviceA.event.OrderEvent 대신 orderEvent라는 논리명이 담기고, Consumer는 그것을 자신의 클래스로 매핑한다.


정리

설정역할
spring.json.type.headers: true헤더의 __TypeId__ 값으로 역직렬화 클래스 결정
spring.json.trusted.packages허용된 패키지의 클래스만 역직렬화 허용 (보안)
spring.json.add.type.headers: trueProducer가 헤더에 타입 정보를 심도록 설정 (기본값)
spring.json.type.mapping서비스 간 클래스 경로가 다를 때 논리명으로 매핑

결국 이 설정의 핵심은 "메시지 본문을 파싱하기 전에 헤더를 먼저 보고, 거기 적힌 클래스로 Jackson이 역직렬화한다"는 것이다. 덕분에 Consumer 코드는 ConsumerRecord<String, Object>가 아니라 처음부터 ConsumerRecord<String, OrderEvent> 같은 구체 타입을 받을 수 있다.

profile
응집력있는 시간을 보내기 위한 블로그

0개의 댓글