읽는 방법

헷갈리는 설정 쌍 6가지 비교 — session.timeout.ms 대 max.poll.interval.ms 등 시험에서 자주 뒤바뀌는 여섯 쌍을 좌우로 비교합니다. 첫째, session.timeout.ms 는 백그라운드 하트비트 스레드 기준(기본 45000)이고 max.poll.interval.ms 는 애플리케이션 스레드의 poll 호출 간격 기준(기본 300000)입니다. 둘째, cleanup.policy 의 delete 는 오래된 세그먼트를 버리고 compact 는 키별 최신 값을 남깁니다. 셋째, acks 는 프로듀서가 요구하는 응답 수준이고 min.insync.replicas 는 브로커·토픽 쪽 최소 ISR 조건으로 둘은 함께 설정해야 합니다. 넷째, subscribe() 는 그룹에 참여해 리밸런스로 파티션을 받고 assign() 은 직접 지정하며 리밸런스가 없습니다. 다섯째, map 계열은 키를 바꿀 수 있어 리파티션을 유발할 수 있고 mapValues 계열은 유발하지 않습니다. 여섯째, 멱등성은 한 세션 안의 중복 제거이고 트랜잭션은 여러 파티션과 오프셋 커밋의 원자성입니다. 헷갈리는 설정·API 6쌍 — 시험에서 가장 자주 뒤바뀌는 짝 session.timeout.ms 하트비트 스레드(백그라운드)가 이 시간 안에 하트비트를 못 보내면 이탈 기본 45000 max.poll.interval.ms 애플리케이션 스레드가 이 시간 안에 poll() 을 다시 부르지 않으면 이탈 기본 300000 vs → 축이 다릅니다. 처리가 길어져 터지는 쪽은 항상 max.poll.interval.ms 입니다. cleanup.policy=delete 시간 · 크기 기준으로 오래된 세그먼트를 통째로 버립니다 기본값 cleanup.policy=compact 키별 최신 값을 남기고 같은 키의 옛 값만 지웁니다 상태·changelog 토픽용 vs → 둘을 "delete,compact" 로 함께 쓸 수도 있습니다. 빈 값이면 무한 보관입니다. acks 프로듀서가 요구하는 응답 수준 acks=all 이면 ISR 전원 응답 대기 프로듀서 설정 · 기본 all min.insync.replicas acks=all 일 때 최소 몇 개의 ISR 이 있어야 쓰기를 받아 줄지 브로커·토픽 설정 · 기본 1 vs → acks=all 만 켜고 min.insync.replicas=1 이면 리더 1대만 살아도 성공합니다. 둘은 짝입니다. subscribe() 그룹에 참여 · 리밸런스로 파티션 배정 group.id 필요 · 오프셋 커밋 가능 assign() 파티션을 직접 지정 · 리밸런스 없음 그룹 관리 없음 · 커밋은 group.id 있으면 가능 vs → assign() 은 컨슈머를 늘려도 자동 분배가 없습니다. 스케일 아웃이 필요하면 subscribe() 입니다. map / flatMap / selectKey 키를 바꿀 수 있으므로 리파티션 토픽이 생길 수 있음 mapValues / flatMapValues 값만 바꾸므로 키가 그대로 리파티션이 생기지 않음 vs → 값만 바꿀 때 mapValues 를 쓰는 것만으로 불필요한 리파티션 토픽을 없앨 수 있습니다. 멱등성 (enable.idempotence) 한 프로듀서 세션 안에서 같은 파티션의 중복 쓰기를 제거 기본 true 트랜잭션 (transactional.id) 여러 파티션 쓰기와 오프셋 커밋을 하나의 원자 단위로 묶음 명시적으로 켜야 함 vs → 멱등성은 중복 방지, 트랜잭션은 원자성입니다. 트랜잭션은 멱등성을 포함합니다.
헷갈리는 설정 쌍 비교 — session.timeout.ms vs max.poll.interval.ms, acks vs min.insync.replicas, retention vs compaction 등 대표 6쌍을 소속(프로듀서·컨슈머·브로커·토픽)과 발동 시점으로 갈라 배치한 그림입니다.

컨슈머 — 1번부터 9번

1. session.timeout.ms vs max.poll.interval.ms

가장 많이 출제되고 가장 많이 틀리는 쌍
session.timeout.msmax.poll.interval.ms
무엇인가하트비트가 끊긴 뒤 코디네이터가 기다리는 시간. 기본 45000poll() 호출 사이 허용 시간. 기본 300000
어디 설정인가컨슈머컨슈머
언제 발동하는가백그라운드 하트비트 스레드가 멈췄을 때애플리케이션 스레드의 처리가 길어졌을 때
혼동 시 결과처리 지연 문제에 session.timeout.ms를 올려 증상은 안 잡히고 장애 감지만 늦어집니다
출제 형태"프로세스가 죽은 것을 감지하는 설정은?""프로세스는 살아 있는데 그룹에서 빠지는 이유는?" → 1차 처방은 max.poll.records 축소

2. heartbeat.interval.ms vs session.timeout.ms

같은 축에 있지만 하나는 주기, 하나는 인내 한계
heartbeat.interval.mssession.timeout.ms
무엇인가하트비트를 보내는 주기. 기본 3000하트비트를 기다리는 한계. 기본 45000
어디 설정인가컨슈머컨슈머 (브로커의 group.min/max.session.timeout.ms 범위 안이어야 함)
언제 발동하는가주기적으로 계속마지막 하트비트로부터 이 시간이 지나면
혼동 시 결과권장 관계는 heartbeat ≤ session ÷ 3입니다. 이를 어기면 하트비트 한 번만 놓쳐도 사망 판정이 납니다
출제 형태"session.timeout.ms=9000일 때 heartbeat.interval.ms 권장값은?" → 3000 이하

3. assign() vs subscribe()

