Conversation
Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This reverts commit 3ca826f.
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * chore: 도커 설정파일에 레디스 추가 --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Baek jonghyun <69610809+jong-0126@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * chore: 도커 설정파일에 레디스 추가 * feat: Jwt 토큰 로그인과 Oauth 기본설정 * fix: 오류수정 * fix: 생성자 누락값 수정 * fix: 생성자 누락값 수정 * chore: 코드정리 * feat: Oauth 구조 변경중.. * feat: 카카오톡 로그인 + jwt 생성 테스트 * feat: 레디스 설정추가 * chore: 코드 정리 * refactor: OAuth2LoginSuccessHandler 책임분리 * refactor: 필터에서 이중작업 정리 --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Baek jonghyun <69610809+jong-0126@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * Revert "Create run-test.yaml" This reverts commit 3ca826f. * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * CI/CD AWS 연동 * CI/CD branches 범위 수정 --------- Co-authored-by: Ksr-ccb <harang4282@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * Revert "Create run-test.yaml" This reverts commit 3ca826f. * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * CI/CD AWS 연동 * CI/CD branches 범위 수정 * CI/CD AWS 연동 --------- Co-authored-by: Ksr-ccb <harang4282@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* feat(build.gradle): validation 의존성 추가 * feat : CreateQuizDto 생성 * feat : QuizCategoryRepository 추가 * feat(QuizService) : json 파일 데이터 Quiz 엔티티로 변환 후 저장 기능 추가 * feat : QuizCategory 예외 코드 추가 * feat : uploadQuizJson에 예외 코드 사용' 추가 * feat(QuizController) : quiz 업로드 api 추가 * feat(QuizController) : QuizService의 uploadQuizJson 연동 * Ignore application-local.properties * feat : 카테고리 타입 생성 api 추가 * refactor(QuizCategoryService) : 메서드 isPresent로 변경 * refactor : 코드래빗 피드백 기반 누락 및 오타 수정 * docker-compose.yml 케시 삭제
* chore: AuthUser, Role 클래스 global.dto 패키지로 이동 * chore: OAuth 패키지 이름 변경 * chore: 주석 및 띄어쓰기 수정 * feat: OAuth2 응답객체 생성 및 수정 * refactor: OAuth2 서비스 로직 리팩토링 * chore: 임시 랜딩페이지 추가 * chore: Role 클래스를 user.entity 패키지로 이동 * refactor: 소셜정보 가져올 때, 예외처리 추가
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * Revert "Create run-test.yaml" This reverts commit 3ca826f. * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * CI/CD AWS 연동 * CI/CD branches 범위 수정 * CI/CD AWS 연동 * CI/CD AWS 연동 * CI/CD AWS 연동 * 수정 * commit * 환경변수로 수정 * commit * deploy.yml 수정 * commit * deploy 수정 --------- Co-authored-by: Ksr-ccb <harang4282@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* feat: Ai, 서비스 구현 및 Config 추가. 서비스와 빈 생성을 위한 해당 Config 추가. * feat:AiService * refactor: Ai, 서비스 및 컨트롤러 코드 수정. 작성했던 API 명세서에 맞추어 기능 및 동작 수정. * temp : commit for merge * feat: AI, 테스트코드 구현1. * refactor: aiService subscriptionId 반영 --------- Co-authored-by: Kimyoonbeom <kimybeom@naver.com> Co-authored-by: ChoiHyuk <wannabeing@naver.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * chore: 패키지 구조 정리 * feat: 요일->int, int->요일 바꾸기 * feat: 요일->int, int->요일 바꾸기 * chore: docker-compose.yml gitignore 추가 * temp: temp commit for pull * temp: temp commit for pull * feat: 구독 엔티티 구조 변경 및 구독 정보 조회 --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Baek jonghyun <69610809+jong-0126@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * Revert "Create run-test.yaml" This reverts commit 3ca826f. * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * CI/CD AWS 연동 * CI/CD branches 범위 수정 * CI/CD AWS 연동 * CI/CD AWS 연동 * CI/CD AWS 연동 * 수정 * commit * 환경변수로 수정 * commit * deploy.yml 수정 * commit * deploy 수정 * commit * properties 중요정보 환경변수 처리 --------- Co-authored-by: Ksr-ccb <harang4282@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * Revert "Create run-test.yaml" This reverts commit 3ca826f. * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * CI/CD AWS 연동 * CI/CD branches 범위 수정 * CI/CD AWS 연동 * CI/CD AWS 연동 * CI/CD AWS 연동 * 수정 * commit * 환경변수로 수정 * commit * deploy.yml 수정 * commit * deploy 수정 * commit * properties 중요정보 환경변수 처리 * deploy 파일 환경 변수 export --------- Co-authored-by: Ksr-ccb <harang4282@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore: 필요없는 어노테이션 삭제 * chore: 공통응답 DTO 수정 - `@RequiredArgsConstructor`는 빌더를 사용한다면 추후 삭제해야 함 * feat: 구독/구독로그 예외처리 추가 및 수정 * feat: 구독기간 enum 클래스 추가 * chore: 구독로그 엔티티에 누락된 컬럼 추가 및 생성자 수정 * refactor: 구독생성자 수정 및 업데이트메서드 추가 * feat: 구독(Subscription) 생성/수정 로직 추가 - SubscriptionLog도 함께 생성되게 추가 * chore: QuizCategory 엔티티에 Getter 추가 * chore: 공통응답 DTO 빌더 삭제 * refactor: 구독로그 테이블명 변경 → 구독내역(SubscriptionHistory) * refactor: 구독테이블에 N+1(QuizCategory) 문제 수정 문제카테고리(QuizCategory)의 경우, 구독내역이 생성될 때마다 쿼리가 중복되어 발생할 수있다고 판단되어 미리 FetchJoin 설정 * feat: 구독 취소 로직 추가 * refactor: QuizCategory 는 생성하는 것이 아닌 조회하는 방식으로 로직 수정 * chore: 예외처리 간단 수정 * refactor: 이메일 동시성문제를 유니크제약조건과 try-catch로 방지 * chore: 엔티티 수정시간과 시간이 다를 수 있기 때문에 엔티티자체의 수정시간을 사용하도록 변경 * chore: QuizCategoryRepository 알맞는 메서드명으로 변경 * chore: 날짜계산을 Days가 아닌 Month로 변경 `plusMonths()` 함수 사용
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * chore: 패키지 구조 정리 * feat: 요일->int, int->요일 바꾸기 * feat: 요일->int, int->요일 바꾸기 * chore: docker-compose.yml gitignore 추가 * temp: temp commit for pull * temp: temp commit for pull * feat: 구독 엔티티 구조 변경 및 구독 정보 조회 * fix: 충돌수정 및 변수형 일치문제 해결 * feat: 구독취소, 회원탈퇴 * chore: 각 api별 권한 추가 (계속 추가되어야함) * chore: Quiz_category Enum 삭제 * feat: 로그인 회원 마이페이지 확인 (구독로그 포함) * feat: 구독 비활성화, (임시) 업데이트 * test: 구독 조회 비활성화(로그생성은 아직x) 테스트코드, 로그인 마이페이지 기본기능 테스트 기능 * test: 테스트코드수정 * chore: Quiz_category Enum 삭제 후처리 * chore: Dto 이름 수정 및 파일정리 --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Baek jonghyun <69610809+jong-0126@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* feat : 이메일 발송을 위한 SMTP 관련 의존성 추가 * feat : 유연성 및 확장성을 위해 MailConfig 추가 * feat : MimeMessage 기반 Html형식 메일 전송 메서드 추가 * feat(UserService) : 인증 코드 생성 * feat : VerificationCode 서비스, 예외 추가 * feat : 인증코드 검증 성공 시, 인증코드 삭제 기능 추가 * feat : 인증 코드 발급 Controller 클래스 추가 * feat : 인증 코드 발송 기능 추가 * refactor : verify 메서드 반환타입 void로 변경 * feat : 인증 코드 관련 api jwt 검증 제외 설정 * fix : 변경된 에러 코드로 인한 실행 오류 수정 * feat : 피드백 기반 수정 * feat : 인증코드 검증 시도 횟수 추가 * refactor : MailConfig 위치 변경
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * Revert "Create run-test.yaml" This reverts commit 3ca826f. * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * CI/CD AWS 연동 * CI/CD branches 범위 수정 * CI/CD AWS 연동 * CI/CD AWS 연동 * CI/CD AWS 연동 * 수정 * commit * 환경변수로 수정 * commit * deploy.yml 수정 * commit * deploy 수정 * commit * properties 중요정보 환경변수 처리 * deploy 파일 환경 변수 export * 도커 추가하여 배포 * commit * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * commit * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 --------- Co-authored-by: Ksr-ccb <harang4282@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * Revert "Create run-test.yaml" This reverts commit 3ca826f. * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * CI/CD AWS 연동 * CI/CD branches 범위 수정 * CI/CD AWS 연동 * CI/CD AWS 연동 * CI/CD AWS 연동 * 수정 * commit * 환경변수로 수정 * commit * deploy.yml 수정 * commit * deploy 수정 * commit * properties 중요정보 환경변수 처리 * deploy 파일 환경 변수 export * 도커 추가하여 배포 * commit * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * commit * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 --------- Co-authored-by: Ksr-ccb <harang4282@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * Revert "Create run-test.yaml" This reverts commit 3ca826f. * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * ADD workflow * CI/CD AWS 연동 * CI/CD branches 범위 수정 * CI/CD AWS 연동 * CI/CD AWS 연동 * CI/CD AWS 연동 * 수정 * commit * 환경변수로 수정 * commit * deploy.yml 수정 * commit * deploy 수정 * commit * properties 중요정보 환경변수 처리 * deploy 파일 환경 변수 export * 도커 추가하여 배포 * commit * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * commit * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 * 도커 추가하여 배포 --------- Co-authored-by: Ksr-ccb <harang4282@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* temp : commit for merge * feat: chroma 연동, RAG 구조 구현 그에 따른 AiService 파일 수정. * refactor: chroma 연동, RAG 구조 구현 수정.
* build: mysql-connector 버전 업데이트 보안 이슈로 버전 업데이트 * refactor: OAuth2 예외 처리 수정 및 생성 UserException에서 분리했음 * chore: OAuth2 카카오 응답객체 예외처리 수정 * fix: OAuth2 Github 로그인 시, 이메일 누락 방지 로직 추가 accessToken 활용하여 이메일 가져오기 * feat: OAuth2 네이버 로그인 기능 추가 공통 유틸메서드를 제공하기 위해 추상클래스 생성 * chore: OAuth2 추상클래스 적용 * chore: OAuth2 데이터(attributes) 파싱 예외처리 코드 추가 * chore: OAuth2Service를 OAuth2 패키지로 이동 및 패키지명 수정 사용하지 않는 Controller, Service, Repository 삭제 * chore: 간단 로직 수정
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * feat: 문제 추천1 차 * feat: 각 문제별 정답률 계산, 유저 개인의 정답률 계산 * feat: 문제를 내어주는 두가지 방법 * - getTodayQuiz -> getTodayQuizNew (O) - getTodayQuizNew -> getTodayQuiz (X) 둘중에 하나씩만 쓰거나 getTodayQuiz -> getTodayQuizNew 해야함 리턴값은 지금 api 형식으로 만든다고 QuizDto 인데, Quiz로 바꿔서 줄 수 있음 * feat: 문제를 내어주는 두가지 방법 * - getTodayQuiz -> getTodayQuizNew (O) - getTodayQuizNew -> getTodayQuiz (X) 둘중에 하나씩만 쓰거나 getTodayQuiz -> getTodayQuizNew 해야함 리턴값은 지금 api 형식으로 만든다고 QuizDto 인데, Quiz로 바꿔서 줄 수 있음 * test: 문제를 내어주는 두가지 방법 테스트코드 * fix: 포특밧 되돌려줌 * refactor: 정답률 포멧 스케일 통일화 * fix: 오류검증 --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Baek jonghyun <69610809+jong-0126@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* chore : initialize project structure (#2) * chore: initialize project structure * chore: initialize project structure * chore: initialize project structure * fix: 엔티티 오류수정 및 설정파일 오류 수정 * 📝 Add docstrings to `dev` (#3) Docstrings generation was requested by @Ksr-ccb. * #2 (comment) The following files were modified: * `src/main/java/com/example/cs25/domain/ai/exception/AiException.java` * `src/main/java/com/example/cs25/domain/mail/entity/MailLog.java` * `src/main/java/com/example/cs25/domain/mail/exception/MailException.java` * `src/main/java/com/example/cs25/domain/oauth/exception/OauthException.java` * `src/main/java/com/example/cs25/domain/quiz/exception/QuizException.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/entity/UserQuizAnswer.java` * `src/main/java/com/example/cs25/domain/userQuizAnswer/exception/UserQuizAnswerException.java` * `src/main/java/com/example/cs25/domain/users/entity/User.java` * `src/main/java/com/example/cs25/domain/users/exception/UserException.java` * `src/main/java/com/example/cs25/domain/users/vo/Subscription.java` * `src/main/java/com/example/cs25/global/exception/BaseException.java` * `src/main/java/com/example/cs25/global/exception/GlobalExceptionHandler.java` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Create run-test.yaml * Create PULL_REQUEST_TEMPLATE.md * refactor: ERD 수정으로 인한 Entity 수정 (#4) * refactor: ERD 수정으로 인한 Entity 수정. * refactor: ERD 수정으로 인한 Entity 수정2. * chore: 도커 볼륨 구조 변경 --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Baek jonghyun <69610809+jong-0126@users.noreply.github.com> Co-authored-by: crocusia <132359536+crocusia@users.noreply.github.com> Co-authored-by: Kimyoonbeom <101162650+Kimyoonbeom@users.noreply.github.com>
* feat : 깃허브 url Parser 추가 * feat : 크롤링 기능 추가 * feat : 프로젝트 내에 저장 기능 추가 * feat : 크롤링한 파일을 프로젝트 폴더 내에 저장하는 기능 추가 * chore : chroma 설정 주석 해제 * feat : 컨트롤러 추가 * feat : VectorStore에 저장 메서드 추가 * refactor : List<Document> 전역변수에서 지역변수로 변경 * feat : CrawlerController 예외 추가
test: - 정상 체점 후 데이터 저장 - 구독 정보 없는 경우 예외 처리 - 퀴즈 정보 없는 경우 예외 처리
기술스택 부분 오타 수정
* refactor: - 무중단 배포 deploy 스크립트 변경 * refactor: - 무중단 배포 deploy 스크립트 * refactor: - 무중단 배포 deploy 스크립트 추가 * refactor: - 무중단 배포 테스트 * refactor: - 무중단 배포 테스트 * refactor: - 무중단 배포 테스트 * refactor: - 무중단 배포 테스트 * refactor: - 무중단 배포 Blue-Green 방식
* chore: 필터 디렉토리 경로 변경 * refactor: XSS REQUEST 필터링 변경 * fix: 주석추가 * fix: 인덱스 설정 * fix: 토큰 https 설정 * fix: 재첨 오류시 오답률 불러오지못하는 문제 수정
* chore: 필터 디렉토리 경로 변경 * refactor: XSS REQUEST 필터링 변경 * fix: 주석추가 * fix: 인덱스 설정 * fix: 토큰 https 설정 * fix: 재첨 오류시 오답률 불러오지못하는 문제 수정 * fix: 필터 이름 변경
* chore: 필터 디렉토리 경로 변경 * fix: JSON body 텍스트 필드에서만 xss 적용되도록 수정
* refactor:Woker수 queue크기에 따라 자동으로 변화하게 오토스케일링 * refactor: 큐 크기에 따른 워커 수 축소 기능 추가와 조건문 최적화 * refactor: 활성 스레드를 직접 줄이는 스케일 다운 로직 추가 * chore:workflow 오타 제거 * refactor: 자동 스케일링 스레드 분리 및 스레드 안전성 확보
* chore: 필터 디렉토리 경로 변경 * fix: 메일로그 기반으로 서술형 주기 판단, offset을 쿼리문제다가 박았음 * fix: 정답률 계산 - totalCount 0일 때 기본값 처리 및 null-safe 보완 * fix: 서비스 모듈에서 함수 가져오기
* refactor: 중복처리 방지키TTL 설정 * refactor: 매 자정마다 셋 비우는 로직 추가 및 첫 아이템 추가시에만 TTL부여
* refactor : 정답 채점 개선 * refactor : AI 정답 채점 결과 확인 메서드 분리 * feat : 테스트 케이스 추가 및 그에 따른 일부 코드 변경
* feat : 각 발송 전략 별 Bucket 생성 * refactor : 전략키 유효성 검증 로직 별도 메서드로 분리 * feat : Bucket 반환 메서드 추가 * feat : mailContext 클래스 기반 Bucket 사용 적용 * refactor : 불필요한 코드 및 요소 삭제
* feat: build.gradle Brave MCP연동 위한 의존성 추가 * feat:MCP 클라이언트 핵심 모듈 의존성 추가 * feat:application.propoerties에 필요 의존성 추가 * feat: Brave web search 툴을 호출해서 검색 결과를 가져오는 서비스 구현 * refactor: 브레이브 서치 결과 반영할 수 있도록 AiPromptProvider 리팩토링 * refactor: prompt.yaml 브레이브 서치 반영 수정 * Brave Search MCP를 통해 검색한 결과를 기반으로 Document 리스트를 반환하는 서비스 구현 * feat: bravesearch MCP 도입 기능 구현 및 로깅 추가 * chore: 불필요한 의존성 제거 * refactor: 외부 검색 실패 시 에러 처리 추가 * chore: API 키 추가
* refactor:streamworker 오탈자 수정 * refactor: 동적 워커 축소 종료 조건 도입 * chore: 중복 증가 오류 방식 및 인터럽트 종료 일관성 확보
# Conflicts: # cs25-service/src/main/java/com/example/cs25service/domain/security/common/XssRequestWrapper.java
* refactor/ MailLog JPA Distinct 추가 * refactor/ getTodayQuizBySubscription offset 오류 예외처리 추가
Walkthrough이번 변경사항은 메일 발송 전략의 레이트 리미터 구조를 전략별로 분리하고, 오늘의 퀴즈 선정 로직을 리팩토링하며, AI 피드백 서비스의 구조를 개선 및 통합하는 대규모 리팩토링입니다. 추가로, Brave Search MCP 클라이언트 연동, AI 프롬프트 및 피드백 처리 로직 개선, 배포 워크플로우 환경변수 추가, XSS 방어 강화, 로깅 AOP 도입 등이 포함되어 있습니다. Changes
Sequence Diagram(s)Brave Search MCP 연동 및 AI 피드백 생성 (간략 흐름)sequenceDiagram
participant User
participant Controller
participant AiFeedbackStreamProcessor
participant BraveSearchMcpService
participant BraveSearchRagService
participant AiPromptProvider
participant ChatClient
User->>Controller: 답안 제출/평가 요청
Controller->>AiFeedbackStreamProcessor: stream(answerId, ...)
AiFeedbackStreamProcessor->>BraveSearchMcpService: search(query)
BraveSearchMcpService-->>AiFeedbackStreamProcessor: JsonNode 검색결과
AiFeedbackStreamProcessor->>BraveSearchRagService: toDocuments(JsonNode)
BraveSearchRagService-->>AiFeedbackStreamProcessor: List<Document>
AiFeedbackStreamProcessor->>AiPromptProvider: getFeedbackUser(..., docs, braveResults)
AiPromptProvider-->>AiFeedbackStreamProcessor: 프롬프트 생성
AiFeedbackStreamProcessor->>ChatClient: prompt(프롬프트)
ChatClient-->>AiFeedbackStreamProcessor: AI 피드백
AiFeedbackStreamProcessor-->>Controller: 피드백/정답여부 응답
메일 발송 전략별 레이트 리미터 적용 흐름sequenceDiagram
participant RedisStreamReader
participant MailSenderContext
participant MailSenderStrategy (JavaMailSenderStrategy/SesMailSenderStrategy)
participant Bucket
RedisStreamReader->>MailSenderContext: getBucket(strategyKey)
MailSenderContext->>MailSenderStrategy: getBucket()
MailSenderStrategy-->>MailSenderContext: Bucket
MailSenderContext-->>RedisStreamReader: Bucket
RedisStreamReader->>Bucket: tryConsume(1)
alt 토큰 소진 성공
RedisStreamReader->>MailSenderContext: send(dto, strategyKey)
else 실패
RedisStreamReader-->>RedisStreamReader: 대기/재시도
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poem
Note 🔌 MCP (Model Context Protocol) integration is now available in Early Access!Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 22
🔭 Outside diff range comments (4)
cs25-service/src/main/java/com/example/cs25service/domain/security/common/XssRequestWrapper.java (1)
114-133: 배열 내부의 문자열이 이스케이프되지 않아 XSS 우회 가능성이 있습니다
node.isArray()분기에서 원소가Textual인 경우에는 그대로 재귀호출만 하고 실제 이스케이프가 수행되지 않습니다.
예)["<script>alert(1)</script>"]→ 그대로 반환되어 XSS 취약점이 발생합니다.- for (JsonNode item : node) { - sanitizeJsonNode(item, depth + 1); - } + for (JsonNode item : node) { + if (item.isTextual()) { + ((ArrayNode) node).set( + node.indexOf(item), + OBJECT_MAPPER.getNodeFactory() + .textNode(StringEscapeUtils.escapeHtml4(item.asText()))); + } else { + sanitizeJsonNode(item, depth + 1); + } + }또는 루프 안에서 공통 처리 유틸리티를 호출하도록 리팩터링해 주세요.
cs25-batch/src/main/java/com/example/cs25batch/batch/component/reader/RedisStreamReader.java (1)
56-58: 처리 전 ACK → 메시지 유실 위험 (중요)현재 Reader에서 바로 ACK를 수행하고 있어 후속 처리(메일 발송) 실패 시 메시지가 유실됩니다. 일반적으로 처리 성공 후 ACK(Writer/Processor 단계)하거나, 실패 시 PEL에서 재처리 전략을 둬야 합니다.
권장 방안:
- 흐름 변경: 읽기 → 처리(발송) 성공 → ACK
- 또는 PEL 기반 재처리 설계(XPENDING/XCLAIM 활용), 재시도/백오프 포함
- 트랜잭션 경계/Exactly-once 요건에 따른 설계 선택 지원 가능
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/OpenAiChatClient.java (1)
35-44: 스트리밍 폴백이 동작하지 않는 구조적 이슈현재 OpenAiChatClient.stream()에서 onErrorResume 안에서 예외를 재-throw하고, FallbackAiChatClient.stream()은 try/catch로만 감싸고 있어(비동기 오류는 잡히지 않음) 런타임 에러 시 Claude로의 폴백이 작동하지 않습니다.
권장 변경(둘 중 하나, 또는 함께 적용):
- OpenAiChatClient에서 onErrorResume 제거(오류를 그대로 신호로 흘려보냄)
return openAiChatClient.prompt() .system(systemPrompt) .user(userPrompt) .stream() .content() - .onErrorResume(error -> { - throw new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR); - }); + ;
- FallbackAiChatClient.stream()에서 reactive 방식으로 폴백 구현
(해당 파일에 적용할 추가 제안)@Override public Flux<String> stream(String systemPrompt, String userPrompt) { return openAiClient.stream(systemPrompt, userPrompt) .onErrorResume(e -> { log.warn("OpenAI 스트리밍 실패. Claude로 폴백합니다.", e); return claudeClient.stream(systemPrompt, userPrompt); }); }cs25-service/src/main/java/com/example/cs25service/domain/ai/client/ClaudeChatClient.java (1)
33-43: Reactor 에러 처리 패턴 수정 권고:onErrorMap또는Flux.error사용
onErrorResume내부에서 예외를throw하면 재구독/대체 흐름 없이 바로 에러 전파만 일어나며, 연산자 의도와 다르게 보일 수 있습니다. 에러 매핑으로 의도를 명확히 하거나, 명시적으로Flux.error를 반환하세요.- .content() - .onErrorResume(error -> { - throw new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR); - }); + .content() + .onErrorMap(error -> new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR));또는
- .content() - .onErrorResume(error -> { - throw new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR); - }); + .content() + .onErrorResume(error -> Flux.error(new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR)));
♻️ Duplicate comments (2)
cs25-batch/src/main/java/com/example/cs25batch/batch/service/TodayQuizService.java (1)
44-47: 정답률 스케일 오류 – 앞서 언급한 Repository 버그와 동일
accuracyResult값이 0–1 범위로 들어오면 난이도 계산이 잘못됩니다.
Repository 쪽 수정이 반영되면 본 코드 변경은 불필요하므로 중복 코멘트로 남깁니다.cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizAccuracyCalculateService.java (1)
40-47: 정답률 스케일 오류 – Repository 레이어에서 수정 필요
accuracyResult가 0–1 범위이면 난이도 판단이 항상 EASY 로 치우칩니다.
앞서 Repository 코멘트와 동일하므로 중복 표시합니다.
🧹 Nitpick comments (21)
cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiQuestionGeneratorService.java (1)
67-70: 포매팅은 OK. 대문자 변환 시 Locale 고정 제안Line 72의
toUpperCase()가 시스템 기본 Locale에 의존합니다. 잠재적 로케일 이슈(예: Turkish i) 방지를 위해Locale.ROOT를 명시하는 것을 권장합니다.예시:
import java.util.Locale; // ... categoryType = categoryType.toUpperCase(Locale.ROOT);cs25-service/src/main/java/com/example/cs25service/common/aop/LoggingAspect.java (3)
23-31: 메서드명 하드코딩된 포인트컷 → 애노테이션 기반으로 전환 권장submitAnswer/evaluateAnswer 시그니처/이름 변경·이동 시 AOP가 무력화됩니다. 커스텀 애노테이션 기반 포인트컷으로 결합도를 낮추는 편이 안전합니다.
다음 diff로 포인트컷을 간소화하고, 컨트롤러 메서드에 애노테이션을 부여하는 방식으로 전환을 제안합니다:
- @Pointcut("execution(* com.example.cs25service.domain.userQuizAnswer.controller.UserQuizAnswerController.submitAnswer(..))") - public void submitAnswer() {} - - @Pointcut("execution(* com.example.cs25service.domain.userQuizAnswer.controller.UserQuizAnswerController.evaluateAnswer(..))") - public void evaluateAnswer() {} - - @Pointcut("submitAnswer() || evaluateAnswer()") - public void quizAnswerMethods() {} + @Pointcut("@annotation(com.example.cs25service.common.aop.LogQuizAnswer)") + public void quizAnswerMethods() {}추가로, 다음 보조 코드가 필요합니다(별도 파일/영역):
// com.example.cs25service.common.aop.LogQuizAnswer package com.example.cs25service.common.aop; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface LogQuizAnswer {}컨트롤러 사용 예:
@LogQuizAnswer public ResponseEntity<?> submitAnswer(SubmitAnswerRequest req) { ... } @LogQuizAnswer public ResponseEntity<?> evaluateAnswer(EvaluateAnswerRequest req) { ... }
37-40: 익명 인증 처리 보강(AnonymousAuthenticationToken 고려)auth != null 만으로는 익명 토큰(anonymousUser)을 걸러내지 못합니다. 아래처럼 보완하세요.
- Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - String username = (auth != null ? auth.getName() : "anonymous"); + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + String username = "anonymous"; + if (auth != null && auth.isAuthenticated() + && !(auth instanceof org.springframework.security.authentication.AnonymousAuthenticationToken)) { + username = auth.getName(); + }참고: 위 diff는 FQCN을 사용해 별도 import 없이 적용 가능합니다.
17-19: AOP 동작/로깅 테스트 추가 권장Aspect가 적용되는지, 예외 시 로깅이 되는지, payload가 debug에만 출력되는지 등을 테스트로 보장하세요.
예시(개요):
- SpringBootTest + 실제 컨텍스트 로드
- Logback ListAppender로 해당 로거의 이벤트 캡처
- UserQuizAnswerController의 대상 메서드 호출
- info 로그에 method/user/tookMs 포함, debug에 quizInfo 존재 여부 검증
- 예외를 유도해 warn 로그 검증
원하시면 테스트 스켈레톤을 생성해 드리겠습니다.
cs25-batch/src/main/java/com/example/cs25batch/sender/SesMailSenderStrategy.java (1)
31-34: getBucket 노출 최소화현재는 버킷을 그대로 반환하고, 사용처에서 직접
tryConsume을 호출합니다. 컨텍스트 또는 전략에tryConsume(tokens)같은 위임 메서드를 두고, 호출자는 그 메서드만 사용하도록 유도하세요. 사용처 분산 로직을 줄일 수 있습니다. (인터페이스 기본 메서드 추가 제안 참고)cs25-batch/src/main/java/com/example/cs25batch/sender/JavaMailSenderStrategy.java (1)
30-33: getBucket 노출 최소화전략 외부가 버킷 세부 구현을 알 필요가 없도록,
tryConsume(tokens)같은 위임 메서드를 통해 소비하도록 전환하는 것을 권장합니다. (인터페이스 기본 메서드 추가 제안 참고)cs25-batch/src/main/java/com/example/cs25batch/sender/context/MailSenderContext.java (1)
26-32: 예외 메시지에 사용가능 키 포함 권장운영 트러블슈팅을 위해 미존재 키 예외에 사용가능 전략 목록을 같이 포함하면 원인 파악이 빨라집니다.
- if (strategy == null) { - throw new IllegalArgumentException("메일 전략이 존재하지 않습니다: " + strategyKey); - } + if (strategy == null) { + throw new IllegalArgumentException( + "메일 전략이 존재하지 않습니다: " + strategyKey + + " (available=" + strategyMap.keySet() + ")" + ); + }cs25-batch/src/main/java/com/example/cs25batch/batch/component/reader/RedisStreamReader.java (1)
31-35: 전략 키 주입 OK, 초기 유효성 조기 확인 권장
@Value("${mail.strategy:javaBatchMailSender}")기본값과 빈 이름이 일치해 안전합니다. 다만 런타임에read()에서 매번 검증/조회하기보다, 초기화 시 한 번 검증해 빠르게 실패하도록 하는 것이 운영상 유리합니다. (예:@PostConstruct에서mailSenderContext.getBucket(strategyKey)호출)초기화 시 검증이 필요한 이유:
- 잘못된 키로 인해 배치 실행 중 예외가 지연 발생하는 것을 방지
- 시작 시 설정 오류 조기 탐지
cs25-entity/src/main/java/com/example/cs25entity/domain/mail/repository/MailLogRepository.java (1)
26-26: 파생 쿼리 네이밍 및 반환 전략 개선 제안
- 메서드명은 Spring Data JPA 관례상 언더스코어 없이
findDistinctQuizIdBySubscriptionId가 더 읽기 쉽고 일반적입니다. 현재 표기도 동작 가능하나 가독성과 유지보수 측면에서 리네임을 권장합니다.- 대량 데이터가 반환될 가능성이 있으면 Set 수집은 메모리 부담이 큽니다. 스트리밍(
Stream<Long>) 또는 페이지네이션/Slice 적용을 고려해 주세요. 단건 존재 여부만 필요하면exists.../count...가 더 적합합니다.- 쿼리 수행 효율을 위해 mail_log(subscription_id), mail_log(quiz_id) 복합/단일 인덱스 존재 여부를 점검해 주세요.
cs25-entity/src/main/java/com/example/cs25entity/domain/userQuizAnswer/entity/UserQuizAnswer.java (1)
25-26: 클래스 선언 줄바꿈은 기능엔 문제 없으나 스타일 상 단일 라인 권장Java 문법상 유효하지만 다수의 코드스타일(예: Checkstyle/Google Style) 규칙에선
public class UserQuizAnswer extends BaseEntity한 줄 표기를 선호합니다. 팀 컨벤션에 맞춰 단일 라인으로 되돌리는 것을 제안합니다.-public class -UserQuizAnswer extends BaseEntity { +public class UserQuizAnswer extends BaseEntity {cs25-batch/src/test/java/com/example/cs25batch/batch/service/TodayQuizServiceTest.java (1)
94-97: 테스트 데이터 구성은 적절하나, 오프셋/타입까지 검증 강화 제안지금은 단일 결과만 검증합니다. 오프셋/타입 인자 계산 로직 변경에 따라 인자 일치(eq vs any) 기준을 엄격히 하거나, 오프셋 산식이 고정이라면
eq(예상오프셋)으로 명세적 검증을 추가하면 회귀에 강해집니다.cs25-entity/src/main/java/com/example/cs25entity/domain/quiz/repository/QuizCustomRepositoryImpl.java (1)
20-25: 메서드명이 반환 타입과 불일치합니다.
findAvailableQuizzesUnderParentCategory는 복수형 이름이지만 이제Quiz한 건만 반환합니다.
혼란을 방지하려면findAvailableQuizUnderParentCategory같이 단수형으로 변경해 주세요.cs25-batch/src/main/java/com/example/cs25batch/batch/service/TodayQuizService.java (1)
59-60: 매직 넘버 20 의 의미가 불분명합니다.오프셋 상한을 하드코딩하면 카테고리별 문제 수가 20개 미만/초과일 때 편향이 생길 수 있습니다.
상수로 추출하거나 문제 수를 조회해서 동적으로 결정하는 방안을 고려해 보세요..github/workflows/service-deploy.yml (1)
82-82: YAMLTrailing spaces 제거 필요YAMLlint가 지적한 라인(82, 90, 98, 102, 106)의 후행 공백을 제거해 주세요. 기능 영향은 없지만 린트 실패와 잡음 로그를 유발합니다.
가능하면 해당 라인의 공백을 완전히 제거하거나 빈 줄로 두세요.
Also applies to: 90-90, 98-98, 102-102, 106-106
cs25-service/src/main/resources/prompts/prompt.yaml (2)
15-17: 문서 vs 검색 결과의 신뢰도/우선순위 가이드 추가 제안충돌 시 어떤 정보를 우선할지 명시하면 일관성이 좋아집니다. 예: 내부 문서 우선, 검색 결과는 최신성 보완.
Brave 검색 결과: {searchResults} + 판단 기준: + 1) 문서의 내용 > 검색 결과(최신성 보완용) 순으로 신뢰합니다. + 2) 서로 충돌할 경우 문서를 우선 적용하고, 검색 결과는 참고로만 사용합니다.
46-46: 후행 공백 제거YAMLlint가 후행 공백을 경고합니다. 46, 48 라인의 공백을 제거해 주세요.
Also applies to: 48-48
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/OpenAiChatClient.java (1)
21-27: call 결과 정규화 일관성 및 NPE 방어
- trim 추가는 좋습니다. 다만 content()가 null일 가능성에 대비하고(방어적 코딩), 다른 공급자(예: ClaudeChatClient)도 동일하게 trim하여 결과 포맷을 일관화하는 것이 좋습니다.
- return openAiChatClient.prompt() - .system(systemPrompt) - .user(userPrompt) - .call() - .content() - .trim(); + String content = openAiChatClient.prompt() + .system(systemPrompt) + .user(userPrompt) + .call() + .content(); + return content != null ? content.trim() : "";추가로, ClaudeChatClient.call()에도 동일한 trim 처리 적용을 권장합니다.
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/ClaudeChatClient.java (1)
20-26: 리턴 일관성: OpenAI 구현과 동일하게trim()적용 고려OpenAI 쪽
call()은 최종.content().trim()을 수행합니다. Claude도 동일하게 트리밍해 출력 일관성을 보장하는 것이 안전합니다.- .call() - .content(); + .call() + .content() + .trim();cs25-service/src/test/java/com/example/cs25service/ai/AiServiceTest.java (1)
149-155: 해당 테스트는 현재 @disabled로 실행되지 않습니다클래스 상단
@Disabled(Line 37)로 인해 본 테스트가 CI에서 동작하지 않습니다. 활성화 의도라면@Disabled제거 또는 별도의 단위 테스트 클래스로 분리해 실행되도록 해주세요. 또한 단순/독립 로직인 만큼@SpringBootTest없이 순수 단위 테스트로 파라미터화하는 편이 실행 속도와 격리가 좋습니다.예: ParameterizedTest로 간결화
@ParameterizedTest @ValueSource(strings = { "- 정답 : 당신의 답은 완벽합니다.", "정답 : 당신의 답은 완벽합니다.", "정답입니다. 당신의 답은 완벽합니다." }) void isCorrect_shouldReturnTrue(String input) { assertThat(aiService.isCorrect(input)).isTrue(); }테스트를 활성화할 계획이 맞는지 확인 부탁드립니다.
cs25-service/src/main/java/com/example/cs25service/domain/ai/service/BraveSearchMcpService.java (2)
48-61: 도구 조회 캐싱으로 오버헤드 감소
resolveBraveClient()가 매 호출마다listTools()를 순회합니다. 초기 1회 해상 후 캐싱(예:volatile필드)하면 지연/부하를 줄일 수 있습니다. 도구 목록 핫 리로드 필요 시 캐시 무효화 전략을 별도로 고려하세요.
26-33: 파라미터 유효성 보강
count,offset에 대한 하한/상한 검증이 없습니다. 음수/과대 입력 방지를 위해 간단한 검증 또는 안전한 기본값으로 보정하는 편이 안전합니다.예:
count = Math.max(1, Math.min(count, 50)); offset = Math.max(0, offset);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
.github/workflows/service-deploy.yml(2 hunks)cs25-batch/src/main/java/com/example/cs25batch/batch/component/reader/RedisStreamReader.java(3 hunks)cs25-batch/src/main/java/com/example/cs25batch/batch/service/TodayQuizService.java(4 hunks)cs25-batch/src/main/java/com/example/cs25batch/config/RateLimiterConfig.java(0 hunks)cs25-batch/src/main/java/com/example/cs25batch/sender/JavaMailSenderStrategy.java(1 hunks)cs25-batch/src/main/java/com/example/cs25batch/sender/MailSenderStrategy.java(1 hunks)cs25-batch/src/main/java/com/example/cs25batch/sender/SesMailSenderStrategy.java(1 hunks)cs25-batch/src/main/java/com/example/cs25batch/sender/context/MailSenderContext.java(2 hunks)cs25-batch/src/main/resources/application.properties(0 hunks)cs25-batch/src/test/java/com/example/cs25batch/batch/service/TodayQuizServiceTest.java(3 hunks)cs25-entity/src/main/java/com/example/cs25entity/domain/mail/repository/MailLogRepository.java(2 hunks)cs25-entity/src/main/java/com/example/cs25entity/domain/quiz/repository/QuizCustomRepository.java(1 hunks)cs25-entity/src/main/java/com/example/cs25entity/domain/quiz/repository/QuizCustomRepositoryImpl.java(1 hunks)cs25-entity/src/main/java/com/example/cs25entity/domain/userQuizAnswer/entity/UserQuizAnswer.java(1 hunks)cs25-entity/src/main/java/com/example/cs25entity/domain/userQuizAnswer/repository/UserQuizAnswerCustomRepository.java(1 hunks)cs25-entity/src/main/java/com/example/cs25entity/domain/userQuizAnswer/repository/UserQuizAnswerCustomRepositoryImpl.java(2 hunks)cs25-service/build.gradle(1 hunks)cs25-service/src/main/java/com/example/cs25service/common/aop/LoggingAspect.java(1 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/client/ClaudeChatClient.java(1 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/client/OpenAiChatClient.java(1 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/config/AiConfig.java(1 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/controller/AiController.java(0 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/prompt/AiPromptProvider.java(2 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackQueueService.java(3 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamProcessor.java(5 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamWorker.java(5 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiQuestionGeneratorService.java(2 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiService.java(0 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/service/BraveSearchMcpService.java(1 hunks)cs25-service/src/main/java/com/example/cs25service/domain/ai/service/BraveSearchRagService.java(1 hunks)cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizAccuracyCalculateService.java(3 hunks)cs25-service/src/main/java/com/example/cs25service/domain/security/common/XssRequestWrapper.java(3 hunks)cs25-service/src/main/resources/application.properties(1 hunks)cs25-service/src/main/resources/prompts/prompt.yaml(2 hunks)cs25-service/src/test/java/com/example/cs25service/ai/AiServiceTest.java(2 hunks)
💤 Files with no reviewable changes (4)
- cs25-batch/src/main/resources/application.properties
- cs25-service/src/main/java/com/example/cs25service/domain/ai/controller/AiController.java
- cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiService.java
- cs25-batch/src/main/java/com/example/cs25batch/config/RateLimiterConfig.java
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-23T01:34:30.742Z
Learnt from: crocusia
PR: NBC-finalProject/CS25-BE#141
File: cs25-batch/src/main/java/com/example/cs25batch/batch/jobs/DailyMailSendJob.java:187-195
Timestamp: 2025-06-23T01:34:30.742Z
Learning: DailyMailSendJob에서 taskExecutor bean은 mailConsumerWithAsyncStep에서만 사용되므로, ThreadShuttingJobListener로 해당 작업 완료 후 executor를 종료해도 다른 배치 작업들에 영향을 주지 않습니다.
Applied to files:
cs25-batch/src/main/java/com/example/cs25batch/sender/JavaMailSenderStrategy.javacs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamWorker.java
🧬 Code Graph Analysis (3)
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/ClaudeChatClient.java (2)
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/OpenAiChatClient.java (1)
Component(10-45)cs25-service/src/main/java/com/example/cs25service/domain/ai/client/FallbackAiChatClient.java (1)
Component(10-46)
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/OpenAiChatClient.java (2)
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/ClaudeChatClient.java (1)
Component(10-44)cs25-service/src/main/java/com/example/cs25service/domain/ai/client/FallbackAiChatClient.java (1)
Component(10-46)
cs25-batch/src/main/java/com/example/cs25batch/batch/component/reader/RedisStreamReader.java (3)
cs25-batch/src/main/java/com/example/cs25batch/sender/SesMailSenderStrategy.java (1)
RequiredArgsConstructor(12-35)cs25-batch/src/main/java/com/example/cs25batch/sender/JavaMailSenderStrategy.java (1)
Component(12-34)cs25-batch/src/main/java/com/example/cs25batch/sender/context/MailSenderContext.java (1)
Component(11-34)
🪛 YAMLlint (1.37.1)
cs25-service/src/main/resources/prompts/prompt.yaml
[error] 46-46: trailing spaces
(trailing-spaces)
[error] 48-48: trailing spaces
(trailing-spaces)
.github/workflows/service-deploy.yml
[error] 82-82: trailing spaces
(trailing-spaces)
[error] 90-90: trailing spaces
(trailing-spaces)
[error] 98-98: trailing spaces
(trailing-spaces)
[error] 102-102: trailing spaces
(trailing-spaces)
[error] 106-106: trailing spaces
(trailing-spaces)
🔇 Additional comments (22)
cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiQuestionGeneratorService.java (1)
33-36: 포매팅 정리: 로직 영향 없음 (LGTM)메서드 체이닝 들여쓰기만 변경되어 가독성이 좋아졌습니다. 동작 변화는 없습니다.
cs25-service/src/main/java/com/example/cs25service/domain/security/common/XssRequestWrapper.java (2)
18-24: Slf4j 도입과 ObjectMapper 싱글톤화 👍로깅 추가 및
static final ObjectMapper재사용으로 성능이 개선되었습니다. 별다른 문제 없이 잘 적용되었습니다.
115-118: DoS 방어용 깊이 제한 예외가 무시되어 실제 차단이 이루어지지 않습니다
IllegalArgumentException을 던지지만 상위sanitizeJsonBody에서 catch 후 원본 JSON을 그대로 반환하므로 공격 요청이 그대로 통과합니다. 예외를 상위로 전파하여 400 응답을 주거나 요청 자체를 거부하도록 로직을 조정하는 것이 안전합니다.cs25-batch/src/main/java/com/example/cs25batch/sender/SesMailSenderStrategy.java (1)
5-11: Bucket4j 빌더 API 호환성 확인됨
프로젝트에 선언된com.bucket4j:bucket4j_jdk17-core:8.14.0버전은Bucket.builder()및Bandwidth.builder()API를 지원하므로 별도의 변경은 필요하지 않습니다.cs25-batch/src/main/java/com/example/cs25batch/sender/context/MailSenderContext.java (1)
16-19: 전략 유효성 검증 분리 리팩토링 좋습니다
getValidStrategy로 검증을 일원화한 점이 명확성과 재사용성 측면에서 좋습니다.cs25-entity/src/main/java/com/example/cs25entity/domain/mail/repository/MailLogRepository.java (1)
8-8: 필요한 import 추가 확인
Set사용을 위한 import 추가는 적절합니다. 별도 이슈 없습니다.cs25-entity/src/main/java/com/example/cs25entity/domain/userQuizAnswer/repository/UserQuizAnswerCustomRepository.java (1)
13-13: 정답률 API 계약(스케일/기본값/null) 명시 필요 + 파라미터 의미 명확화
Double getCorrectRate(...)의 반환 스케일(0.01.0 vs 0100)과 “답안 없음” 시 기본값이 무엇인지가 인터페이스에서 명세되지 않았습니다. 구현이 100.0을 디폴트로 준다면 문서화가 필수입니다. 그렇지 않으면 호출부에서 해석 혼선이 생깁니다.Double대신double또는OptionalDouble사용을 고려해 null 안전성을 확보하세요.quizCategoryId가 부모 카테고리 기준이라면 파라미터명을parentCategoryId등으로 구체화해 오해를 줄이세요.- 현재 이 인터페이스에는
findByUserIdAndQuizCategoryId(...)도 공존합니다. 의도대로 신규 집계 API로 전환 중이라면 중복/혼재 사용을 방지하기 위한 정리 계획이 필요합니다.Likely an incorrect or invalid review comment.
.github/workflows/service-deploy.yml (1)
58-58: BRAVE_API_KEY 전달 추가 LGTM. 시크릿 존재/권한만 재확인 요청
- GitHub Secrets에 BRAVE_API_KEY가 설정되어 있고, 조직/레포 권한상 워크플로가 접근 가능한지 확인해 주세요. 누락 시 컨테이너는 뜨더라도 Brave MCP 연동이 런타임에서 실패합니다.
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/OpenAiChatClient.java (1)
15-17: 생성자 주입 + Qualifier 적용 LGTM구성 변경과 일치하며 명시적 주입으로 가독성도 좋아졌습니다. 해당 이름(openAiChatModelClient)의 Bean이 실제로 등록되어 있는지만 확인해 주세요.
cs25-service/src/main/java/com/example/cs25service/domain/ai/client/ClaudeChatClient.java (1)
15-17: 명시적 생성자 주입 전환 적절Qualifier("anthropicChatClient")로 명시적 생성자 주입 전환은 의존성 해상도를 명확히 해 가독성과 유지보수성이 좋아집니다.
cs25-service/src/main/java/com/example/cs25service/domain/ai/service/BraveSearchRagService.java (1)
16-64: 파싱 견고성 및 Document 생성자 시그니처 검토 요청현재
toDocuments메서드는 동작하나, 다음 보완을 권장드립니다.
- CR/LF 구분을 위해
text.split("\\R")사용- 각 라인에
line.trim()적용하여 선·후행 공백 제거Title:/URL:매칭 시 대소문자·공백 허용 정규식(matches("(?i)^title\\s*:.*"),matches("(?i)^url\\s*:.*")) 사용Document생성자 시그니처가 사용 중인 Spring AI 버전과 호환되는지 확인핵심 수정 예시:
- String[] lines = text.split("\\n"); + String[] lines = text.split("\\R"); // CRLF 포함 - for (String line : lines) { + for (String raw : lines) { + String line = raw.trim(); if (line.startsWith("Title:")) { ... - } else if (line.startsWith("URL:")) { + } else if (line.matches("(?i)^url\\s*:.*")) { ... } } ... - documents.add(new Document( - title, - contentBuilder.toString().trim(), - Map.of("title", title, "url", url) - )); + documents.add(new Document( + contentBuilder.toString().trim(), + Map.of("id", url, "title", title, "url", url) + ));위 개선으로 파싱 안정성과 메타데이터 기반 문서 식별·중복 제거가 용이해집니다.
Document생성자(title, content, metadata)vs(content, metadata)지원 여부를 확인 부탁드립니다.cs25-service/src/main/java/com/example/cs25service/domain/ai/config/AiConfig.java (2)
24-36: ChatClient 빈 구성 세부 설정 누락
ChatClient.builder(chatModel).build()기본값으로는 타임아웃·retry·temperature 등이 모두 default 입니다.
운영 환경에서 모델·네트워크 지연이 잦은 편이라면ChatClient.builder(chatModel).timeout(Duration.ofSeconds(..))등 세부 옵션을 함께 설정해두는 편이 안전합니다.
[ suggest_optional_refactor ]
24-36: 이름/Qualifier 불일치 가능성 확인 요청메서드명은
openAiChatClient이지만 빈 이름은"openAiChatModelClient"로 명시되어 있습니다.
주입 지점이@Qualifier("openAiChatModelClient")로 맞춰져 있는지 한번 더 확인 바랍니다.
[ request_verification ]cs25-service/src/main/java/com/example/cs25service/domain/ai/prompt/AiPromptProvider.java (3)
44-56: INFO 레벨 로그에 전문(프롬프트) 출력
log.info("[AI User Prompt]\n{}"로 전체 프롬프트를 남기면
- 개인정보‧문제 문구가 그대로 로그에 저장되고
- 대용량 문자열로 로그가 급격히 불어날 수 있습니다.
debug수준으로 낮추거나, 길이 제한·마스킹 적용을 권장합니다.
[ suggest_essential_refactor ][ security ]
48-53: 문자 치환 방식의 확장성 한계
String.replace("{context}", …)방식은 템플릿 키가 사용자의 입력값과 우연히 겹칠 경우 오동작할 수 있습니다.
ApacheStringSubstitutor(common-text) 또는MessageFormat같은 안전한 템플릿 유틸로 교체하면 예측 가능성이 높아집니다.
[ suggest_optional_refactor ]
59-72: Brave 결과 포매팅 중복 변환
root.get("results")존재 확인 뒤 실제로는braveSearchRagService.toDocuments(root)를 다시 호출하여 동일 JSON을 파싱합니다.
resultsNode검사 후 곧바로 변환 로직을 호출하므로, 앞단resultsNode조회는 불필요해 보입니다. 불필요한 분기 제거로 가독성을 높일 수 있습니다.
[ suggest_nitpick ]cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamProcessor.java (2)
94-97: nullable 체크 불필요
StringBuilder.toString()은 절대null을 반환하지 않으므로feedback == null조건은 의미가 없습니다.
빈 문자열만 검사하도록 간소화해도 됩니다.
[ suggest_nitpick ]
127-140:isCorrect판정 로직의 신뢰도
- 피드백 서두 6자만 검사하면
"정답이 아닙니다"도정답으로 오인할 수 있습니다.- AI 출력 형식이 조금만 바뀌어도 실패 위험이 큽니다.
정규식
^정답(\\s|:)처럼 전체 문장 패턴을 확인하거나, 프롬프트 자체에 JSON 태그("isCorrect": true/false)를 포함하도록 수정하는 방법을 권장드립니다.
[ suggest_essential_refactor ]cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamWorker.java (4)
41-48: ThreadPoolExecutor 생성 시 ThreadFactory 미지정현재 스레드가
Thread-?이름으로 생성되어 디버깅이 어려울 수 있습니다.
Executors.defaultThreadFactory()를 래핑해"ai-worker-%d"형식으로 명명하면 로그 추적이 수월합니다.
[ suggest_optional_refactor ]
64-67: 스케일링 주기 하드코딩
SCALING_CHECK_INTERVAL = 5초가 하드코딩되어 있습니다.
프로퍼티로 외부 노출해 운영 중에 조정 가능하도록 하는 편이 운영 유연성을 높입니다.
[ suggest_nitpick ]
90-97:setCorePoolSize축소 후 잔존 워커 처리 지연core 수를 줄인 즉시 surplus 워커가 종료되도록
allowCoreThreadTimeOut(true)로 설정해두셨지만,
poll루프가 한 번 더 블로킹(최대 2초)된 뒤에야workerIndex체크가 이뤄집니다.
StreamReadOptions.block(2s)값을 더 짧게 조정하거나 interrupt 시그널 처리로 종료 반응 속도를 높일 수 있습니다.
[ suggest_optional_refactor ]
125-154: Redis 읽기 예외 처리 후 재시도 전략 부재
poll내부에서 예외가 발생하면 단순 로그만 남기고 루프를 계속 돕니다.
짧은 시간 내 반복 오류가 발생할 경우 로그가 폭주할 수 있으므로,
지수 back-off(슬립) 또는 에러 카운터 기반 일시 중단 로직을 추가하는 것을 권장합니다.
[ suggest_optional_refactor ]
| Bucket bucket = mailSenderContext.getBucket(strategyKey); | ||
|
|
||
| while (!bucket.tryConsume(1)) { | ||
| Thread.sleep(200); //토큰을 얻을 때까지 간격을 두고 재시도 |
There was a problem hiding this comment.
🛠️ Refactor suggestion
버킷 직접 획득/루프 대신 컨텍스트 위임 사용
컨텍스트에 tryConsume(strategyKey, tokens)를 추가했다면 아래처럼 호출부를 단순화할 수 있습니다. 버킷 구현/정책을 호출처에서 몰라도 되며, 이후 정책 변경 시 영향 범위를 줄일 수 있습니다.
- Bucket bucket = mailSenderContext.getBucket(strategyKey);
-
- while (!bucket.tryConsume(1)) {
+ while (!mailSenderContext.tryConsume(strategyKey, 1)) {
Thread.sleep(200); //토큰을 얻을 때까지 간격을 두고 재시도
}참고: 이 변경 후 io.github.bucket4j.Bucket import는 불필요해집니다(정리 권장).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Bucket bucket = mailSenderContext.getBucket(strategyKey); | |
| while (!bucket.tryConsume(1)) { | |
| Thread.sleep(200); //토큰을 얻을 때까지 간격을 두고 재시도 | |
| while (!mailSenderContext.tryConsume(strategyKey, 1)) { | |
| Thread.sleep(200); //토큰을 얻을 때까지 간격을 두고 재시도 | |
| } |
🤖 Prompt for AI Agents
In
cs25-batch/src/main/java/com/example/cs25batch/batch/component/reader/RedisStreamReader.java
around lines 40 to 43, replace the direct bucket acquisition and while loop with
a call to mailSenderContext.tryConsume(strategyKey, 1). This delegates token
consumption to the context, simplifying the code and hiding bucket
implementation details. After this change, remove the unused import of
io.github.bucket4j.Bucket.
| public Bucket getBucket(String strategyKey) { | ||
| MailSenderStrategy strategy = getValidStrategy(strategyKey); | ||
| return strategy.getBucket(); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
버킷 직접 반환 대신 소비 위임 메서드 추가 권장
컨텍스트에서 토큰 소비를 대행하면 호출처는 버킷을 알 필요가 없습니다. 아래처럼 tryConsume 위임을 추가하고, 사용처에서는 이 API를 사용하도록 전환해 주세요.
public Bucket getBucket(String strategyKey) {
MailSenderStrategy strategy = getValidStrategy(strategyKey);
return strategy.getBucket();
}
+
+ public boolean tryConsume(String strategyKey, long tokens) {
+ return getValidStrategy(strategyKey).getBucket().tryConsume(tokens);
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public Bucket getBucket(String strategyKey) { | |
| MailSenderStrategy strategy = getValidStrategy(strategyKey); | |
| return strategy.getBucket(); | |
| } | |
| public Bucket getBucket(String strategyKey) { | |
| MailSenderStrategy strategy = getValidStrategy(strategyKey); | |
| return strategy.getBucket(); | |
| } | |
| public boolean tryConsume(String strategyKey, long tokens) { | |
| return getValidStrategy(strategyKey).getBucket().tryConsume(tokens); | |
| } |
🤖 Prompt for AI Agents
In
cs25-batch/src/main/java/com/example/cs25batch/sender/context/MailSenderContext.java
around lines 21 to 24, instead of directly returning the Bucket object from
getBucket, add a new method like tryConsume that delegates token consumption to
the Bucket internally. Modify the usage sites to call this new tryConsume method
so they do not need to access the Bucket directly, encapsulating the consumption
logic within the context class.
| import io.github.bucket4j.Bandwidth; | ||
| import io.github.bucket4j.Bucket; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import java.time.Duration; | ||
|
|
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Bucket4j API 버전 확인
Bucket.builder()/Bandwidth.builder() 사용 가능 버전인지 빌드 설정을 점검해 주세요.
🏁 Script executed:
#!/bin/bash
# 저장소 내 Bucket4j 의존성 및 버전 확인
fd -HIa 'build.gradle*' 'pom.xml' | xargs -I{} sh -c 'echo ">>> {}"; sed -n "1,200p" "{}" | rg -n "bucket4j|io.github.bucket4j" -A 2'Length of output: 230
🏁 Script executed:
#!/bin/bash
# 저장소 루트에서 pom.xml, build.gradle, build.gradle.kts 파일을 찾아 Bucket4j 의존성 및 버전 확인
find . -maxdepth 2 -type f \( -name 'pom.xml' -o -name 'build.gradle' -o -name 'build.gradle.kts' \) | while read file; do
echo ">>> $file"
sed -n '1,200p' "$file" | rg -n "io\.github\.bucket4j" -A 2 || echo " → Bucket4j 의존성이 없습니다."
doneLength of output: 1169
Bucket4j 의존성 선언 및 버전 확인 필요
JavaMailSenderStrategy에서 io.github.bucket4j.Bucket/Bandwidth 클래스를 사용하고 있지만, Gradle 설정에서 Bucket4j 의존성이 선언되어 있지 않아 빌드가 실패합니다. 아래 모듈의 build.gradle에 적절한 Bucket4j 코어 의존성을 추가하고, 사용 가능한 버전을 명시해 주세요.
– 수정 위치
• cs25-batch/build.gradle
– 예시 추가 코드
dependencies {
// 필요한 버전으로 조정하세요
implementation 'com.github.bucket4j:bucket4j-core:7.6.0'
}🤖 Prompt for AI Agents
In cs25-batch/build.gradle, add the Bucket4j core dependency to fix the build
failure caused by missing Bucket4j classes used in
cs25-batch/src/main/java/com/example/cs25batch/sender/JavaMailSenderStrategy.java
lines 5 to 11. Add the implementation line for
'com.github.bucket4j:bucket4j-core' with a specific version like 7.6.0 inside
the dependencies block.
| private final Bucket bucket = Bucket.builder() | ||
| .addLimit( | ||
| Bandwidth.builder() | ||
| .capacity(4) | ||
| .refillGreedy(2, Duration.ofMillis(500)) | ||
| .build() | ||
| ) | ||
| .build(); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
레이트 리밋 상수 하드코딩 → 설정 외부화 권장
capacity(4), refill(2/500ms)을 코드에 고정하지 말고 프로퍼티로 외부화하면 환경별/전략별로 유연하게 조정할 수 있습니다. SES/자바메일 전략 간 할당량 차이도 설정만으로 관리 가능합니다.
권장: @ConfigurationProperties(prefix="mail.java.rate")로 바인딩 후 Bucket 생성.
🤖 Prompt for AI Agents
In
cs25-batch/src/main/java/com/example/cs25batch/sender/JavaMailSenderStrategy.java
around lines 16 to 23, the rate limit values for capacity and refill are
hardcoded. Refactor the code to externalize these values by creating a
configuration properties class annotated with
@ConfigurationProperties(prefix="mail.java.rate") and bind the capacity, refill
tokens, and refill duration from application properties. Then use these injected
properties to build the Bucket instance, allowing flexible adjustment per
environment or strategy without code changes.
| public interface MailSenderStrategy { | ||
| void sendQuizMail(MailDto mailDto); | ||
|
|
||
| Bucket getBucket(); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Bucket을 인터페이스로 직접 노출 → 추상화 누수
전략의 내부 구현(버킷)을 외부로 노출하면 결합도가 올라가고 사용처가 토큰 소비 정책을 분산해서 갖게 됩니다. 점진적 마이그레이션을 위해 기본 메서드로 토큰 소비 API를 제공한 뒤, 사용처에서는 이를 호출하도록 전환하는 방식을 권장합니다.
아래처럼 기본 메서드를 추가해 외부가 버킷 인지 없이 토큰 소비만 하도록 유도할 수 있습니다.
public interface MailSenderStrategy {
void sendQuizMail(MailDto mailDto);
Bucket getBucket();
+
+ default boolean tryConsume(long tokens) {
+ return getBucket().tryConsume(tokens);
+ }
}🤖 Prompt for AI Agents
In cs25-batch/src/main/java/com/example/cs25batch/sender/MailSenderStrategy.java
at line 9, the getBucket() method exposes the internal Bucket interface causing
abstraction leakage and increased coupling. Remove the getBucket() method and
instead add a default method in the interface that handles token consumption
internally. This way, external callers interact only with the token consumption
API without direct access to the Bucket, enabling gradual migration and reducing
coupling.
| JsonNode content = objectMapper.valueToTree(result.content()); | ||
| log.info("[Brave MCP Response Raw content]: {}", content.toPrettyString()); | ||
|
|
||
| if (content != null && content.isArray()) { | ||
| var root = objectMapper.createObjectNode(); | ||
| root.set("results", content); | ||
| return root; | ||
| } | ||
|
|
||
| return content != null ? content : objectMapper.createObjectNode(); | ||
| } |
There was a problem hiding this comment.
NullNode 처리 누락: valueToTree(null)은 null이 아닌 NullNode를 반환
valueToTree는 입력이 null이어도 NullNode를 반환합니다. 현재 content != null 체크만으로는 빈 결과를 적절히 처리하지 못할 수 있습니다. content.isNull()을 함께 확인해 빈 오브젝트 반환 의도를 보장하세요.
- JsonNode content = objectMapper.valueToTree(result.content());
+ JsonNode content = objectMapper.valueToTree(result.content());
log.info("[Brave MCP Response Raw content]: {}", content.toPrettyString());
- if (content != null && content.isArray()) {
+ if (content != null && !content.isNull() && content.isArray()) {
var root = objectMapper.createObjectNode();
root.set("results", content);
return root;
}
- return content != null ? content : objectMapper.createObjectNode();
+ return (content != null && !content.isNull()) ? content : objectMapper.createObjectNode();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| JsonNode content = objectMapper.valueToTree(result.content()); | |
| log.info("[Brave MCP Response Raw content]: {}", content.toPrettyString()); | |
| if (content != null && content.isArray()) { | |
| var root = objectMapper.createObjectNode(); | |
| root.set("results", content); | |
| return root; | |
| } | |
| return content != null ? content : objectMapper.createObjectNode(); | |
| } | |
| JsonNode content = objectMapper.valueToTree(result.content()); | |
| log.info("[Brave MCP Response Raw content]: {}", content.toPrettyString()); | |
| if (content != null && !content.isNull() && content.isArray()) { | |
| var root = objectMapper.createObjectNode(); | |
| root.set("results", content); | |
| return root; | |
| } | |
| return (content != null && !content.isNull()) ? content : objectMapper.createObjectNode(); | |
| } |
🤖 Prompt for AI Agents
In
cs25-service/src/main/java/com/example/cs25service/domain/ai/service/BraveSearchMcpService.java
around lines 36 to 46, the code checks if content is not null but does not
handle the case where content is a NullNode returned by valueToTree(null).
Update the condition to also check if content.isNull() is false before
proceeding, and if content is null or NullNode, return an empty object node to
correctly handle empty results.
| CallToolResult result = braveClient.callTool(request); | ||
|
|
||
| JsonNode content = objectMapper.valueToTree(result.content()); | ||
| log.info("[Brave MCP Response Raw content]: {}", content.toPrettyString()); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
민감정보(PII) 노출 위험: Raw 응답을 INFO 레벨로 전체 로그 출력
검색 쿼리/결과는 민감할 수 있습니다. 운영 환경에서는 INFO 레벨 전체 출력은 피하고, DEBUG로 낮추거나 샘플링/마스킹을 적용하세요.
- log.info("[Brave MCP Response Raw content]: {}", content.toPrettyString());
+ log.debug("[Brave MCP Response Raw content]: {}", content.toPrettyString());📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| log.info("[Brave MCP Response Raw content]: {}", content.toPrettyString()); | |
| log.debug("[Brave MCP Response Raw content]: {}", content.toPrettyString()); |
🤖 Prompt for AI Agents
In
cs25-service/src/main/java/com/example/cs25service/domain/ai/service/BraveSearchMcpService.java
at line 37, the raw response content is logged at INFO level, which risks
exposing sensitive PII data. Change the log level from INFO to DEBUG to reduce
exposure in production environments, or implement masking or sampling of the
logged content to protect sensitive information.
| # FALLBACK | ||
| spring.ai.model.chat=openai,anthropic | ||
| spring.ai.chat.client.enabled=false | ||
| # MCP | ||
| spring.ai.mcp.client.enabled=true | ||
| spring.ai.mcp.client.type=SYNC | ||
| spring.ai.mcp.client.request-timeout=30s | ||
| spring.ai.mcp.client.root-change-notification=false | ||
| # STDIO Connect: Brave Search | ||
| spring.ai.mcp.client.stdio.connections.brave.command=npx | ||
| spring.ai.mcp.client.stdio.connections.brave.args[0]=-y | ||
| spring.ai.mcp.client.stdio.connections.brave.args[1]=@modelcontextprotocol/server-brave-search | ||
| spring.ai.mcp.client.stdio.connections.brave.env.BRAVE_API_KEY=${BRAVE_API_KEY} |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
MCP(STDIO) 실행 환경 점검: npx/Node 필요, 버전 고정 및 타임아웃 튜닝 제안
- npx 실행에는 컨테이너 내 Node.js/npm이 필요합니다. Docker 이미지에 포함되지 않으면 런타임에 즉시 실패합니다.
- npx는 매 실행 시 패키지 설치를 시도할 수 있어 콜드 스타트 지연/불안정성이 있습니다. 전역 설치(이미지 빌드 단계에서 npm i -g) 또는 특정 버전 고정(@x.y.z) 사용을 권장합니다.
- request-timeout=30s는 검색+AI 파이프라인에는 촉박할 수 있습니다. 45~60s로 상향을 고려해 주세요.
- spring.ai.chat.client.enabled=false 설정으로 기본 ChatClient 오토컨피그를 끈 상태이므로, 코드상에서 참조하는 Bean(예: openAiChatModelClient)이 실제로 등록되어 있는지 함께 확인 바랍니다.
다음 스크립트로 Dockerfile에 Node/npx 포함 여부를 점검해 주세요:
선택적 개선:
- 전역 설치 전략(예시)
- Dockerfile 빌드 단계에서: npm i -g @modelcontextprotocol/server-brave-search
- properties에서는 command를 해당 바이너리로 직접 지정(또는 npx에 버전 고정 추가: @modelcontextprotocol/server-brave-search@<고정버전>)
- 타임아웃 상향:
-spring.ai.mcp.client.request-timeout=30s
+spring.ai.mcp.client.request-timeout=60s🏁 Script executed:
#!/bin/bash
# 컨테이너에 node/npm/npx 설치 흔적 확인
fd Dockerfile | xargs -I{} sh -c 'echo ">>> {}"; cat {}'
rg -n "node|npm|npx" -SLength of output: 21973
MCP(STDIO) 환경: Docker 이미지에 Node/npx 미포함 → 빌드 단계 수정 필요
- Dockerfile(cs25-service/Dockerfile 포함)에 Node.js/npm/npx가 없어
npx실행 시 런타임에서 즉시 실패합니다. - cs25-service/src/main/resources/application.properties (Lines 62–74)
spring.ai.mcp.client.stdio.connections.brave.command=npx - 개선 방안:
• Dockerfile 빌드 스테이지에 Node.js 설치 또는 Brave 검색 패키지 전역 설치
예)• 또는 properties에서 직접 바이너리 호출FROM openjdk:17 AS runtime RUN apt-get update && apt-get install -y nodejs npm \ && npm install -g @modelcontextprotocol/server-brave-search@<버전>
spring.ai.mcp.client.stdio.connections.brave.command=server-brave-search - 타임아웃 상향 권장:
-spring.ai.mcp.client.request-timeout=30s +spring.ai.mcp.client.request-timeout=60s
spring.ai.chat.client.enabled=false로 기본 ChatClient 오토컨피그가 비활성화된 상태이므로, 코드에서 참조하는 Bean(예: openAiChatModelClient)이 실제로 등록되어 있는지 함께 확인해 주세요.
🤖 Prompt for AI Agents
In cs25-service/src/main/resources/application.properties lines 62 to 74, the
command for Brave Search uses 'npx', but the Docker image lacks Node.js and npx,
causing runtime failures. To fix this, update the Dockerfile to install Node.js
and npm, and globally install the Brave Search package during the build stage,
or alternatively, change the properties to call the Brave Search binary directly
by setting
'spring.ai.mcp.client.stdio.connections.brave.command=server-brave-search'.
Also, consider increasing the timeout value and verify that any referenced
ChatClient beans like openAiChatModelClient are properly registered since
'spring.ai.chat.client.enabled' is false.
| 당신은 CS 문제 채점 전문가입니다. 아래 문서와 검색 결과를 참고하여 사용자의 답변이 문제의 요구사항에 부합하는지 판단하세요. | ||
| 문서나 검색 결과가 충분하지 않거나 관련 정보가 없는 경우, 당신이 알고 있는 CS 지식으로 보완해서 판단해도 됩니다. |
There was a problem hiding this comment.
🛠️ Refactor suggestion
근거 기반 판단을 명시해 환각 감소
현재 문구는 모델의 일반 지식 사용을 허용하여 근거 부족 시 환각적 판단을 유도할 수 있습니다. 문서/검색 근거 우선, 불충분 시 ‘근거 부족’으로 판정하도록 바꾸는 것을 권장합니다.
- 당신은 CS 문제 채점 전문가입니다. 아래 문서와 검색 결과를 참고하여 사용자의 답변이 문제의 요구사항에 부합하는지 판단하세요.
- 문서나 검색 결과가 충분하지 않거나 관련 정보가 없는 경우, 당신이 알고 있는 CS 지식으로 보완해서 판단해도 됩니다.
+ 당신은 CS 문제 채점 전문가입니다. 아래 문서와 검색 결과를 ‘주요 근거’로 사용하여 사용자의 답변이 문제 요구사항에 부합하는지 판단하세요.
+ 문서나 검색 결과가 불충분하면 ‘근거 부족’으로 판단하고, 임의 추론은 금지합니다. (명백한 기초 개념 수준의 상식만 보조 근거로 허용)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 당신은 CS 문제 채점 전문가입니다. 아래 문서와 검색 결과를 참고하여 사용자의 답변이 문제의 요구사항에 부합하는지 판단하세요. | |
| 문서나 검색 결과가 충분하지 않거나 관련 정보가 없는 경우, 당신이 알고 있는 CS 지식으로 보완해서 판단해도 됩니다. | |
| 당신은 CS 문제 채점 전문가입니다. 아래 문서와 검색 결과를 ‘주요 근거’로 사용하여 사용자의 답변이 문제 요구사항에 부합하는지 판단하세요. | |
| 문서나 검색 결과가 불충분하면 ‘근거 부족’으로 판단하고, 임의 추론은 금지합니다. (명백한 기초 개념 수준의 상식만 보조 근거로 허용) |
🤖 Prompt for AI Agents
In cs25-service/src/main/resources/prompts/prompt.yaml around lines 9 to 10, the
prompt text allows the model to supplement with its own knowledge when document
or search results are insufficient, which may cause hallucinations. Modify the
prompt to prioritize document and search evidence for judgment and instruct the
model to respond with 'insufficient evidence' if the information is lacking,
instead of using its own knowledge.
| @Test | ||
| @DisplayName("오답인 경우 false 반환") | ||
| void testIfAiFeedbackIsWrongThenReturnfalse(){ | ||
| assertThat(aiService.isCorrect("- 오답 : 당신의 답은 완벽합니다.")).isFalse(); | ||
| assertThat(aiService.isCorrect("오답 : 당신의 답은 완벽합니다.")).isFalse(); | ||
| assertThat(aiService.isCorrect("오답입니다. 당신의 답은 완벽합니다.")).isFalse(); | ||
| assertThat(aiService.isCorrect("오답: 정답이라고 하기에는 부족합니다.")).isFalse(); | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
부정 케이스 추가 제안 및 메서드 소유 위치 확인
현재 부정 케이스는 적절합니다. 다음 보완을 권장합니다.
- "정답"이 6자 초과 위치에 등장하는 경우 false 검증 추가
- "정답"과 "오답"이 동시에 존재하며 선후관계가 바뀌는 케이스 추가
또한 PR 설명에 따르면 isCorrect 로직이 AiFeedbackStreamProcessor로 이동했을 수 있습니다. AiService.isCorrect가 실제로 존재하는지 확인 필요합니다.
다음 스크립트로 isCorrect 메서드의 실제 위치를 확인하세요.
🏁 Script executed:
#!/bin/bash
# AiService 및 AiFeedbackStreamProcessor에서 isCorrect 존재 여부 검색
rg -n --no-heading "class\s+AiService|class\s+AiFeedbackStreamProcessor" -A 200 cs25-service/src/main/java | rg -n --no-heading "boolean\s+isCorrect\s*\("Length of output: 311
AiFeedbackStreamProcessor로 테스트 이전 및 추가 부정 케이스 보강 권장
-
isCorrect메서드가AiService가 아닌
cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamProcessor.java:127에 정의되어 있습니다.
→AiServiceTest대신AiFeedbackStreamProcessorTest로 테스트 파일을 이동하거나, 테스트 대상 클래스를AiFeedbackStreamProcessor로 수정하세요. -
추가 부정 케이스 검증 제안:
•"정답"이 6자 초과 위치에 등장하는 경우false반환 확인
•"정답"과"오답"이 동시에 존재하며 선후관계가 바뀌는 경우 검증
위 두 가지를 반영하여 테스트 위치를 바로잡고, 제안된 케이스를 테스트에 추가해 주세요.
🤖 Prompt for AI Agents
In cs25-service/src/test/java/com/example/cs25service/ai/AiServiceTest.java
around lines 157 to 164, the isCorrect method is tested in AiServiceTest but it
is actually defined in AiFeedbackStreamProcessor at line 127. Move this test
method to AiFeedbackStreamProcessorTest or change the test target class to
AiFeedbackStreamProcessor. Additionally, add test cases to verify that isCorrect
returns false when "정답" appears beyond the 6th character and when both "정답" and
"오답" appear with reversed order, to strengthen negative case coverage.
Summary by CodeRabbit
신규 기능
기능 개선
버그 수정
테스트
설정 및 문서
리팩터/정리