인프런 커뮤니티 질문&답변
UserSignedUpEventConsumer 에서 로그 DB 저장 문의
작성
·
37
0
말씀해주신 것처럼 컨슈머 로직 안에 로그를 디비로 저장하는 부분이 비동기 처리를 하기 위해 kafka를 도입하는 것과 상충하지 않는지 의문입니다.
@Service
public class UserSignedUpEventConsumer {
private EmailLogRepository emailLogRepository;
public UserSignedUpEventConsumer(EmailLogRepository emailLogRepository) {
this.emailLogRepository = emailLogRepository;
}
@KafkaListener(
topics = "user.signed-up",
groupId = "email-service",
concurrency = "3"
)
@RetryableTopic(
attempts = "5",
backoff = @Backoff(delay = 1000, multiplier = 2),
dltTopicSuffix = ".dlt"
)
public void consume(String message) throws InterruptedException {
UserSignedUpEvent userSignedUpEvent = UserSignedUpEvent.fromJson(message);
String receiverEmail = userSignedUpEvent.getEmail();
String subject = userSignedUpEvent.getName() + "님, 회원 가입을 축하드립니다!";
Thread.sleep(3000);
System.out.println("이메일 발송 완료");
EmailLog emailLog = new EmailLog(
userSignedUpEvent.getUserId(),
receiverEmail,
subject
);
emailLogRepository.save(emailLog);
}
}
이 부분을 실무레벨에서 해결한다면 어떤 방법이 있는지 궁금합니다.
답변 2
0
안녕하세요 ! 질문 잘 해주셨어요 ~
질문해주신 내용에 답변 드려볼게요 !
우선 컨슈머 안에서 DB 저장을 하는 것 자체가 Kafka 도입 목적과 완전히 상충하는 것은 아니지만, 컨슈머가 해야 할 일이 너무 무거워지면 Kafka를 붙인 장점이 줄어들 수는 있어요 ~
UserService는 회원가입 DB 저장 후 user.signed-up 이벤트를 발행하고, EmailService 쪽에서 이를 받아 처리하도록 분리되어 있어서, UserService와 EmailService를 비동기로 분리했다는 점 자체는 잘 살아 있어요 !
다만 EmailService 내부로 들어와 보면, @KafkaListener 안에서 이메일 발송 작업을 하고, 그 다음 EmailLog를 생성해서 emailLogRepository.save(emailLog)로 저장하고 있어요 ! 또 재시도와 DLT도 함께 붙어 있죠 !
즉 현재 구조는 “서비스 간 비동기”는 맞지만, “컨슈머 내부 처리”는 동기적으로 순차 실행되는 구조라고 보시면 돼요 ~
"실무레벨에서 해결한다면 어떤 방법이 있는지 궁금합니다."
-> 실무에서도 컨슈머 내부에서 이메일 발송 후 바로 DB에 로그를 저장하는 패턴을 많이 사용해요 !
다만 이메일 발송 자체가 실패했을 때에도 로그가 저장되는 문제가 생길 수 있어서, 실무에서는 이메일 발송 성공 여부를 EmailLog에 함께 기록하거나, 발송 성공 시에만 저장하도록 예외 처리를 세밀하게 가져가는 방식을 많이 써요 ~
그리고 이미 @RetryableTopic과 DLT를 활용해서 재시도 및 실패 메시지 처리 로직을 넣어두었기 때문에, 이 구조 자체가 실무에서도 충분히 탄탄한 패턴이라고 보시면 돼요 :)
추가로 궁금하신 점 있으시면 언제든 편하게 질문 남겨주세요~~
0
안녕하세요, 인프런 AI 인턴입니다. luxleo님!
Kafka 컨슈머 로직에서 로그를 DB에 저장하는 부분이 비동기 처리를 목표로 하는 Kafka의 사용 목적과 상충할 수 있다는 의문을 가지고 계신 것 같습니다. DB에 동기적으로 저장하는 연산 때문에 전체 처리 속도가 저하될 수 있기 때문입니다. 이를 실무에서 해결하기 위한 방법에는 여러 가지 접근이 가능하며, 아래에 몇 가지 방향을 제안드립니다.
1. 비동기 저장 방식 사용
- 비동기 처리를 위한 메시지 큐 사용: 이메일 발송 로그를 직접 DB에 저장하는 대신, 별도의 메시지 큐(Kafka나 RabbitMQ 등)를 사용하여 로그 저장 요청을 큐에 쌓고, 이를 처리하는 별도의 컨슈머가 비동기적으로 DB에 저장하도록 설계할 수 있습니다. 이를 통해 처리량이 많은 경우에도 빠르게 반응할 수 있습니다.
2. 배치 처리
- 배치로 로그 저장: 일정량의 로그가 쌓이면 한 번에 DB에 저장하는 배치 처리를 통해 성능을 최적화할 수 있습니다. 이는 DB로의 네트워크 호출을 줄여주고, 부하를 더 예측 가능한 수준으로 유지할 수 있게 됩니다.
3. 개선된 DB 설정 및 사용
- DB 트랜잭션 및 연결 최적화: 데이터베이스 연결 설정을 최적화하거나, 고성능 DB 인스턴스를 사용하여 저장 시간을 단축할 수 있습니다. 이를 통해 이메일 로그 저장 시의 오버헤드를 줄일 수 있습니다.
4. 캐싱 사용
- 로그 캐싱: 실제 DB에 저장하기 전에 메모리나 Redis 같은 인메모리 데이터 저장소에 임시로 저장하여 동시성 처리 능력을 높일 수 있습니다. 캐싱을 통해 실시간 조회 성능과 병목 문제를 해소할 수 있습니다.
추가 자료
위에서 제안한 방법들은 각각의 장단점이 있으므로, 실제 시스템의 요구사항과 상황에 맞춰 선택하는 것이 중요합니다. 관련된 좀 더 심화된 적용 사례는 아래 유사한 질문에서 찾을 수 있습니다:
이 정보들이 luxleo님의 시스템 설계와 성능 최적화에 도움이 되기를 바랍니다. 현재 베타 기능으로서 만족스럽지 않을 수 있습니다만, 추가적으로 궁금하신 점이 있다면 언제든지 이어서 질문해 주세요. 곧 지식공유자께서 자세히 답변해 주실 것입니다. 🙏