그룹 조정에 참여하는가
subscribe(topics)assign(partitions)
무엇인가토픽을 구독하고 할당을 받음파티션을 직접 지정
어디 설정인가컨슈머 코드 (API)컨슈머 코드 (API)
언제 발동하는가리밸런스 시 파티션이 재배정됨호출 즉시 고정. 리밸런스 없음
혼동 시 결과둘을 같은 인스턴스에서 섞으면 IllegalStateException. assign()파티션 증가를 감지하지 않아 새 파티션이 조용히 방치됩니다
출제 형태"group.id 없이 동작하는 것은?" → assign() / "리밸런스를 피하려면?" → assign()(단 확장성 포기)

4. auto.offset.resetearliest vs latest vs none

세 값의 분기와 발동 조건
earliestlatest (기본값)none
무엇인가로그의 처음부터 읽음지금 이후에 오는 것만 읽음예외를 던짐 (NoOffsetForPartitionException)
어디 설정인가컨슈머
언제 발동하는가커밋된 오프셋이 없을 때, 또는 커밋된 오프셋이 로그 범위를 벗어났을 때만. 정상 커밋이 있으면 아무 일도 하지 않습니다
혼동 시 결과재시작마다 전량 재처리한다고 오해offsets.retention.minutes(7일) 경과로 커밋이 만료되면 그 사이 데이터를 조용히 건너뜁니다운영 중 새 파티션이 생겼을 때 애플리케이션이 죽음
출제 형태"기존 그룹에서 earliest로 바꾸면 처음부터 읽는가?" → 아니오. 새 group.id나 오프셋 리셋이 필요합니다

5. enable.auto.commit vs 수동 커밋

커밋 시점을 누가 결정하는가
enable.auto.commit=true (기본값)수동 커밋
무엇인가auto.commit.interval.ms(5000)마다 자동 커밋commitSync() / commitAsync()를 직접 호출
어디 설정인가컨슈머 설정컨슈머 코드 (설정은 false로)
언제 발동하는가poll()이 호출될 때 직전 반환분을 커밋개발자가 정한 시점
혼동 시 결과자동 커밋은 처리 완료를 기다리지 않습니다. 처리 중 크래시하면 이미 커밋된 레코드가 유실됩니다. 트랜잭션을 쓸 때 자동 커밋이 켜져 있으면 원자성이 깨집니다
출제 형태"at-least-once를 보장하려면?" → 자동 커밋 끄고 처리 후 커밋

6. commitSync() vs commitAsync()

블로킹과 재시도의 차이
commitSync()commitAsync()
무엇인가커밋 응답을 기다림커밋을 보내고 즉시 반환 (콜백으로 결과 수신)
어디 설정인가컨슈머 코드 (API)
언제 발동하는가호출 시 블로킹. 실패하면 자동 재시도호출 시 논블로킹. 자동 재시도 없음
혼동 시 결과루프마다 호출하면 처리량이 떨어짐실패가 조용히 넘어가 재시작 시 중복 처리가 늘어남
출제 형태권장 패턴: 루프에서는 commitAsync(), 종료 직전 finally에서 commitSync()

7. eager 리밸런스 vs cooperative 리밸런스

전부 반납하는가, 필요한 것만 옮기는가
eagercooperative (incremental)
무엇인가리밸런스 시작 시 모든 파티션 반납 (stop-the-world)옮겨야 할 파티션만 두 라운드에 걸쳐 회수·재할당
어디 설정인가컨슈머 partition.assignment.strategy (classic 프로토콜)
언제 발동하는가멤버 변경 시 전체 중단 후 재할당멤버 변경 시 영향 없는 파티션은 계속 소비
혼동 시 결과eager에서 cooperative로 옮길 때 두 단계 롤링 배포가 필요합니다. 한 번에 바꾸면 프로토콜 협상이 실패합니다
출제 형태"리밸런스 중에도 일부 파티션을 계속 소비하는 방식은?" → cooperative. KIP-848(group.protocol=consumer)은 전면 증분 설계입니다

8. Range vs RoundRobin vs Sticky vs CooperativeSticky

할당 전략 4종
RangeAssignorRoundRobinAssignorStickyAssignorCooperativeStickyAssignor
무엇인가토픽별로 연속 구간 분배전체 토픽-파티션을 돌려 담기균등 + 기존 할당 유지Sticky + 증분 재할당
어디 설정인가컨슈머 partition.assignment.strategy. 기본값은 [RangeAssignor, CooperativeStickyAssignor]
언제 발동하는가리밸런스 시. 그룹 멤버 전원이 공통으로 지원하는 전략이 협상으로 선택됩니다
혼동 시 결과토픽이 여러 개일 때 불균등해질 수 있음토픽 간 균등하지만 기존 할당이 다 바뀜여전히 eager라 stop-the-world 발생기본값 목록의 첫 항목이 Range이므로, 쓰려면 이것만 단독 지정
출제 형태"리밸런스 영향을 최소화하는 전략은?" → CooperativeStickyAssignor

9. group.protocol=classic vs consumer (KIP-848)

4.0 GA이지만 기본값이 아닙니다
classic (기본값)consumer (KIP-848)
무엇인가클라이언트가 할당을 계산하는 기존 프로토콜브로커가 할당을 계산하는 새 프로토콜
어디 설정인가컨슈머 group.protocol. 서버 쪽은 4.0부터 자동 활성
언제 발동하는가기본값이므로 명시하지 않으면 이것consumer명시해야 활성
혼동 시 결과consumer에서는 session.timeout.ms·heartbeat.interval.ms·partition.assignment.strategy클라이언트에서 무시됩니다. 이 설정으로 튜닝하려다 아무 효과를 못 봅니다 (할당자는 group.remote.assignor)
출제 형태"KIP-848은 4.0 GA다. 컨슈머 기본값은?" → classic. 시중 자료가 가장 많이 틀리는 지점

프로듀서 — 10번부터 16번

10. acks vs min.insync.replicas

