Kafka μ ν리μΌμ΄μ ν μ€νΈνκΈ°: λ¨μ ν μ€νΈλΆν° ν΅ν© ν μ€νΈκΉμ§
Apache Kafka λ λκ·λͺ¨ λ°μ΄ν° μ€νΈλ¦¬λ° μ ν리μΌμ΄μ μμ λ리 μ¬μ©λλ©°, μ΄λ¬ν μ ν리μΌμ΄μ μ ν μ€νΈ λ λ§€μ° μ€μν©λλ€. μ΄λ² ν¬μ€ν μμλ νλ‘λμμ 컨μλ¨Έμ λ¨μ ν μ€νΈ , Embedded Kafkaλ₯Ό νμ©ν ν΅ν© ν μ€νΈ , Kafka λͺ¨μ κ°μ²΄(Mock) λ₯Ό μ¬μ©ν ν μ€νΈ λ°©λ², κ·Έλ¦¬κ³ λΉλκΈ° μ½λ ν μ€νΈλ₯Ό μν λͺ¨λ² μ¬λ‘μ λν΄ λ€λ£Ήλλ€.
1. νλ‘λμμ 컨μλ¨Έμ λ¨μ ν μ€νΈ
Kafka μ ν리μΌμ΄μ μμ νλ‘λμ μ 컨μλ¨Έ μ λμμ λ¨μ ν μ€νΈ λ‘ νμΈνλ κ²μ λ§€μ° μ€μν©λλ€. Mockito μ κ°μ λͺ¨μ κ°μ²΄(Mock)λ₯Ό νμ©νμ¬ Kafka λΈλ‘컀μμ μ€μ μ°κ²° μμ΄λ λ¨μ ν μ€νΈλ₯Ό μνν μ μμ΅λλ€.
νλ‘λμ λ¨μ ν μ€νΈ μμ
@RunWith(SpringRunner.class)
@SpringBootTest
public class KafkaProducerTest {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@MockBean
private KafkaProducer producer;
@Test
public void testSendMessage() {
String message = "Test message";
kafkaTemplate.send("test_topic", message);
// λ©μλ νΈμΆ νμΈ
verify(producer).send(eq("test_topic"), eq(message));
}
}
컨μλ¨Έ λ¨μ ν μ€νΈ μμ
@RunWith(SpringRunner.class)
@SpringBootTest
public class KafkaConsumerTest {
@MockBean
private KafkaConsumer consumer;
@Test
public void testConsumeMessage() {
String message = "Test message";
// λ©μμ§ μ²λ¦¬ λ©μλ νΈμΆ νμΈ
consumer.consume(message);
verify(consumer).consume(eq(message));
}
}
μ€λͺ :
- @MockBean : Kafka λΈλ‘컀μμ μ€μ ν΅μ μμ΄, νλ‘λμ μ 컨μλ¨Έ λ₯Ό λͺ¨μ κ°μ²΄ λ‘ ν μ€νΈν μ μμ΅λλ€.
- verify() : Mockito λ₯Ό μ¬μ©νμ¬ νΉμ λ©μλκ° νΈμΆλμλμ§ νμΈν©λλ€.
2. Embedded Kafkaλ₯Ό νμ©ν ν΅ν© ν μ€νΈ
Embedded Kafka λ Kafka λΈλ‘컀 λ₯Ό ν μ€νΈ νκ²½μμ μ€μ λ‘ μ€ννμ¬ ν΅ν© ν μ€νΈ λ₯Ό μνν μ μκ² ν©λλ€. μ΄λ₯Ό ν΅ν΄ Kafka λΈλ‘컀μ μ€μ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°μΌλ©° ν μ€νΈν μ μμ΅λλ€.
Embedded Kafka μ€μ λ° ν΅ν© ν μ€νΈ μμ
@RunWith(SpringRunner.class)
@SpringBootTest
@EmbeddedKafka(partitions = 1, topics = {"test_topic"})
public class KafkaIntegrationTest {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@Autowired
private KafkaConsumer consumer;
@Test
public void testSendAndConsumeMessage() throws Exception {
String message = "Test message";
kafkaTemplate.send("test_topic", message);
// 컨μλ¨Έκ° λ©μμ§λ₯Ό λ°μλμ§ νμΈ
Awaitility.await()
.atMost(10, TimeUnit.SECONDS)
.untilAsserted(() -> verify(consumer).consume(eq(message)));
}
}
μ€λͺ :
- @EmbeddedKafka : ν΅ν© ν μ€νΈ μ Kafka λΈλ‘컀 λ₯Ό ν μ€νΈ νκ²½μμ μ€νν©λλ€.
- Awaitility.await() : λΉλκΈ° λ©μμ§ μ²λ¦¬ κ° μλ£λ λκΉμ§ λκΈ°νλ λ©μλμ λλ€.
3. ν μ€νΈμμ Kafka λͺ¨μ κ°μ²΄ μ¬μ©
Mockito μ κ°μ νλ μμν¬λ₯Ό νμ©νμ¬ Kafka λΈλ‘컀μμ μ€μ μ°κ²° μμ΄ λͺ¨μ κ°μ²΄(Mock) λ₯Ό μ¬μ©ν΄ Kafka κΈ°λ₯μ ν μ€νΈν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λΉ λ₯΄κ² λ¨μ ν μ€νΈ λ₯Ό μνν μ μμΌλ©°, μΈλΆ μμ‘΄μ±μ ꡬμ λ°μ§ μκ³ λ 립μ μΌλ‘ ν μ€νΈν μ μμ΅λλ€.
KafkaTemplate λͺ¨μ κ°μ²΄ ν μ€νΈ μμ
@RunWith(SpringRunner.class)
@SpringBootTest
public class KafkaProducerMockTest {
@MockBean
private KafkaTemplate<String, String> kafkaTemplate;
@Test
public void testSendMessage() {
String message = "Mock message";
// KafkaTemplateμ μ¬μ©ν λ©μμ§ μ μ‘ ν
μ€νΈ
kafkaTemplate.send("mock_topic", message);
// λ©μλ νΈμΆ νμΈ
verify(kafkaTemplate).send(eq("mock_topic"), eq(message));
}
}
μ€λͺ :
- KafkaTemplate μ Mock μΌλ‘ μ²λ¦¬νμ¬ μ€μ Kafka λΈλ‘컀 μμ΄ ν μ€νΈν μ μμ΅λλ€.
- verify() λ©μλλ₯Ό ν΅ν΄ λ©μμ§κ° μ±κ³΅μ μΌλ‘ μ μ‘λμλμ§ νμΈν©λλ€.
4. λΉλκΈ° μ½λ ν μ€νΈλ₯Ό μν λͺ¨λ² μ¬λ‘
Kafka μ ν리μΌμ΄μ μ λΉλκΈ° μ²λ¦¬ κ° μΌλ°μ μ΄κΈ° λλ¬Έμ, λΉλκΈ° μ½λλ₯Ό ν¨κ³Όμ μΌλ‘ ν μ€νΈ νλ κ²μ΄ μ€μν©λλ€. λΉλκΈ° μ½λ ν μ€νΈ μ ν μ€νΈ μ€ν¨ λ₯Ό λ°©μ§νκΈ° μν΄ λκΈ° μκ° μ μ μ ν μ€μ νκ±°λ Promise , Future μ κ°μ λΉλκΈ° κ°λ μ λ€λ£¨λ λ°©λ²μ΄ νμν©λλ€.
λΉλκΈ° ν μ€νΈ μμ
@RunWith(SpringRunner.class)
@SpringBootTest
public class KafkaAsyncTest {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@Test
public void testAsyncSendMessage() throws Exception {
CompletableFuture<SendResult<String, String>> future =
kafkaTemplate.send("async_topic", "Async message");
// λΉλκΈ° κ²°κ³Ό νμΈ
SendResult<String, String> result = future.get(5, TimeUnit.SECONDS);
assertNotNull(result.getRecordMetadata());
assertEquals("async_topic", result.getRecordMetadata().topic());
}
}
μ€λͺ :
- CompletableFuture : λΉλκΈ° μμ μ΄ μλ£λ λκΉμ§ κΈ°λ€λ¦¬λ©°, λ©μμ§κ° μ μμ μΌλ‘ μ μ‘λμλμ§ νμΈν©λλ€.
- future.get(5, TimeUnit.SECONDS) : μ΅λ 5μ΄ λμ κ²°κ³Όλ₯Ό κΈ°λ€λ¦½λλ€.
Kafka ν μ€νΈ νΈλ λ λ° ν΅κ³
μ΅κ·Ό λ°μ΄ν°μ λ°λ₯΄λ©΄, λκ·λͺ¨ Kafka μ ν리μΌμ΄μ μ μ¬μ©νλ κΈ°μ λ€μ λ¨μ ν μ€νΈ μ ν΅ν© ν μ€νΈ λ₯Ό μ κ·Ήμ μΌλ‘ λμ νμ¬ ν μ€νΈ 컀λ²λ¦¬μ§ λ₯Ό 70% μ΄μ λ¬μ±νκ³ μμ΅λλ€. νΉν Embedded Kafka λ₯Ό νμ©ν ν΅ν© ν μ€νΈλ μ€μ λΈλ‘컀 νκ²½ μμμ ν μ€νΈλ₯Ό κ°λ₯νκ² νμ¬ μ λ’°μ± μ ν¬κ² λμ¬μ€λλ€.
μμ£Ό 묻λ μ§λ¬Έ (FAQ)
Q1. Kafka νλ‘λμμ 컨μλ¨Έμ λ¨μ ν
μ€νΈλ μ΄λ»κ² μ§ννλμ?
A1. Mockito μ κ°μ λͺ¨μ κ°μ²΄λ₯Ό μ¬μ©νμ¬ μ€μ Kafka λΈλ‘컀μ μ°κ²°νμ§ μκ³ , KafkaTemplate κ³Ό KafkaListener λ₯Ό MockμΌλ‘ μ²λ¦¬νμ¬ λ¨μ ν
μ€νΈλ₯Ό μ§νν μ μμ΅λλ€.
Q2. Embedded Kafkaλ₯Ό νμ©ν ν΅ν© ν
μ€νΈμ μ₯μ μ 무μμΈκ°μ?
A2. Embedded Kafka λ ν
μ€νΈ νκ²½μμ μ€μ Kafka λΈλ‘컀λ₯Ό μ€ννμ¬ ν΅ν© ν
μ€νΈ λ₯Ό μνν μ μκ² ν©λλ€. μ΄λ₯Ό ν΅ν΄ νλ‘λμμ 컨μλ¨Έ κ°μ μ€μ λ°μ΄ν° μ μ‘ μ ν
μ€νΈν μ μμ΅λλ€.
Q3. Kafka μ ν리μΌμ΄μ
μμ λΉλκΈ° μ½λλ₯Ό μ΄λ»κ² ν
μ€νΈνλμ?
A3. Awaitility λ CompletableFuture μ κ°μ λΉλκΈ° μ²λ¦¬ λ©μ»€λμ¦μ μ¬μ©νμ¬ λΉλκΈ° μ½λ κ° μλ£λ λκΉμ§ κΈ°λ€λ¦¬κ³ , κ²°κ³Όλ₯Ό νμΈνλ λ°©μμΌλ‘ ν
μ€νΈν μ μμ΅λλ€.
Q4. Kafka λͺ¨μ κ°μ²΄(Mock)λ₯Ό μ¬μ©νλ©΄ μ΄λ€ μ΄μ μ΄ μλμ?
A4. Kafka λͺ¨μ κ°μ²΄ λ₯Ό μ¬μ©νλ©΄ μ€μ Kafka λΈλ‘컀μ μ°κ²°ν νμ μμ΄, νλ‘λμ μ 컨μλ¨Έ μ λμμ λ
립μ μΌλ‘ ν
μ€νΈν μ μμ΄ λΉ λ₯΄κ³ κ°λ¨νκ² ν
μ€νΈ λ₯Ό μ§νν μ μμ΅λλ€.
Q5. ν
μ€νΈμμ Kafka λΈλ‘컀 μμ΄ Mockμ μ¬μ©νλ κ²μ΄ μμ νκ°μ?
A5. λ¨μ ν
μ€νΈ μμλ Kafka λΈλ‘컀 μμ΄ λͺ¨μ κ°μ²΄ λ₯Ό μ¬μ©ν΄λ μμ ν©λλ€. κ·Έλ¬λ ν΅ν© ν
μ€νΈ λ μμ€ν
ν
μ€νΈ μμλ Embedded Kafka λ₯Ό μ¬μ©νμ¬ μ€μ λΈλ‘컀μμ μνΈμμ©μ ν
μ€νΈνλ κ²μ΄ μ’μ΅λλ€.
λκΈ