Conversation
📝 WalkthroughSummary by CodeRabbit릴리스 노트
🔍 Walkthrough게스트 티켓 이메일 발송 시스템을 개선하기 위해 전용 예외 클래스를 추가하고, 다중 파트 이메일 콘텐츠(평문 + HTML) 지원, QR 코드 첨부, 한글 폰트 유틸리티를 도입했습니다. 📋 Changes
🎯 Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 📌 Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (1 warning, 2 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/com/permitseoul/permitserver/domain/admin/guestticket/api/service/AdminGuestTicketService.java (1)
37-62:⚠️ Potential issue | 🟠 Major이메일 발송 실패 시 티켓 상태 관리 문제 - 부분 실패 데이터 정합성 이슈
issueGuestTickets()메서드에는@Transactional어노테이션이 없으며, 각 반복마다saveGuestTickets()호출 시 티켓이 DB에 저장되고 즉시 커밋됩니다. 이메일 발송 실패 시:
- 이미 저장된 게스트의 티켓은
updateGuestTicketToReadyStatus()호출 전에 DB에 커밋된 상태GuestEmailSendException발생 시updateGuestTicketToReadyStatus()(51번 라인)에 도달하지 않음- 예외가 던져지며 루프 종료
- 실패한 게스트의 티켓은 DB에 존재하지만 상태 업데이트 없이 남음
트랜잭션 경계 추가 또는 부분 실패 시 보상(compensation) 로직 검토가 필요합니다.
🤖 Fix all issues with AI agents
In
`@src/main/java/com/permitseoul/permitserver/domain/admin/util/GuestTicketEmailSender.java`:
- Around line 88-91: The catch block in GuestTicketEmailSender that logs toEmail
and guestName must avoid writing PII; replace those values in the log with
either masked versions (e.g., maskLocalPart(toEmail)) or a non-identifying
internal id, and update the log statement in the catch of send (references:
toEmail, guestName, log.error call) to only include non-PII fields and the
exception message/stack; also throw the GuestEmailSendException with the
original exception as the cause (new GuestEmailSendException(e)) so debugging
retains the root cause while keeping logs PII-free.
🧹 Nitpick comments (4)
src/main/java/com/permitseoul/permitserver/domain/admin/util/GuestTicketEmailSender.java (2)
74-74: 주석 처리된 코드 정리 필요주석 처리된
helper.setSubject(...)코드가 남아 있습니다. 더 이상 사용하지 않으므로 제거하는 것이 좋습니다.
77-83: 첨부파일과 인라인 이미지를 동일한 소스로 추가하는 방식 확인동일한
ByteArrayResource를 인라인(addInline)과 첨부(addAttachment)에 모두 사용하고 있습니다.ByteArrayResource는 반복 읽기가 가능하므로 기능적으로는 문제가 없으나, 이메일 용량이 QR 이미지 수 × 2배로 증가합니다. 티켓 수가 많을 경우 이메일 크기 제한에 주의하세요.src/main/java/com/permitseoul/permitserver/domain/admin/util/PngFontUtil.java (1)
14-25: 폰트 파일은 정상 배포되지만 폴백 폰트 전략 개선 권장
NotoSansKR-Regular.ttf파일은src/main/resources/fonts/디렉토리에 정상적으로 포함되어 있으므로, Maven 빌드 시 자동으로 JAR에 포함됩니다. 다만, 파일 로딩 실패 시SansSerif폴백 폰트는 한국어 글리프를 지원하지 않아 QR 코드 위의 이벤트명이 깨질 수 있습니다.예외 발생 시에도 한국어 렌더링을 보장하기 위해 다음을 고려하세요:
DejaVu Sans등 한글을 지원하는 폴백 폰트 사용- 또는 폰트 로딩 실패 시 더 강한 에러 처리 (예: 초기화 실패 로깅)
src/main/java/com/permitseoul/permitserver/domain/admin/guestticket/core/exception/GuestEmailSendException.java (1)
1-4: 예외 원인(cause)을 명시적으로 전달할 수 있도록 생성자를 추가하면 좋습니다.현재
GuestTicketCoreException이RuntimeException을 상속하고 있어 기술적으로는new GuestEmailSendException(cause)로 원본 예외를 전달할 수 있습니다. 다만 명시적 생성자가 없어 이 기능이 드러나지 않습니다. 또한GuestTicketEmailSender에서 원본 예외를 로깅하고 있으므로 정보 손실은 없는 상태입니다.코드 가독성과 의도를 명확히 하기 위해 다음과 같이 생성자를 추가하는 것을 권장합니다:
♻️ 명시적 생성자 추가 제안
public class GuestEmailSendException extends GuestTicketCoreException { + public GuestEmailSendException() { + super(); + } + + public GuestEmailSendException(final Throwable cause) { + super(cause); + } }이후
GuestTicketEmailSender에서throw new GuestEmailSendException(e);로 원본 예외를 명시적으로 전달하면 예외 체인이 유지됩니다.
| } catch (Exception e) { | ||
| log.error("[Guest Ticket Email] 발송 실패 - to={}, guestName={}, event={}, ticketCount={}", | ||
| toEmail, guestName, eventName, ticketCodes.size(), e); | ||
| throw new GuestEmailSendException(); |
There was a problem hiding this comment.
에러 로그에 이메일(PII) 포함 — 개인정보 유출 위험
Line 89-90에서 toEmail과 guestName을 에러 로그에 직접 기록하고 있습니다. 이메일 주소와 이름은 개인식별정보(PII)이며, 로그 시스템에 저장될 경우 GDPR/개인정보보호법 위반 가능성이 있습니다.
이메일은 마스킹 처리하거나, 식별 가능한 내부 ID로 대체하는 것을 권장합니다. 또한, new GuestEmailSendException()에 원인 예외(e)를 전달하면 디버깅이 용이합니다.
🛡️ PII 마스킹 및 예외 원인 전달 제안
} catch (Exception e) {
- log.error("[Guest Ticket Email] 발송 실패 - to={}, guestName={}, event={}, ticketCount={}",
- toEmail, guestName, eventName, ticketCodes.size(), e);
- throw new GuestEmailSendException();
+ log.error("[Guest Ticket Email] 발송 실패 - event={}, ticketCount={}",
+ eventName, ticketCodes.size(), e);
+ throw new GuestEmailSendException(e);
}🤖 Prompt for AI Agents
In
`@src/main/java/com/permitseoul/permitserver/domain/admin/util/GuestTicketEmailSender.java`
around lines 88 - 91, The catch block in GuestTicketEmailSender that logs
toEmail and guestName must avoid writing PII; replace those values in the log
with either masked versions (e.g., maskLocalPart(toEmail)) or a non-identifying
internal id, and update the log statement in the catch of send (references:
toEmail, guestName, log.error call) to only include non-PII fields and the
exception message/stack; also throw the GuestEmailSendException with the
original exception as the cause (new GuestEmailSendException(e)) so debugging
retains the root cause while keeping logs PII-free.
🔥Pull requests
⛳️ 작업한 브랜치
👷 작업한 내용
🚨 참고 사항