소속이 다르고, 한쪽 조건에서만 상호작용합니다
acksmin.insync.replicas
무엇인가응답을 몇 곳에서 받을지. 기본 all쓰기를 성립시키는 최소 ISR 수. 기본 1
어디 설정인가프로듀서브로커 · 토픽
언제 발동하는가매 전송acks=all일 때만. acks=0/1이면 검사되지 않음
혼동 시 결과min.insync.replicas=2를 걸어도 프로듀서가 acks=1이면 아무 보호가 없습니다. 반대로 acks=all이어도 min.insync.replicas=1이면 ISR이 1로 줄었을 때 유실됩니다
출제 형태"RF=3, min.insync.replicas=2일 때 브로커 몇 대까지 죽어도 쓰기가 되는가?" → 1대 (RF − minISR)

11. batch.size vs linger.ms

배치 전송을 유발하는 두 조건
batch.sizelinger.ms
무엇인가파티션별 배치의 크기 상한. 기본 16384 바이트배치를 더 모으기 위해 기다리는 시간. 기본 5
어디 설정인가프로듀서프로듀서
언제 발동하는가둘 중 먼저 충족되는 쪽에 전송됩니다. AND가 아니라 OR입니다
혼동 시 결과batch.size만 올려도 트래픽이 적으면 배치가 안 참기본값이 0이라고 외우면 틀립니다. 4.0에서 05로 변경되었습니다
출제 형태"지연을 최소화하려면?" → linger.ms=0 명시. "처리량을 올리려면?" → 둘 다 상향 + 압축

12. buffer.memory vs max.block.ms

버퍼가 가득 찼을 때 무슨 일이 일어나는가
buffer.memorymax.block.ms
무엇인가전송 대기 레코드를 담는 전체 메모리. 기본 33554432(32MB)버퍼·메타데이터 대기의 블로킹 상한. 기본 60000
어디 설정인가프로듀서프로듀서
언제 발동하는가브로커가 느려 배치가 쌓이면 소진됨버퍼가 소진되어 send()블로킹될 때부터 카운트
혼동 시 결과버퍼가 가득 차면 send()가 블로킹되고, max.block.ms를 넘기면 TimeoutException이 발생합니다. "비동기니까 절대 블로킹되지 않는다"는 오해가 여기서 깨집니다
출제 형태"send()가 블로킹될 수 있는가?" → , 버퍼 고갈과 메타데이터 미확보 시

13. request.timeout.ms vs delivery.timeout.ms

요청 단위 시간과 전체 예산
request.timeout.msdelivery.timeout.ms
무엇인가한 번의 요청에 대한 응답 대기. 기본 30000send()부터 성공/실패 확정까지 전체. 기본 120000
어디 설정인가프로듀서 (컨슈머·Admin에도 동명 설정 존재)프로듀서
언제 발동하는가매 요청마다. 초과하면 재시도 대상배치 대기 + 모든 재시도의 합이 이 값을 넘으면 최종 실패
혼동 시 결과linger.ms + request.timeout.msdelivery.timeout.ms가 성립해야 합니다. 어기면 설정 검증에서 걸립니다
출제 형태"전송이 최대 얼마나 걸릴 수 있는가?" → delivery.timeout.ms

14. retries vs delivery.timeout.ms

4.x에서 실질 상한은 무엇인가
retriesdelivery.timeout.ms
무엇인가재시도 횟수. 기본 2147483647재시도에 쓸 수 있는 시간. 기본 120000
어디 설정인가프로듀서프로듀서
언제 발동하는가기본값이 사실상 무한이라 거의 발동하지 않음실질적인 재시도 종료 조건
혼동 시 결과retries=0으로 두면 중복이 사라진다고 오해합니다. 실제로는 멱등성이 중복을 막고, retries=0은 유실 위험만 늘립니다. 멱등성을 켜면 retries>0이 강제됩니다
출제 형태"재시도 동작을 제어하는 4.x 권장 방법은?" → 시간 예산(delivery.timeout.ms) 조절

15. retriable 예외 vs non-retriable 예외

기준은 RetriableException 상속 여부입니다
retriablenon-retriable
무엇인가 LeaderNotAvailableException, NotLeaderOrFollowerException, NotEnoughReplicasException, NetworkException, TimeoutException, CoordinatorNotAvailableException RecordTooLargeException, SerializationException, AuthorizationException, InvalidTopicException
어디 설정인가설정이 아니라 예외 계층. 프로듀서가 자동 판별
언제 발동하는가클러스터 상태가 일시적으로 나쁠 때데이터·설정·권한이 잘못되었을 때
혼동 시 결과non-retriable을 재시도로 해결하려 하면 영구히 실패하는 레코드가 파티션을 막습니다. 코드·설정·권한을 고쳐야 합니다
출제 형태matching 유형(예외 ↔ 원인)의 단골. RecordTooLargeException재시도해도 안 됩니다

16. 키 있는 메시지 vs 키 없는 메시지

파티션 결정 방식과 순서 보장의 근거
키 있음키 없음 (null)
무엇인가murmur2(key) % numPartitions결정적기본 파티셔너의 sticky batching
어디 설정인가ProducerRecord의 key 인자. 파티셔너는 partitioner.class(기본 null = 내장 로직)
언제 발동하는가매 전송 시 해시 계산배치가 마감되면 다음 파티션으로 전환
혼동 시 결과파티션 수를 늘리면 같은 키가 다른 파티션으로 가 순서가 깨집니다같은 엔티티의 이벤트가 여러 파티션에 흩어져 순서 보장이 사라집니다
출제 형태"키 없는 메시지는 어떻게 분배되는가?" — 큰 그림은 "여러 파티션에 나눠 담김"이 맞고, 세부는 레코드 단위 라운드로빈이 아니라 배치 단위 sticky입니다 (2.4 이전 DefaultPartitioner는 라운드로빈)

전달 보장 — 17번부터 21번

17. 멱등 프로듀서 vs 트랜잭션

