Skip to content

Refactor/#66 chatbot api - #69

Closed
docodocod wants to merge 3 commits into
mainfrom
refactor/#66-chatbot-api
Closed

Refactor/#66 chatbot api#69
docodocod wants to merge 3 commits into
mainfrom
refactor/#66-chatbot-api

Conversation

@docodocod

Copy link
Copy Markdown
Contributor

📢 기능 설명

챗봇 기능 확장 및 쿠폰 조회 버그 수정
챗봇 코드리뷰 반영 및 가드레일 추가

필요시 실행결과 스크린샷 첨부

연결된 issue

연결된 issue를 자동을 닫기 위해 아래 {이슈넘버}를 입력해주세요.

close #66

✅ 체크리스트

  • PR 제목 규칙 잘 지켰는가?
  • 추가/수정사항을 설명하였는가?
  • 이슈넘버를 적었는가?

johe00123 and others added 3 commits May 15, 2026 22:35
- 취소/노쇼 예약 내역 조회 AI Tool 추가
- 주변 인기 맛집 추천 AI Tool 추가 (반경 3km, 인기순 정렬)
- 예약 가능 시간대 조회 AI Tool 추가
- 챗봇 요청에 위치 좌표(latitude/longitude) 필드 추가
- 쿠폰 목록 API Cache-Control: no-store 추가
- 챗봇 대화 내역 조회 시 세션 없으면 빈 목록 반환으로 수정
- SecurityConfig ASYNC DispatcherType 설정 제거

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- N+1 쿼리 제거: PENDING orderId 조회 IN 쿼리 1회로 교체 (PaymentRepository)
- DB 레벨 필터링: findAllByUserAndStatusIn 추가로 메모리 필터 제거 (ReservationRepository)
- DB 레벨 매장 조회: findByStoreNameIgnoreCaseAndIsDeletedFalse 추가 (StoreRepository)
- ThreadLocal 누수 방지: PendingPaymentHolder.clear() try-finally로 보장 (ChatbotService)
- 챗봇 시스템 프롬프트 가드레일 6항목 추가 (역할고정, 범위제한, 프롬프트보호, 타인정보보호, 역할극거부, 개인정보수집금지)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@docodocod docodocod closed this May 18, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request significantly enhances the chatbot's functionality by introducing location-aware store searches, reservation management tools (viewing and canceling), and a more sophisticated AI prompting system that includes history summarization and strict guardrails. It also implements a ThreadLocal mechanism to capture pending payment information during AI-driven reservation creation. Review feedback highlights several areas for improvement: ensuring store name uniqueness to prevent runtime exceptions, refactoring duplicated payment creation logic into a reusable method, externalizing hardcoded search radius values, and optimizing string concatenation in the history summarization logic for better performance.

@Query("SELECT s.storeName FROM Store s WHERE s.isDeleted = false AND LOWER(s.storeName) LIKE LOWER(CONCAT('%', :name, '%')) ORDER BY s.storeName ASC")
List<String> findNamesByNameContaining(@Param("name") String name, Pageable pageable);

Optional<Store> findByStoreNameIgnoreCaseAndIsDeletedFalse(String storeName);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

findByStoreNameIgnoreCaseAndIsDeletedFalse 메서드는 Optional<Store>를 반환하므로 매장 이름이 유일하다고 가정합니다. 하지만 데이터베이스 수준에서 매장 이름에 유니크 제약 조건이 없다면, 동일한 이름을 가진 매장이 중복 등록될 경우 NonUniqueResultException이 발생하여 챗봇 서비스 전체가 중단될 위험이 있습니다. 매장 이름의 유일성을 보장하거나, 중복 가능성이 있다면 List를 반환하도록 수정이 필요합니다.

Comment on lines +117 to +123
String orderId = "CATCH-" + saved.getId() + "-" + System.currentTimeMillis();
Payment payment = Payment.builder()
.reservation(saved)
.orderId(orderId)
.amount(DEPOSIT_AMOUNT)
.build();
paymentRepository.save(payment);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

createReservationFromAi 메서드와 create 메서드(208-214행)에서 Payment 객체를 생성하고 저장하는 로직이 완전히 동일합니다. 코드 중복을 제거하고 로직의 일관성을 유지하기 위해 이를 별도의 private 메서드(예: createAndSavePayment)로 추출하는 것을 권장합니다.


double latitude = ((Number) lat).doubleValue();
double longitude = ((Number) lon).doubleValue();
double radiusMeters = 3000;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

검색 반경인 radiusMeters 값이 3000으로 하드코딩되어 있습니다. 이 값을 상수로 정의하거나 설정 파일에서 주입받도록 하여 유지보수성을 높이는 것이 좋습니다. 또한, AI가 사용자의 의도에 따라 검색 범위를 조절할 수 있도록 파라미터로 노출하는 방안도 고려해 보시기 바랍니다.

List<ChatMessage> older = history.subList(0, history.size() - SUMMARY_KEEP_RECENT);
String historyText = older.stream()
.map(m -> (m.getRole() == MessageRole.USER ? "사용자" : "AI") + ": " + m.getContent())
.reduce("", (a, b) -> a + "\n" + b);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

스트림의 reduce를 사용한 문자열 결합은 매 단계마다 새로운 문자열 객체를 생성하므로 대화 내역이 많아질수록 성능에 불리할 수 있습니다. java.util.stream.Collectors.joining("\n")을 사용하는 것이 더 효율적이고 가독성 면에서도 우수합니다.

Suggested change
.reduce("", (a, b) -> a + "\n" + b);
.collect(java.util.stream.Collectors.joining("\n"));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[refactor] 챗봇 ai 에이전트 고도화 및 로직 수정

2 participants