둘 다 중복을 다루지만 범위가 다릅니다
멱등 프로듀서트랜잭션
무엇인가PID + 파티션별 시퀀스 번호로 재시도 중복 제거여러 파티션·토픽 쓰기와 오프셋 커밋의 원자성
어디 설정인가프로듀서 enable.idempotence=true (기본값)프로듀서 transactional.id + API 호출. 컨슈머 isolation.level도 필요
언제 발동하는가재시도로 같은 배치가 다시 도착할 때 브로커가 폐기commitTransaction() 시점에 일괄 가시화
혼동 시 결과멱등성만으로 EOS가 된다고 오해합니다. 멱등성은 한 세션 × 한 파티션만 커버하고, 애플리케이션이 두 번 send()한 것이나 프로듀서 재시작은 막지 못합니다
출제 형태"EOS에 필요한 것을 모두 고르시오" — 멱등성만 고르면 오답

18. at-least-once vs exactly-once

설정 조합과 실제 결과
at-least-once (기본 동작)exactly-once
무엇인가유실 없음, 중복 가능Kafka 경계 안에서 정확히 한 번
어디 설정인가프로듀서 acks=all + 컨슈머 처리 후 커밋프로듀서 transactional.id + 컨슈머 read_committed + sendOffsetsToTransaction. Streams는 processing.guarantee=exactly_once_v2
언제 발동하는가재시도·리밸런스 시 중복이 발생할 수 있음트랜잭션 커밋 단위로
혼동 시 결과EOS를 켰다고 컨슈머 멱등성을 생략하면, 외부 시스템에는 여전히 중복이 갑니다. 그리고 EOS는 처리량·지연 비용이 있습니다
출제 형태"기본 설정에서 얻는 보장은?" → at-least-once

19. read_uncommitted vs read_committed

isolation.level은 컨슈머 설정입니다
read_uncommitted (기본값)read_committed
무엇인가high watermark까지 전부 읽음 (중단된 트랜잭션 포함)LSO(Last Stable Offset)까지, 커밋된 것만
어디 설정인가컨슈머 isolation.level. 프로듀서 설정이 아닙니다
언제 발동하는가항상진행 중 트랜잭션이 있으면 그 뒤에 커밋된 메시지까지 대기
혼동 시 결과프로듀서만 트랜잭션을 쓰고 컨슈머를 기본값으로 두면 abort된 데이터가 하위 시스템으로 갑니다. 반대로 read_committed에서 긴 트랜잭션이 열려 있으면 지연이 폭증합니다
출제 형태"트랜잭션을 썼는데 취소된 데이터가 들어갔다" → 컨슈머 설정 누락. "컨트롤 레코드는 애플리케이션에 보이는가?" → 아니오(오프셋은 소비)

20. Kafka 내부 EOS vs 외부 시스템

가장 흔한 오해 — 보장의 경계
Kafka → KafkaKafka → 외부 DB · API
무엇인가consume-transform-produce가 한 트랜잭션외부 호출은 트랜잭션 밖
어디 설정인가프로듀서·컨슈머·Streams 설정으로 달성설정으로 해결 불가. 애플리케이션 코드가 멱등해야 함
언제 발동하는가커밋 시점에 원자적으로 가시화재시도할 때마다 외부에 다시 호출
혼동 시 결과"EOS를 켰으니 결제가 두 번 되지 않는다"고 믿고 멱등 키를 넣지 않아 이중 결제가 발생합니다
출제 형태"Kafka EOS로 막을 수 없는 것은?" → 외부 시스템 중복. 대응은 멱등 키 · UPSERT · dedup 저장소

21. high watermark vs LEO vs committed offset

세 지점을 섞으면 lag 계산이 전부 틀립니다
committed offsethigh watermarkLEO
무엇인가컨슈머 그룹이 커밋한 위치ISR 전원이 복제를 마친 상한리더가 기록한 마지막 다음 위치
어디 설정인가설정 아님 — __consumer_offsets에 저장설정 아님 — 리더가 ISR 최소 LEO로 계산설정 아님 — 로그의 끝
언제 발동하는가커밋할 때 갱신ISR 복제가 진행될 때 전진리더가 append할 때 전진
혼동 시 결과lag = high watermark − committed offset입니다. LEO로 계산하면 아직 복제 중이라 읽을 수도 없는 레코드를 lag에 포함시켜 과대 계산합니다
출제 형태"컨슈머가 읽을 수 있는 상한은?" → high watermark. HW와 LEO 사이 구간은 컨슈머에게 보이지 않습니다

크기와 스토리지 — 22번부터 26번

22. max.request.size vs message.max.bytes vs fetch.max.bytes

이름이 비슷하고 소속이 전부 다릅니다
max.request.sizemessage.max.bytesfetch.max.bytes
무엇인가프로듀서 요청 크기 상한. 1048576브로커가 허용하는 배치 크기. 1048588컨슈머 fetch 응답 상한. 52428800
어디 설정인가프로듀서브로커 (토픽은 max.message.bytes)컨슈머
언제 발동하는가전송 직전, 클라이언트에서브로커가 배치를 받을 때 (압축 후 기준)fetch 요청 크기 산정 시
혼동 시 결과큰 메시지를 허용하려면 4곳을 모두 올려야 합니다 — 토픽 max.message.bytes, 프로듀서 max.request.size, 컨슈머 max.partition.fetch.bytes, 브로커 replica.fetch.max.bytes. 마지막을 빼먹어도 복제가 멈추거나 ISR이 줄지는 않습니다 — fetch 계열은 하드 상한이 아니라 큰 배치도 진행 보장을 위해 그대로 반환되기 때문입니다. 대신 fetch 응답당 배치 1건으로 떨어져 복제 처리량이 무너집니다. 하드 게이트는 프로듀서 max.request.size와 브로커 message.max.bytes(토픽 max.message.bytes) 둘뿐입니다
출제 형태matching(설정↔소속)과 "1.5MB를 보내려면 무엇을 바꿔야 하는가(모두 고르시오)". 1048576과 1048588의 12바이트 차이도 출제 대상

23. retention vs compaction (cleanup.policy)

무엇이 남는가가 다릅니다
delete (기본값)compact
무엇인가기간·크기를 넘긴 세그먼트를 삭제키별 최신 값만 유지
어디 설정인가토픽 cleanup.policy (브로커 기본값도 존재). compact,delete 조합 가능
언제 발동하는가retention.ms/retention.bytes 초과 + 세그먼트 마감dirty ratio가 min.cleanable.dirty.ratio(0.5)를 넘으면 백그라운드 클리너가. 활성 세그먼트는 제외
혼동 시 결과상태 토픽에 delete가 남아 상태가 사라집니다이벤트 토픽에 compact를 걸어 이력이 사라집니다. 그리고 키가 없으면 컴팩션이 동작하지 않습니다
출제 형태"컴팩션 토픽인데 같은 키의 옛 값이 보인다" → 활성 세그먼트 + 백그라운드 동작. "즉시 하나만 남는다"는 오답

24. retention.ms vs segment.ms

보관 기간을 줄였는데 디스크가 안 줄어드는 이유
retention.mssegment.ms
무엇인가보관 기간. 기본 604800000(7일)세그먼트를 마감하는 주기. 기본 604800000(7일)
어디 설정인가토픽토픽 (segment.bytes는 1GiB)
언제 발동하는가마감된 세그먼트에 대해서만 판정이 시간이 지나면 활성 세그먼트를 닫고 새로 만듦
혼동 시 결과retention.ms=3600000(1시간)으로 줄여도 segment.ms가 7일이면 최대 7일치가 남습니다. 삭제 단위가 세그먼트이기 때문입니다
출제 형태"짧은 보관을 실제로 적용하려면?" → segment.ms(또는 segment.bytes)도 함께 줄여야 합니다

25. retention.ms vs delete.retention.ms

둘 다 "retention"이지만 대상이 다릅니다
retention.msdelete.retention.ms
무엇인가일반 레코드의 보관 기간. 604800000tombstone(value=null)의 보관 기간. 86400000(1일)
어디 설정인가토픽 (cleanup.policy=delete에서 의미)토픽 (cleanup.policy=compact에서 의미)
언제 발동하는가세그먼트 마감 후 기간 초과 시컴팩션이 tombstone을 만난 뒤 이 시간이 지나면 tombstone도 제거
혼동 시 결과tombstone이 너무 빨리 사라지면, 오래 멈췄던 컨슈머가 삭제 사실을 보지 못하고 옛 값을 계속 유지합니다 (삭제가 하위로 전파되지 않음)
출제 형태"컴팩션 토픽에서 삭제가 반영되지 않은 컨슈머가 있다" → tombstone 수명 문제

26. 컨슈머 그룹 vs Share Group (KIP-932)

4.2에서 production-ready가 된 새 그룹 종류
컨슈머 그룹Share Group (Queues)
무엇인가파티션을 배타적으로 나눠 소비한 파티션을 여러 컨슈머가 함께 소비
어디 설정인가컨슈머 group.id + subscribe()share consumer API (별도 그룹 종류)
언제 발동하는가컨슈머 수 ≤ 파티션 수까지만 병렬성 증가컨슈머 수가 파티션 수를 넘어도 병렬 처리
혼동 시 결과Share Group은 레코드 단위 ack(ACCEPT / RELEASE / REJECT)과 전달 시도 카운트를 쓰며, 파티션 단위 순서 보장을 제공하지 않습니다. 순서가 필요한 스트림을 Share Group으로 옮기면 순서가 깨집니다
출제 형태"처리 시간 편차가 큰 작업 큐에 적합한 것은?" → Share Group. 버전 사실: 4.1 preview → 4.2 production-ready

스키마 — 27번부터 29번

27. BACKWARD vs FORWARD 호환성 (배포 순서)

어느 쪽을 먼저 배포하는가
BACKWARD (기본값)FORWARD
무엇인가새 스키마로 옛 데이터를 읽을 수 있다옛 스키마로 새 데이터를 읽을 수 있다
어디 설정인가Schema Registry의 subject 단위 호환성 설정 (전역 기본값도 존재)
언제 발동하는가새 스키마 등록 시 검사새 스키마 등록 시 검사
혼동 시 결과컨슈머 먼저 배포. 순서를 뒤바꾸면 컨슈머가 모르는 스키마를 받아 전량 실패프로듀서 먼저 배포
출제 형태"BACKWARD에서 필드를 추가하려면?" → default가 있어야 허용. FORWARD는 default 없는 필드 추가도 허용, 대신 default 없는 필드 삭제는 거부

28. TRANSITIVE vs 비-TRANSITIVE

차이는 비교 대상 하나뿐입니다
BACKWARD / FORWARD / FULL*_TRANSITIVE
무엇인가직전 버전과만 대조등록된 모든 이전 버전과 대조
어디 설정인가Schema Registry subject 호환성 설정
언제 발동하는가v3 등록 시 v2만 검사v3 등록 시 v2, v1 모두 검사
혼동 시 결과비-TRANSITIVE에서 v1→v2→v3로 조금씩 바꾸면 v1과 v3가 호환되지 않을 수 있습니다. 오래된 데이터를 재처리할 때 터집니다
출제 형태"v1 데이터를 v3 컨슈머로 재처리해야 한다. 어느 모드가 필요한가?" → BACKWARD_TRANSITIVE

29. TopicNameStrategy vs RecordNameStrategy

subject 이름을 무엇으로 만드는가
TopicNameStrategy (기본값)RecordNameStrategy
무엇인가subject = {topic}-key / {topic}-valuesubject = 레코드 풀네임
어디 설정인가직렬화기 설정 (key.subject.name.strategy / value.subject.name.strategy)
언제 발동하는가스키마 등록·조회 시 subject 계산같음
혼동 시 결과한 토픽에 여러 종류의 레코드를 넣으면 호환성 검사가 매번 실패합니다같은 레코드 타입이 토픽을 넘어 스키마를 공유하므로, 한 토픽만 바꾸려 해도 전체가 영향받습니다
출제 형태"한 토픽에 여러 이벤트 타입을 담으려면?" → RecordName 또는 TopicRecordName 전략. 절충안이 TopicRecordNameStrategy({topic}-{레코드 풀네임})

Kafka Connect — 30번부터 33번

30. source 커넥터 vs sink 커넥터의 오프셋 저장 위치

Connect 도메인 최다 출제 사실
SourceSink
무엇인가외부 시스템 → Kafka. 소스 시스템의 위치를 기록Kafka → 외부 시스템. Kafka 컨슈머 오프셋을 기록
어디 설정인가워커 offset.storage.topic (standalone은 offset.storage.file.filename)__consumer_offsets — 일반 컨슈머와 동일. 그룹 이름은 connect-{커넥터 이름}
언제 발동하는가offset.flush.interval.ms 기본 60000(1분)마다
혼동 시 결과복구 시 엉뚱한 곳을 초기화해 전량 재수집 또는 재적재가 일어납니다
출제 형태matching(커넥터 종류 ↔ 저장 위치). "sink 커넥터의 lag을 보는 명령은?" → kafka-consumer-groups --describe --group connect-{name}

31. standalone vs distributed Connect

설정을 어떻게 전달하고 상태를 어디에 두는가
standalonedistributed
무엇인가단일 프로세스, 로컬 상태워커 클러스터, Kafka 토픽에 상태 저장
어디 설정인가워커 properties + 커넥터 properties 파일워커 properties + REST API. group.id가 클러스터 이름
언제 발동하는가기동 시 커넥터가 즉시 시작REST로 등록할 때 시작. 워커 변경 시 태스크 재분배
혼동 시 결과distributed에 커넥터 properties를 커맨드라인으로 주면 무시됩니다. standalone은 프로세스가 죽으면 오프셋 파일 외에 모든 상태가 사라집니다
출제 형태"워커를 재시작하니 커넥터가 사라졌다" → standalone. 내부 토픽 3종은 모두 cleanup.policy=compact이고 config.storage.topic파티션 1개

32. SMT vs Kafka Streams

어디까지 SMT로 할 것인가
SMT (Single Message Transform)Kafka Streams
무엇인가레코드 1건 단위의 stateless 변환상태를 갖는 스트림 처리 애플리케이션
어디 설정인가커넥터 설정 transforms=… (체인, 순서가 결과를 바꿈)별도 애플리케이션 코드
언제 발동하는가source는 converter , sink는 converter 토폴로지 실행 시
혼동 시 결과SMT로 집계·조인을 하려다 막힙니다 — stateless라서 불가능합니다. 반대로 필드 하나 바꾸려고 Streams 앱을 띄우는 것은 과잉입니다
출제 형태"두 토픽을 조인해 적재하려면?" → Streams(또는 ksqlDB). 대표 SMT: InsertField, MaskField, ValueToKey, RegexRouter, Cast, TimestampConverter, Filter

33. errors.tolerance vs errors.retry.timeout

건너뛰는 것과 다시 시도하는 것
errors.toleranceerrors.retry.timeout
무엇인가실패 레코드를 건너뛸지 여부. 기본 none재시도에 쓸 시간 예산. 기본 0(재시도 없음), -1은 무한
어디 설정인가커넥터 설정
언제 발동하는가변환·컨버터·sink 쓰기 실패 시재시도 가능한 실패 시 (지수 백오프, 상한은 errors.retry.delay.max.ms 60000)
혼동 시 결과all만 켜면 일시 장애로도 데이터가 조용히 버려집니다. DLQ는 세 조건이 필요합니다 — errors.tolerance=all + errors.deadletterqueue.topic.name 지정 + sink 커넥터. errors.deadletterqueue.context.headers.enable=true가 없으면 원인 헤더가 없습니다
출제 형태"일시 장애는 재시도, 영구 불량은 격리하려면?" → 둘을 함께 설정 + total-records-skipped 알림

Kafka Streams — 34번부터 38번

34. KStream vs KTable

같은 토픽을 어떻게 해석하는가
KStreamKTable
무엇인가레코드 스트림 — append-only 사실의 연속changelog 스트림 — 키별 최신 상태(upsert)
어디 설정인가builder.stream("topic")builder.table("topic")
언제 발동하는가같은 키가 또 오면 별개 이벤트같은 키가 또 오면 갱신, value=null이면 삭제
혼동 시 결과상태를 스트림으로 읽어 중복 집계이벤트를 테이블로 읽어 이벤트 유실 (합계가 실제보다 작아짐)
출제 형태판단 기준: "같은 키가 반복될 때 두 값이 모두 의미가 있는가". 결제·클릭·센서 = KStream, 프로필·재고·잔액 = KTable

35. KTable vs GlobalKTable

분산인가 전체 복제인가
KTableGlobalKTable
무엇인가파티션 단위로 인스턴스에 분산된 테이블모든 인스턴스가 전체 사본을 가진 테이블
어디 설정인가builder.table(...)builder.globalTable(...)
언제 발동하는가조인 시 co-partitioning 필요조인 시 co-partitioning 불필요. KeyValueMapper로 키가 아닌 값으로도 조인 가능
혼동 시 결과큰 테이블을 GlobalKTable로 만들면 인스턴스마다 전체를 적재해 메모리와 시작 시간이 폭증합니다
출제 형태"파티션 수가 다른 참조 데이터와 조인하려면?" → GlobalKTable. 적합한 데이터는 작고 자주 안 바뀌는 마스터

36. map vs mapValues

Streams에서 가장 자주 나오는 쌍
mapmapValues
무엇인가키와 값을 모두 바꿀 수 있는 stateless 변환값만 바꾸는 stateless 변환
어디 설정인가Streams DSL 토폴로지 코드
언제 발동하는가키가 바뀔 수 있으므로 스트림을 "리파티션 필요"로 표시. 실제 리파티션 토픽은 뒤에 키 기반 연산(집계·조인)이 올 때 생성표시하지 않음 → 리파티션 없음
혼동 시 결과값만 바꾸면 되는데 map을 쓰면 불필요한 리파티션 토픽이 생겨 네트워크·디스크·지연이 증가합니다
출제 형태"리파티션을 유발하는 연산을 모두 고르시오" → map, flatMap, selectKey, groupBy, repartition. mapValues·flatMapValues·filter·groupByKey는 아닙니다

37. tumbling vs hopping vs sliding vs session 윈도우

겹치는가, 크기가 고정인가
TumblingHoppingSlidingSession
무엇인가고정 크기, 겹치지 않음고정 크기, advance 간격으로 겹침레코드 기준 고정 간격 구간비활성 gap으로 구분, 크기 가변
어디 설정인가TimeWindows.ofSizeWithNoGraceTimeWindows…advanceBy(…)SlidingWindows.ofTimeDifferenceAndGraceSessionWindows.ofInactivityGap…
언제 발동하는가한 레코드가 1개 윈도우에한 레코드가 size÷advance 개 윈도우에데이터가 있는 구간만gap 안에 이벤트가 오면 세션이 계속 늘어나고, 세션 병합도 일어남
혼동 시 결과Hopping을 Tumbling으로 착각하면 집계가 중복 계산됩니다. …WithNoGrace를 쓰면 지연 도착 레코드가 버려집니다
출제 형태"10분 크기, 5분 advance면 한 레코드는 몇 개 윈도우에?" → 2개. "사용자 활동 구간을 묶으려면?" → session

38. co-partitioning vs repartition()

요구사항과 그것을 만족시키는 수단
co-partitioningrepartition()
무엇인가조인의 전제 조건 — 공식 요건은 ① 파티션 수 동일 ② 파티셔너 동일 두 개입니다. “키 동일”은 요건이 아니라 equi-join 자체의 전제키 기준으로 다시 분배하는 연산 (리파티션 토픽 생성)
어디 설정인가토픽 설계 · 프로듀서 partitioner.class · StreamPartitioner토폴로지 코드
언제 발동하는가런타임 파티션 할당 단계에서 파티션 수만 검증호출 즉시
혼동 시 결과파티션 수가 다르면 TopologyException이 나지만, 파티셔너가 다른 것은 감지되지 않아 조인이 조용히 누락됩니다. KStream-GlobalKTable 조인과 KTable-KTable 외래키 조인은 co-partitioning이 필요하지 않습니다
출제 형태"파티션 3개와 6개 토픽을 조인하려면?" → 적은 쪽을 6으로 리파티션. KStream-KTable이면 KStream을 리파티션하는 편이 낫습니다(KTable은 상태 저장소가 하나 더 생김)

보안 — 39번과 40번

39. SASL_PLAINTEXT vs SASL_SSL

이름의 PLAINTEXT는 전송 계층을 가리킵니다
SASL_PLAINTEXTSASL_SSL
무엇인가SASL 인증 + 암호화 없음SASL 인증 + TLS 암호화
어디 설정인가클라이언트 security.protocol · 브로커 listeners / listener.security.protocol.map
언제 발동하는가연결 수립 시. 나머지 두 값은 PLAINTEXT(둘 다 없음)와 SSL(암호화 + 선택적 mTLS 인증)
혼동 시 결과SASL 메커니즘 이름 PLAIN과 헷갈려 비밀번호를 평문으로 네트워크에 흘립니다. SASL_PLAINTEXT + PLAIN 조합이 가장 위험합니다
출제 형태"프로덕션에서 인증과 암호화를 모두 원하면?" → SASL_SSL. SASL 메커니즘: PLAIN, SCRAM-SHA-256/512, GSSAPI, OAUTHBEARER

40. 인증(authentication) vs 인가(authorization / ACL)

"누구인가"와 "무엇을 할 수 있는가"
인증 (authentication)인가 (authorization / ACL)
무엇인가연결한 주체가 누구인지 확인그 주체가 무엇을 할 수 있는지 결정
어디 설정인가브로커 listeners · sasl.mechanism · SSL 설정 / 클라이언트 security.protocol브로커 authorizer 설정 + kafka-acls로 부여하는 ACL. super.users는 우회
언제 발동하는가연결 수립 시매 요청마다 (읽기·쓰기·토픽 생성·그룹 참여 각각)
혼동 시 결과인증만 설정하고 ACL을 빠뜨리면 TopicAuthorizationException이 발생합니다. 반대로 인증 없이 ACL만 걸면 주체를 특정할 수 없어 의미가 없습니다
출제 형태"로그인은 되는데 읽기가 거부된다" → 인가(ACL) 문제. 컨슈머는 Topic Read + Group Read 두 ACL이 모두 필요합니다

오답 유도 패턴 분석

위 40쌍은 지식입니다. 이 절은 기술입니다 — 내용을 모르는 상태에서도 선택지의 형태만 보고 함정을 배제하는 방법입니다. 시험 당일 전략의 요약판을 여기서 확장합니다.

패턴 1 — 절대적 표현이 들어간 선택지

"항상", "절대", "모든 경우에", "무조건", "완전히 보장한다", "결코 ~하지 않는다"가 들어간 선택지는 대개 오답입니다. Kafka에는 조건 없는 보장이 거의 없기 때문입니다.

절대적 표현이 붙은 오답 예시와 실제 조건
함정 선택지빠진 조건
"acks=all이면 절대 유실되지 않는다"min.insync.replicas가 1이면 ISR이 1로 줄었을 때 유실됩니다
"Kafka는 항상 순서를 보장한다"순서 보장은 파티션 단위이며 키가 있어야 합니다
"EOS를 켜면 모든 중복이 사라진다"Kafka 경계 안에서만. 외부 시스템은 별개입니다
"컴팩션 토픽에는 키당 레코드가 항상 하나다"활성 세그먼트 제외 + 백그라운드 동작이므로 옛 값이 남습니다
"파티션을 늘리면 무조건 빨라진다"컨슈머 수·파일 핸들·리밸런스 비용·키 분포가 함께 작용합니다

패턴 2 — 설정의 소속을 바꿔치기

이 사이트 전체에서 가장 강조하는 패턴입니다. 설정 이름은 정확한데 소속만 틀려 놓습니다. 아는 이름이 나오면 안심하게 되므로 잘 걸립니다.

소속 바꿔치기 사전 — 왼쪽이 진짜입니다
설정진짜 소속함정으로 붙이는 소속
acks프로듀서브로커 · 토픽
min.insync.replicas브로커 · 토픽프로듀서
isolation.level컨슈머프로듀서 · 브로커
transactional.id프로듀서컨슈머
max.request.size프로듀서브로커
message.max.bytes브로커프로듀서
max.message.bytes토픽프로듀서
fetch.max.bytes · max.partition.fetch.bytes컨슈머브로커
replica.fetch.max.bytes브로커컨슈머
cleanup.policy · retention.ms토픽컨슈머
max.poll.interval.ms · max.poll.records컨슈머브로커
offsets.retention.minutes브로커컨슈머
errors.tolerance · DLQ 설정Connect 커넥터 (sink 전용)브로커 · source 커넥터
processing.guaranteeKafka Streams프로듀서
transaction.state.log.min.isr브로커Streams · 프로듀서

패턴 3 — 기본값을 미묘하게 변형

3.x 기준 값이거나 몇 바이트만 다른 값을 섞습니다. 시중 자료 대부분이 3.x 기준이라 이 함정이 특히 잘 통합니다.

4.3 실제 값과 함정 값
설정4.3 실제함정으로 나오는 값함정의 출처
linger.ms503.x 기본값
acksall12.x 기본값
enable.idempotencetruefalse2.x 기본값
session.timeout.ms4500010000예전 기본값
group.protocolclassicconsumer"KIP-848이 GA니까"라는 오추론
message.max.bytes10485881048576"1MB"로 반올림
isolation.levelread_uncommittedread_committed"트랜잭션이 기본이니까"라는 오추론
processing.guaranteeat_least_onceexactly_once_v2같은 오추론
num.stream.threads1CPU 코어 수"당연히 코어만큼"이라는 추측
num.standby.replicas01"기본적으로 대비되어 있겠지"
errors.retry.timeout0양수"재시도가 기본이겠지"
unclean.leader.election.enablefalsetrue아주 오래된 기본값

패턴 4 — 사실이지만 질문에 답하지 않는 선택지

"가장 적절한(BEST/MOST appropriate)"류 문항에 주로 나옵니다. 선택지 문장 자체는 옳아서 지우기 어렵습니다. 질문의 목적어를 다시 읽는 것이 해법입니다.

예시
질문"옳지만 답이 아닌" 선택지정답 방향
"같은 주문의 상태 변화 순서를 보장하려면?" "acks=all과 멱등성을 켠다" (내구성·중복에 대한 사실) 주문 ID를 키로 지정한다
"컨슈머가 계속 그룹에서 빠진다. 1차 처방은?" "session.timeout.ms를 올린다" (하트비트 축의 사실) max.poll.records를 줄인다
"sink 커넥터의 처리량을 올리려면?" "워커를 추가한다" (확장 방법 중 하나) tasks.max와 입력 파티션 수를 먼저 본다
"값만 변환하는데 리파티션을 피하려면?" "topology.optimization=all로 켠다" (도움은 됨) mapValues를 쓴다

패턴 5 — 과잉 조치 선택지

증상은 사라지지만 데이터 유실이나 큰 부작용이 따르는 선택지입니다. 시험은 대체로 최소 변경으로 원인을 제거하는 답을 정답으로 둡니다.

패턴 6 — 보장의 경계나 동작 시점을 넓혀 놓은 선택지

"어디까지"와 "언제"를 확인하면 걸러집니다
함정 선택지실제 경계
"EOS를 켜면 외부 DB 중복도 막힌다"Kafka 토픽 경계 안에서만
"멱등 프로듀서는 애플리케이션의 이중 send()도 걸러낸다"재시도 중복만. 서로 다른 레코드로 봅니다
"컴팩션은 중복을 즉시 제거한다"백그라운드 + dirty ratio 조건 + 활성 세그먼트 제외
"cleanup.policy를 바꾸면 이미 지워진 데이터가 돌아온다"돌아오지 않습니다
"tasks.max를 올리면 항상 빨라진다"sink는 입력 파티션 수가, source는 커넥터 구현이 상한
"오프셋은 토픽 전체에서 유일하다"파티션 안에서만 의미가 있습니다
"auto.offset.reset은 재시작할 때마다 적용된다"커밋 오프셋이 없거나 범위를 벗어났을 때만
"records-lag-max가 0이면 안전하다"컨슈머가 죽으면 메트릭이 사라져 0처럼 보입니다
"TopologyTestDriver로 리밸런스도 테스트할 수 있다"브로커가 없으므로 불가

패턴 7 — 버전에 따라 답이 달라지는 문항 식별법

선택지 조합으로 버전 문항을 알아채는 방법
선택지에 함께 등장하면묻는 것4.3 기준 정답
05linger.ms의 버전 차이5
1allacks의 버전 차이all
1000045000session.timeout.ms45000
ZooKeeper와 KRaft메타데이터 저장소KRaft 전용 (ZK는 4.0에서 제거)
--zookeeper--bootstrap-serverCLI 옵션--bootstrap-server (--zookeeper는 없는 옵션)
exactly_onceexactly_once_v2Streams 보장 값exactly_once_v2
"2.13"이 Kafka 버전으로 서술버전 표기 이해오답 — 2.13은 Scala 버전입니다

공식 문서 출처

40쌍의 설정 이름·기본값·소속은 모두 Apache Kafka 4.3 공식 문서에서 확인했습니다. 오답 유도 패턴 절은 문항 형태에 대한 분석이며 공식 문서의 서술이 아닙니다.