Skip to content

πŸ› Fix: 3μ°¨ μŠ€ν”„λ¦°νŠΈ κ°œμ„ μ μ„ μˆ˜μ •ν•œλ‹€#162

Merged
EunjinWoo merged 11 commits into
developfrom
fix/159-3rd
Dec 13, 2025
Merged

πŸ› Fix: 3μ°¨ μŠ€ν”„λ¦°νŠΈ κ°œμ„ μ μ„ μˆ˜μ •ν•œλ‹€#162
EunjinWoo merged 11 commits into
developfrom
fix/159-3rd

Conversation

@EunjinWoo
Copy link
Copy Markdown
Member

@EunjinWoo EunjinWoo commented Dec 11, 2025

✨ Related Issue


πŸ“Œ Task Details

  • μ§€μ›μ„œ μƒμ„Έλ³΄κΈ°μ—μ„œ λ©΄μ ‘ κ°€λŠ₯ 일정 λ‚ μ§œ 같이 보여주기 -> 이미 μ£Όκ³  μžˆμ—ˆμŒ
  • 지원 ν˜„ν™© 관리 νŽ˜μ΄μ§€μ—μ„œ μ΅œμ‹ μˆœ ν•„ν„°
  • μ§€μ›μž μ‚¬μš©μž 이미지 뢈러였기 μ—λŸ¬ -> ν”„λ‘ νŠΈμ—μ„œ jpeg으둜 λ³€ν™˜ν•΄μ£ΌλŠ” 것이 쒋을 λ“―.
  • μ§€μ›ν˜„ν™©-ν•„ν„°(파트, μƒνƒœ)
  • 문자/메일 ν…œν”Œλ¦Ώ μˆ˜μ •κΈ°λŠ₯
  • 메일 보낼 λ•Œ 예쁘게 λ³΄λ‚΄κ³ μ‹ΆμŒ -> ν…œν”Œλ¦Ώ 자체λ₯Ό ν”„λ‘ νŠΈμ—μ„œ μž…ν˜€μ„œ μ„œλ²„μ— μ£ΌλŠ” 게 쒋을 λ“―
  • μ§€μ›ν˜„ν™©-μ§€μ›μž 검색
  • μ§€μ›μž 정보 μ—‘μ…€ λ‹€μš΄
  • μ§€μ›μ„œ μ œμΆœν•˜λ©΄ μ„œλ₯˜ 합격 λ°œν‘œμΌ 같은거 메일 μžλ™ 전솑 - 1μ°¨ μˆ˜μ • μ‹œ 반영 μ™„λ£Œ
  • μ§€μ›νŒŒνŠΈ μ„€μ • μ•ˆλ˜μ–΄μžˆμ„λ•Œ ν‰κ°€μž λΆ„λ°° - λ…Όμ˜ ν•„μš”
  • 문자 λ³΄λ‚΄λŠ” 번호 κ΄€λ¦¬μžλ²ˆν˜Έλ‘œ μ„€μ • - λ…Όμ˜ ν•„μš”(μˆ˜μ •μ–Έλ‹ˆ 번호?)

πŸ’¬ Review Requirements (Optional)

Summary by CodeRabbit

  • μƒˆλ‘œμš΄ κΈ°λŠ₯
    • κ΄€λ¦¬μž: 쑰직 μ—­ν• Β·μƒνƒœΒ·ν‚€μ›Œλ“œ 검색 ν•„ν„° μΆ”κ°€
    • κ΄€λ¦¬μž: μ§€μ›μ„œ 상세 μ—‘μ…€ 내보내기 κΈ°λŠ₯ μΆ”κ°€
    • ν…œν”Œλ¦Ώ μˆ˜μ •(μ—…λ°μ΄νŠΈ) κΈ°λŠ₯ μΆ”κ°€
  • λ™μž‘ λ³€κ²½
    • κ΄€λ¦¬μž μ§€μ›μ„œ κΈ°λ³Έ 정렬을 μ΅œμ‹ μˆœ(LATEST/DESC)으둜 λ³€κ²½
  • μ„±λŠ₯/인프라
    • 닀건 쑰회 μ§€μ›μœΌλ‘œ λŒ€μš©λŸ‰ μ—‘μ…€ 내보내기 μ„±λŠ₯ κ°œμ„ 
  • 작무
    • μ—‘μ…€ 처리용 라이브러리 μ˜μ‘΄μ„± μΆ”κ°€

✏️ Tip: You can customize this high-level summary in your review settings.

@EunjinWoo EunjinWoo self-assigned this Dec 11, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 11, 2025

Walkthrough

κ΄€λ¦¬μž μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λͺ©λ‘μ— 닀쀑 ν•„ν„°(organizationRoleIds, statuses, keyword)와 κΈ°λ³Έ μ •λ ¬ λ³€κ²½(LATEST/DESC)을 λ„μž…ν•˜κ³ , Excel 내보내기(Workbook μƒμ„±Β·μŠ€νŠΈλ¦¬λ°) κΈ°λŠ₯ 및 Apache POI μ˜μ‘΄μ„±μ„ μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€. 평가/μ§€μ›μž 배치 쑰회용 λ ˆν¬μ§€ν† λ¦¬ λ©”μ„œλ“œμ™€ ν…œν”Œλ¦Ώ μˆ˜μ • APIΒ·μ„œλΉ„μŠ€Β·μ—”ν‹°ν‹° μ—…λ°μ΄νŠΈλ„ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

Changes

Cohort / File(s) Summary
μ˜μ‘΄μ„±
\build.gradle``
org.apache.poi:poi-ooxml:5.2.3 μΆ”κ°€ (Excel 처리용)
μ €μž₯μ†Œ(배치 쑰회)
**src/main/java/.../applicantAvailability/repository/**, **src/main/java/.../evaluation/evaluation/repository/**
findAllByApplicationIdIn(List<Long> appIds) 배치 쑰회 λ©”μ„œλ“œ μΆ”κ°€ (ApplicantAvailability, Evaluation - Jpa/Repo/Impl 계측)
κ΄€λ¦¬μž μ• ν”Œλ¦¬μΌ€μ΄μ…˜ (컨트둀러 β†’ μ„œλΉ„μŠ€)
\src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java`, `src/main/java/KUSITMS/WITHUS/domain/application/application/enumerate/AdminApplicationSortField.java`, `src/main/java/KUSITMS/WITHUS/domain/application/application/service/**``
λͺ©λ‘ μ‘°νšŒμ— organizationRoleIds, statuses, keyword νŒŒλΌλ―Έν„° μΆ”κ°€, κΈ°λ³Έ 정렬을 LATEST/DESC둜 λ³€κ²½, Excel 내보내기 μ—”λ“œν¬μΈνŠΈ μΆ”κ°€, μ„œλΉ„μŠ€μ— ν•„ν„°Β·μ •λ ¬Β·Excel 상세 쑰회 λ©”μ„œλ“œ μΆ”κ°€
Excel μœ ν‹Έλ¦¬ν‹°
\src/main/java/KUSITMS/WITHUS/global/util/excel/ExcelExporter.java``
List<ApplicationResponseDTO.Detail>λ₯Ό Apache POI Workbook으둜 λ³€ν™˜ν•˜λŠ” createExcel μœ ν‹Έ 클래슀 μΆ”κ°€
ν…œν”Œλ¦Ώ CRUD ν™•μž₯
\src/main/java/KUSITMS/WITHUS/domain/template/controller/TemplateController.java`, `.../dto/TemplateRequestDTO.java`, `.../entity/Template.java`, `.../service/TemplateService*.java``
ν…œν”Œλ¦Ώ μˆ˜μ •μš© DTO(Update)Β·μ„œλΉ„μŠ€ μΈν„°νŽ˜μ΄μŠ€/κ΅¬ν˜„ λ©”μ„œλ“œ μΆ”κ°€, Controller에 PUT /api/v1/templates/{templateId} μ—”λ“œν¬μΈνŠΈ μΆ”κ°€, Template 엔티티에 update λ©”μ„œλ“œ μΆ”κ°€

Sequence Diagram(s)

sequenceDiagram
    participant Admin as Admin Client
    participant Controller as AdminApplicationController
    participant Service as ApplicationServiceImpl
    participant AppRepo as Application Repository
    participant AvailRepo as ApplicantAvailability Repository
    participant EvalRepo as Evaluation Repository
    participant Exporter as ExcelExporter
    participant Response as HttpServletResponse

    Admin->>Controller: GET /admin/.../applications/excel (recruitmentId, stage, sort, filters)
    Controller->>Service: getAllDetailForExcel(recruitmentId, stage, sortBy, direction, organizationRoleIds, statuses, keyword, userId)
    Service->>AppRepo: findByRecruitmentIdAndStage(...)
    AppRepo-->>Service: List<Application>
    Service->>AvailRepo: findAllByApplicationIdIn(appIds)
    AvailRepo-->>Service: List<ApplicantAvailability>
    Service->>EvalRepo: findAllByApplicationIdIn(appIds)
    EvalRepo-->>Service: List<Evaluation>
    Service->>Service: ν•„ν„°Β·μ •λ ¬ 적용, DTO λ§€ν•‘ (toDetail)
    Service-->>Controller: List<ApplicationResponseDTO.Detail>
    Controller->>Exporter: createExcel(detailList)
    Exporter-->>Controller: Workbook
    Controller->>Response: set headers & write workbook bytes
    Response-->>Admin: Excel 파일 응닡
Loading
sequenceDiagram
    participant Admin as Admin Client
    participant Controller as AdminApplicationController
    participant Service as ApplicationServiceImpl
    participant AppRepo as Application Repository

    Admin->>Controller: GET /admin/.../applications/list (recruitmentId, stage, sort, pageable, filters)
    Controller->>Service: getByRecruitmentIdForAdmin(recruitmentId, stage, pageable, sortBy, direction, organizationRoleIds, statuses, keyword)
    Service->>AppRepo: findByRecruitmentIdAndStage(...)
    AppRepo-->>Service: List<Application>
    Service->>Service: ν•„ν„° 적용 (organizationRoleIds, statuses, keyword)
    Service->>Service: μ •λ ¬ 적용 (LATEST λ“±) -> νŽ˜μ΄μ§• 및 단계별 카운트 생성
    Service-->>Controller: AdminPageWithStageCounts
    Controller-->>Admin: νŽ˜μ΄μ§•λœ 응닡
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • μ£Όμ˜ν•  파일/μ˜μ—­:
    • ApplicationServiceImpl: 닀쀑 ν•„ν„°Β·μ •λ ¬ 둜직과 getSortedApps 검증
    • ExcelExporter: 컬럼 λ§€ν•‘, 널 처리, λ‚ μ§œ ν˜•μ‹ 확인
    • AdminApplicationController: HttpServletResponse 슀트리밍 및 μ˜ˆμ™Έ 처리
    • λ ˆν¬μ§€ν† λ¦¬ 배치 쑰회 λ©”μ„œλ“œ: 쿼리 μ„±λŠ₯ 및 N+1 κ°€λŠ₯μ„± κ²€ν† 
    • Template update 흐름: μœ νš¨μ„± 검사와 νŠΈλžœμž­μ…˜ 경계 확인

Possibly related issues

Possibly related PRs

Suggested labels

πŸ›bug

Suggested reviewers

  • SeongHo5356
  • KJaeKwan

Poem

🐰 λ‚˜λŠ” 토끼, μ½”λ“œλ°­μ„ λ›°μ–΄λ‹€λ…€
정렬은 μ΅œμ‹ μœΌλ‘œ, ν•„ν„°λŠ” λŠ˜μ—ˆλ„€
μ—‘μ…€ ν•œ μž₯에 μ§€μ›μ„œλ“€μ΄ 반짝이고
ν…œν”Œλ¦Ώ κ³ μ³μ£Όλ‹ˆ 메일도 λ°˜μ§μ—¬
λ‹Ήκ·ΌμœΌλ‘œ μΆ•ν•˜ν•΄μš”, 힘찬 λ°°ν¬ν•˜μ„Έμš© πŸ₯•

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive PR 제λͺ©μ€ 'κ°œμ„ μ  λͺ¨μŒ 마무리 μˆ˜μ •'으둜 맀우 λͺ¨ν˜Έν•˜λ©°, ꡬ체적인 변경사항을 μ„€λͺ…ν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€. 제λͺ©μ„ ꡬ체적으둜 λ³€κ²½ν•˜μ„Έμš”. 예: 'κ΄€λ¦¬μž μ§€μ›ν˜„ν™© ν•„ν„° μΆ”κ°€ 및 μ—‘μ…€ 내보내기 κΈ°λŠ₯ κ΅¬ν˜„', 'ν…œν”Œλ¦Ώ μˆ˜μ • κΈ°λŠ₯ 및 μ§€μ›μž μ—‘μ…€ 내보내기 μΆ”κ°€'
βœ… Passed checks (1 passed)
Check name Status Explanation
Description check βœ… Passed PR μ„€λͺ…이 ν…œν”Œλ¦Ώμ„ λ”°λ₯΄κ³  있으며, κ΄€λ ¨ μ΄μŠˆμ™€ μ™„λ£Œλœ μž‘μ—… ν•­λͺ©λ“€μ„ λͺ…ν™•ν•˜κ²Œ λ‚˜μ—΄ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.
✨ Finishing touches
  • πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/159-3rd

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.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (7)
src/main/java/KUSITMS/WITHUS/domain/application/applicantAvailability/repository/ApplicantAvailabilityRepository.java (1)

12-12: LGTM! Excel 내보내기λ₯Ό μœ„ν•œ 배치 쑰회 λ©”μ„œλ“œκ°€ μ˜¬λ°”λ₯΄κ²Œ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜κ°€ Spring Data JPA κ·œμΉ™μ„ λ”°λ₯΄κ³  있으며, μ—¬λŸ¬ Application ID둜 ApplicantAvailabilityλ₯Ό μ‘°νšŒν•˜λŠ” κΈ°λŠ₯이 μ •ν™•ν•˜κ²Œ κ΅¬ν˜„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

λ‹€λ§Œ, κΈ°μ‘΄ λ©”μ„œλ“œλ“€(findByApplicationIn, findByApplicationId)은 "All" 접두사λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 반면, μƒˆλ‘œ μΆ”κ°€λœ λ©”μ„œλ“œλŠ” findAllBy...λ₯Ό μ‚¬μš©ν•˜μ—¬ 넀이밍 일관성이 λ‹€μ†Œ λ–¨μ–΄μ§‘λ‹ˆλ‹€. Spring Data JPAμ—μ„œ "All"은 선택적이며 λ™μž‘μ—λŠ” 영ν–₯을 μ£Όμ§€ μ•Šμ§€λ§Œ, 일관성을 μœ„ν•΄ λ‹€μŒ 쀑 ν•˜λ‚˜λ₯Ό κ³ λ €ν•΄λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€:

-    List<ApplicantAvailability> findAllByApplicationIdIn(List<Long> appIds);
+    List<ApplicantAvailability> findByApplicationIdIn(List<Long> appIds);
src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationService.java (1)

10-30: κ΄€λ¦¬μž 쑰회/μ—‘μ…€ λ‹€μš΄λ‘œλ“œμš© ν•„ν„° νŒŒλΌλ―Έν„° ν™•μž₯ 적절, id λͺ…ν™•ν™” μ œμ•ˆ

κ΄€λ¦¬μž 리슀트/μ—‘μ…€ 경둜 λͺ¨λ‘μ—μ„œ λ™μΌν•œ ν•„ν„°(쑰직 μ—­ν• , μƒνƒœ, ν‚€μ›Œλ“œ)λ₯Ό 받도둝 μ‹œκ·Έλ‹ˆμ²˜λ₯Ό ν™•μž₯ν•œ 점은 μš”κ΅¬μ‚¬ν•­κ³Ό 잘 λ§žμŠ΅λ‹ˆλ‹€. λ‹€λ§Œ getAllDetailForExcel 의 λ§ˆμ§€λ§‰ 인자 이름이 λ‹¨μˆœ id λΌμ„œ, currentUserId λ‚˜ adminId λ“± μ˜λ―Έκ°€ λ“œλŸ¬λ‚˜λŠ” μ΄λ¦„μœΌλ‘œ λ°”κΎΈλ©΄ 이후 μœ μ§€λ³΄μˆ˜ μ‹œ ν˜Όλ™μ„ μ€„μ΄λŠ” 데 도움이 될 것 κ°™μŠ΅λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/domain/evaluation/evaluation/repository/EvaluationRepositoryImpl.java (1)

88-92: JPA λ ˆν¬μ§€ν† λ¦¬ μœ„μž„ κ΅¬ν˜„μ€ 적절, λŒ€λŸ‰ 쑰회 μ‹œ ν™•μž₯ μ—¬μ§€

findAllByApplicationIdIn 을 JPA λ ˆν¬μ§€ν† λ¦¬μ— λ‹¨μˆœ μœ„μž„ν•˜λŠ” κ΅¬ν˜„μ€ κΉ”λ”ν•˜κ³  μ΄ν•΄ν•˜κΈ° μ‰½μŠ΅λ‹ˆλ‹€. ν–₯ν›„ μ—‘μ…€ λ‹€μš΄λ‘œλ“œ λ“±μ—μ„œ 맀우 λ§Žμ€ μ§€μ›μ„œ ID에 λŒ€ν•΄ μ‚¬μš©λœλ‹€λ©΄, 별도 νŽ˜μ΄μ§• μΏΌλ¦¬λ‚˜ 슀트리밍 λ°©μ‹μœΌλ‘œ ν™•μž₯ν•  수 μžˆλ„λ‘λ§Œ 염두에 λ‘μ‹œλ©΄ 될 것 κ°™μŠ΅λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/global/util/excel/ExcelExporter.java (1)

40-45: 숫자 ν•„λ“œμ˜ null 처리 κ³ λ €

documentAverageScore, interviewAverageScore, acquaintanceCount λ“±μ˜ ν•„λ“œκ°€ Doubleμ΄λ‚˜ Integer 래퍼 νƒ€μž…μ΄κ³  null일 경우, setCellValue()μ—μ„œ unboxing μ‹œ NPEκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. κΈ°λ³Έκ°’ 처리λ₯Ό κ³ λ €ν•΄ λ³΄μ„Έμš”.

-            row.createCell(8).setCellValue(dto.documentAverageScore());
-            row.createCell(9).setCellValue(dto.interviewAverageScore());
+            row.createCell(8).setCellValue(dto.documentAverageScore() != null ? dto.documentAverageScore() : 0.0);
+            row.createCell(9).setCellValue(dto.interviewAverageScore() != null ? dto.interviewAverageScore() : 0.0);
             row.createCell(10).setCellValue(dto.address());
             row.createCell(11).setCellValue(dto.birthDate() != null ? dto.birthDate().toString() : "");
             row.createCell(12).setCellValue(dto.university());
-            row.createCell(13).setCellValue(dto.acquaintanceCount());
+            row.createCell(13).setCellValue(dto.acquaintanceCount() != null ? dto.acquaintanceCount() : 0);
src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java (1)

62-63: Swagger @Operation μ–΄λ…Έν…Œμ΄μ…˜ λˆ„λ½

λ‹€λ₯Έ μ—”λ“œν¬μΈνŠΈλ“€κ³Ό 달리 downloadExcel λ©”μ„œλ“œμ— @Operation μ–΄λ…Έν…Œμ΄μ…˜μ΄ μ—†μ–΄ API λ¬Έμ„œν™”κ°€ λˆ„λ½λ©λ‹ˆλ‹€.

     @GetMapping("/recruitment/{recruitmentId}/excel")
+    @Operation(summary = "μ§€μ›μ„œ μ—‘μ…€ λ‹€μš΄λ‘œλ“œ", description = "곡고별 μ§€μ›μ„œ λͺ©λ‘μ„ ν•„ν„° 쑰건에 따라 μ—‘μ…€ 파일둜 λ‹€μš΄λ‘œλ“œν•©λ‹ˆλ‹€.")
     public void downloadExcel(
src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (2)

324-379: Comparator λ‚΄μ—μ„œ DTO 생성은 μ„±λŠ₯ μ €ν•˜λ₯Ό μœ λ°œν•©λ‹ˆλ‹€.

allApps.sort() 비ꡐ ν•¨μˆ˜ λ‚΄μ—μ„œ 맀번 SummaryForAdmin.from()을 ν˜ΈμΆœν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜μ€ O(n log n) 비ꡐλ₯Ό μˆ˜ν–‰ν•˜λ―€λ‘œ, n개의 μš”μ†Œμ— λŒ€ν•΄ 수만 번의 DTO 생성이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ˜ν•œ, Double.parseDouble()이 μœ νš¨ν•˜μ§€ μ•Šμ€ λ¬Έμžμ—΄μ— λŒ€ν•΄ NumberFormatException을 던질 수 μžˆμŠ΅λ‹ˆλ‹€.

μ •λ ¬ 전에 DTOλ₯Ό ν•œ 번만 μƒμ„±ν•˜κ±°λ‚˜, 정렬에 ν•„μš”ν•œ κ°’λ§Œ 미리 μΆ”μΆœν•˜λŠ” 방식을 ꢌμž₯ν•©λ‹ˆλ‹€:

+    @NotNull
+    private static List<Application> getSortedApps(AdminApplicationSortField sortBy, Sort.Direction direction, List<Application> allApps) {
+        // μ •λ ¬ 전에 DTOλ₯Ό 미리 μƒμ„±ν•˜μ—¬ Map으둜 캐싱
+        Map<Long, ApplicationResponseDTO.SummaryForAdmin> dtoCache = allApps.stream()
+                .collect(Collectors.toMap(Application::getId, a -> ApplicationResponseDTO.SummaryForAdmin.from(a, 0L)));
+
         allApps.sort((a, b) -> {
-            var sa = ApplicationResponseDTO.SummaryForAdmin.from(a, 0L);
-            var sb = ApplicationResponseDTO.SummaryForAdmin.from(b, 0L);
+            var sa = dtoCache.get(a.getId());
+            var sb = dtoCache.get(b.getId());
             // ... λ‚˜λ¨Έμ§€ 둜직 동일

469-478: 필터링 둜직 쀑볡 - 곡톡 λ©”μ„œλ“œ μΆ”μΆœ ꢌμž₯

getByRecruitmentIdForAdminκ³Ό getAllDetailForExcel λ©”μ„œλ“œμ—μ„œ organizationRoleIds, statuses, keyword 필터링 둜직이 거의 λ™μΌν•˜κ²Œ λ°˜λ³΅λ©λ‹ˆλ‹€. μœ μ§€λ³΄μˆ˜μ„±μ„ μœ„ν•΄ 곡톡 private λ©”μ„œλ“œλ‘œ μΆ”μΆœν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.

private List<Application> applyFilters(
        List<Application> apps,
        List<Long> organizationRoleIds,
        List<ApplicationStatus> statuses,
        String keyword
) {
    Stream<Application> stream = apps.stream();
    
    if (organizationRoleIds != null && !organizationRoleIds.isEmpty()) {
        stream = stream.filter(app ->
                app.getOrganizationRole() != null &&
                organizationRoleIds.contains(app.getOrganizationRole().getId()));
    }
    
    if (statuses != null && !statuses.isEmpty()) {
        stream = stream.filter(app -> statuses.contains(app.getStatus()));
    }
    
    if (keyword != null && !keyword.isBlank()) {
        String lower = keyword.toLowerCase();
        stream = stream.filter(app ->
                app.getName() != null && app.getName().toLowerCase().contains(lower));
    }
    
    return stream.collect(Collectors.toList());
}
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between bf01ff8 and 3157af1.

πŸ“’ Files selected for processing (15)
  • build.gradle (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/application/applicantAvailability/repository/ApplicantAvailabilityRepository.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java (2 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/application/application/enumerate/AdminApplicationSortField.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationService.java (2 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (4 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/evaluation/evaluation/repository/EvaluationJpaRepository.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/evaluation/evaluation/repository/EvaluationRepository.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/evaluation/evaluation/repository/EvaluationRepositoryImpl.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/template/controller/TemplateController.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/template/dto/TemplateRequestDTO.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/template/entity/Template.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/template/service/TemplateService.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/template/service/TemplateServiceImpl.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/global/util/excel/ExcelExporter.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java (1)
src/main/java/KUSITMS/WITHUS/global/util/excel/ExcelExporter.java (1)
  • ExcelExporter (9-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-docker-image
πŸ”‡ Additional comments (10)
build.gradle (1)

78-80: Excel μ˜μ‘΄μ„± μΆ”κ°€ 적절

κ΄€λ¦¬μž μ—‘μ…€ λ‹€μš΄λ‘œλ“œ κΈ°λŠ₯을 μœ„ν•΄ org.apache.poi:poi-ooxml:5.2.3 을 μΆ”κ°€ν•œ 선택은 μžμ—°μŠ€λŸ½κ³ , ν˜„μž¬λ‘œμ„œλŠ” 별닀λ₯Έ 문제 μ—†μ–΄ λ³΄μž…λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/domain/evaluation/evaluation/repository/EvaluationRepository.java (1)

21-21: μ—¬λŸ¬ μ§€μ›μ„œ ID둜 평가 일괄 쑰회 λ©”μ„œλ“œ μΆ”κ°€ 적절

findAllByApplicationIdIn μΆ”κ°€λŠ” 도메인 μš”κ΅¬(μ—¬λŸ¬ μ§€μ›μ„œμ— λŒ€ν•œ 평가 일괄 쑰회)에 μžμ—°μŠ€λŸ½κ³ , κΈ°μ‘΄ existsByApplicationId... νŒ¨ν„΄κ³Όλ„ 일관적이라 μ΄ν•΄ν•˜κΈ° μ‰½μŠ΅λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/domain/evaluation/evaluation/repository/EvaluationJpaRepository.java (1)

17-17: νŒŒμƒ 쿼리 λ©”μ„œλ“œ μΆ”κ°€ 문제 μ—†μŒ

findAllByApplicationIdIn νŒŒμƒ 쿼리 λ©”μ„œλ“œ μΆ”κ°€κ°€ μƒμœ„ μΈν„°νŽ˜μ΄μŠ€/κ΅¬ν˜„μ²΄μ™€ 잘 맞고, κΈ°μ‘΄ λ©”μ„œλ“œ 넀이밍 μŠ€νƒ€μΌκ³Όλ„ μΌκ΄€μ μž…λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/domain/application/application/enumerate/AdminApplicationSortField.java (1)

4-4: μ •λ ¬ ν•„λ“œμ— LATEST μΆ”κ°€ 적절, λ§€ν•‘ κΈ°μ€€λ§Œ ν•œ 번 더 확인 ν•„μš”

κ΄€λ¦¬μž ν™”λ©΄μ—μ„œ μ΅œμ‹ μˆœ μ •λ ¬ μ˜΅μ…˜μ„ μ œκ³΅ν•˜κΈ° μœ„ν•΄ LATEST μƒμˆ˜λ₯Ό μΆ”κ°€ν•œ 뢀뢄은 UX κ΄€μ μ—μ„œ μžμ—°μŠ€λŸ½μŠ΅λ‹ˆλ‹€. λ‹€λ§Œ μ„œλΉ„μŠ€/쿼리 κ΅¬ν˜„λΆ€μ—μ„œ LATEST κ°€ 생성일, 지원 ID μ—­μˆœ λ“± μ–΄λ–€ 컬럼 κΈ°μ€€μœΌλ‘œ λ§€ν•‘λ˜μ—ˆλŠ”μ§€ ν•œ 번 더 점검해 μ£Όμ„Έμš”(μΆ”ν›„ μ •λ ¬ κΈ°μ€€ λ³€κ²½ μ‹œμ—λ„ enum 이름과 μ˜λ―Έκ°€ μ–΄κΈ‹λ‚˜μ§€ μ•Šλ„λ‘).

src/main/java/KUSITMS/WITHUS/domain/template/service/TemplateService.java (1)

14-15: ν…œν”Œλ¦Ώ μˆ˜μ • κΈ°λŠ₯을 μœ„ν•œ Service μΈν„°νŽ˜μ΄μŠ€ ν™•μž₯ 적절

create 와 λ™μΌν•˜κ²Œ Detail 을 λ°˜ν™˜ν•˜λŠ” update λ©”μ„œλ“œ μΆ”κ°€λ‘œ ν…œν”Œλ¦Ώ CRUD 흐름이 κΉ”λ”ν•΄μ‘ŒμŠ΅λ‹ˆλ‹€. ν˜„μž¬ κ΅¬ν˜„/컨트둀러/DTO와 μ‹œκ·Έλ‹ˆμ²˜κ°€ μΌκ΄€λ˜λ‹€λ©΄ μΆ”κ°€ μˆ˜μ • 없이도 무리 없을 것 κ°™μŠ΅λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/domain/template/controller/TemplateController.java (1)

54-62: LGTM!

μ—”λ“œν¬μΈνŠΈ κ΅¬ν˜„μ΄ κΈ°μ‘΄ νŒ¨ν„΄μ„ λ”°λ₯΄κ³  있으며, @Validλ₯Ό ν†΅ν•œ μž…λ ₯ 검증과 Swagger λ¬Έμ„œν™”κ°€ μ μ ˆν•˜κ²Œ μ μš©λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μ„œλΉ„μŠ€ λ ˆμ΄μ–΄μ—μ„œ κΆŒν•œ 검증이 μΆ”κ°€λœλ‹€λ©΄ μ™„μ „ν•œ κ΅¬ν˜„μ΄ 될 κ²ƒμž…λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java (1)

45-60: LGTM!

ν•„ν„° νŒŒλΌλ―Έν„° 좔가와 κΈ°λ³Έ μ •λ ¬ μˆœμ„œ λ³€κ²½(LATEST/DESC)이 PR μš”κ΅¬μ‚¬ν•­μ— 맞게 잘 κ΅¬ν˜„λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 선택적 νŒŒλΌλ―Έν„°λ‘œ μ„€μ •ν•˜μ—¬ κΈ°μ‘΄ ν˜Έν™˜μ„±λ„ μœ μ§€λ©λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/global/util/excel/ExcelExporter.java (1)

36-45: μƒνƒœ ν•„λ“œμ˜ NPE κ°€λŠ₯성은 μ—†μŠ΅λ‹ˆλ‹€.

status ν•„λ“œλŠ” Application μ—”ν‹°ν‹°μ—μ„œ @Column(nullable = false) μ œμ•½μ‘°κ±΄μ΄ μžˆμœΌλ―€λ‘œ null이 될 수 μ—†μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ dto.status().name()은 NPEλ₯Ό λ°œμƒμ‹œν‚€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. gender와 birthDateλŠ” NOT NULL μ œμ•½μ΄ μ—†λŠ” nullable ν•„λ“œμ΄κΈ° λ•Œλ¬Έμ— null 체크가 ν•„μš”ν•˜μ§€λ§Œ, statusλŠ” λ°μ΄ν„°λ² μ΄μŠ€ μ œμ•½μ— μ˜ν•΄ 항상 값을 κ°€μ§‘λ‹ˆλ‹€.

Likely an incorrect or invalid review comment.

src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (2)

512-555: N+1 문제 해결을 μœ„ν•œ bulk 쑰회 μ΅œμ ν™” - μ’‹μŠ΅λ‹ˆλ‹€.

λ©΄μ ‘ κ°€λŠ₯ μ‹œκ°„κ³Ό 평가 데이터λ₯Ό findAllByApplicationIdIn으둜 bulk μ‘°νšŒν•˜μ—¬ N+1 문제λ₯Ό λ°©μ§€ν•œ 점이 μ’‹μŠ΅λ‹ˆλ‹€. Map을 ν™œμš©ν•œ 그룹핑도 μ μ ˆν•©λ‹ˆλ‹€.


368-370: LATEST μ •λ ¬ μΌ€μ΄μŠ€ μΆ”κ°€ - LGTM

createdAt κΈ°μ€€ 정렬이 μ˜¬λ°”λ₯΄κ²Œ κ΅¬ν˜„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

Comment thread src/main/java/KUSITMS/WITHUS/domain/template/entity/Template.java
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (1)

324-379: μ •λ ¬ Comparatorκ°€ β€œλ¬Έμžβ†’μˆ«μž νŒŒμ‹±/널 κ°€λŠ₯ ν•„λ“œ 비ꡐ”에 μ·¨μ•½ν•©λ‹ˆλ‹€
DOCUMENT_SCORE/INTERVIEW_SCOREμ—μ„œ Double.parseDouble(...)이 빈 λ¬Έμžμ—΄/비정상 값이면 NumberFormatException이 λ‚  수 있고, NAME/POSITION_NAME도 null이면 NPEκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€(DTO ν•„λ“œκ°€ 항상 non-nullμ΄λΌλŠ” 보μž₯이 μ—†μœΌλ©΄). μ΅œμ†Œν•œ μ•ˆμ „ νŒŒμ‹±/널 세이프 비ꡐλ₯Ό λ„£λŠ” 편이 μ’‹μŠ΅λ‹ˆλ‹€.

-                case DOCUMENT_SCORE:
-                    cmp = Double.compare(
-                            Double.parseDouble(sa.documentAverageScore()),
-                            Double.parseDouble(sb.documentAverageScore())
-                    );
+                case DOCUMENT_SCORE:
+                    cmp = Double.compare(
+                            safeParseDouble(sa.documentAverageScore()),
+                            safeParseDouble(sb.documentAverageScore())
+                    );
                     break;
                 case INTERVIEW_SCORE:
-                    cmp = Double.compare(
-                            Double.parseDouble(sa.interviewAverageScore()),
-                            Double.parseDouble(sb.interviewAverageScore())
-                    );
+                    cmp = Double.compare(
+                            safeParseDouble(sa.interviewAverageScore()),
+                            safeParseDouble(sb.interviewAverageScore())
+                    );
                     break;
                 case POSITION_NAME:
-                    cmp = sa.organizationRoleName().compareToIgnoreCase(sb.organizationRoleName());
+                    cmp = nullSafeString(sa.organizationRoleName())
+                            .compareToIgnoreCase(nullSafeString(sb.organizationRoleName()));
                     break;
...
                 case NAME:
                 default:
-                    cmp = sa.name().compareToIgnoreCase(sb.name());
+                    cmp = nullSafeString(sa.name())
+                            .compareToIgnoreCase(nullSafeString(sb.name()));
                     break;

(μœ„ diffλ₯Ό μ μš©ν•˜λ €λ©΄ 파일 내에 safeParseDouble, nullSafeString 헬퍼 λ©”μ„œλ“œ μΆ”κ°€κ°€ ν•„μš”ν•©λ‹ˆλ‹€.)

Also applies to: 327-377

♻️ Duplicate comments (3)
src/main/java/KUSITMS/WITHUS/domain/template/entity/Template.java (1)

49-57: MAIL ν…œν”Œλ¦Ώ μ—…λ°μ΄νŠΈμ—λ„ 제λͺ© λΆˆλ³€μ‘°κ±΄(Subject required) μ μš©ν•œ 점 μ’‹μŠ΅λ‹ˆλ‹€.
μƒμ„±μžμ™€ λ™μΌν•œ 검증을 update()에도 λ„£μ–΄μ„œ 도메인 κ·œμΉ™μ΄ μ—…λ°μ΄νŠΈ μ‹œμ μ— κΉ¨μ§€λŠ” 문제λ₯Ό λ§‰μ•˜μŠ΅λ‹ˆλ‹€.

src/main/java/KUSITMS/WITHUS/domain/template/service/TemplateServiceImpl.java (1)

65-80: ν…œν”Œλ¦Ώ μˆ˜μ • κΆŒν•œ(쑰직 μ†Œμœ κΆŒ) 검증이 TODO둜 남아 μžˆμ–΄ IDOR 취약점이 λ©λ‹ˆλ‹€.
listAll()처럼 β€œν˜„μž¬ μ‚¬μš©μžκ°€ μ†ν•œ 쑰직의 ν…œν”Œλ¦Ώλ§Œβ€ μˆ˜μ • κ°€λŠ₯ν•˜λ„λ‘, 쑰회 λ‹¨κ³„μ—μ„œλΆ€ν„° 쑰직 λ²”μœ„λ₯Ό κ±Έμ–΄λ‘κ±°λ‚˜(ꢌμž₯), 쑰회 ν›„ 쑰직 일치 검증을 λ°˜λ“œμ‹œ μΆ”κ°€ν•΄μ•Ό ν•©λ‹ˆλ‹€.

@@
-    public TemplateResponseDTO.Detail update(Long templateId, TemplateRequestDTO.Update dto) {
-        Template template = templateRepository.getById(templateId);
-
-        // TODO: μ‚¬μš©μžκ°€ μ†ν•œ 쑰직의 ν…œν”Œλ¦Ώλ§Œ μˆ˜μ •ν•˜λ„λ‘ 검증 μΆ”κ°€ ν•„μš”
+    public TemplateResponseDTO.Detail update(Long templateId, TemplateRequestDTO.Update dto, User user) {
+        List<Long> organizationIds = user.getUserOrganizations().stream()
+                .map(uo -> uo.getOrganization().getId())
+                .toList();
+
+        // ꢌμž₯: repositoryμ—μ„œ "id + organizationIds"둜 ν•¨κ»˜ 쑰회되게 ν•΄μ„œ 우회 자체λ₯Ό 차단
+        Template template = templateRepository.getById(templateId);
+        if (!organizationIds.contains(template.getOrganization().getId())) {
+            // TODO: ν”„λ‘œμ νŠΈμ˜ ν‘œμ€€ κΆŒν•œ μ˜ˆμ™Έ/μ—λŸ¬μ½”λ“œλ‘œ ꡐ체
+            throw new CustomException(ErrorCode.FORBIDDEN);
+        }
@@
         template.update(
                 dto.name(),
                 dto.subject(),
                 dto.body(),
                 dto.medium()
         );
src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (1)

253-322: (이전 지적 반영) ν•„ν„° ν›„ mutable list μœ μ§€ + name null-guard 처리 μ’‹μ•„μš”
Stream.toList() λŒ€μ‹  collect(Collectors.toList())둜 μ •λ ¬ μ‹œ UnsupportedOperationException 리슀크λ₯Ό μ œκ±°ν–ˆκ³ , ν‚€μ›Œλ“œ ν•„ν„°μ—μ„œ getName() null 체크도 λ“€μ–΄κ°”μŠ΅λ‹ˆλ‹€.

Also applies to: 266-292

🧹 Nitpick comments (3)
src/main/java/KUSITMS/WITHUS/domain/template/dto/TemplateRequestDTO.java (1)

29-42: subject의 쑰건뢀 ν•„μˆ˜(= medium==MAIL일 λ•Œλ§Œ) 검증을 μš”μ²­ DTO λ‹¨κ³„μ—μ„œλ„ μ •λ¦¬ν•˜λŠ” 게 μ’‹μŠ΅λ‹ˆλ‹€.
ν˜„μž¬λŠ” μ—”ν‹°ν‹°μ—μ„œλ§Œ λ§‰νžˆλ―€λ‘œ, API κ΄€μ μ—μ„œ 4xx 응닡/λ©”μ‹œμ§€ 일관성을 μœ„ν•΄ medium 값에 λ”°λ₯Έ 쑰건뢀 검증(μ»€μŠ€ν…€ validator λ˜λŠ” DTO compact constructorμ—μ„œ 체크)을 κ³ λ €ν•΄ μ£Όμ„Έμš”.

src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (1)

284-292: ν‚€μ›Œλ“œ ν•„ν„°μ—μ„œ trim()을 μ‹€μ œ 맀칭에도 μ μš©ν•˜λŠ” 게 μ•ˆμ „ν•©λ‹ˆλ‹€
ν˜„μž¬λŠ” 곡백 μ—¬λΆ€ 체크만 trim()을 μ“°κ³ , μ‹€μ œ λΉ„κ΅λŠ” 원문 keyword둜 λ‚΄λ €κ°€μ„œ " kim " 같은 μž…λ ₯이 κΈ°λŒ€μ™€ λ‹€λ₯΄κ²Œ λ™μž‘ν•  수 μžˆμ–΄μš”.

-        if (keyword != null && !keyword.trim().isEmpty()) {
-            String lower = keyword.toLowerCase();
+        if (keyword != null && !keyword.trim().isEmpty()) {
+            String lower = keyword.trim().toLowerCase(Locale.ROOT);
             allApps = allApps.stream()
                     .filter(app ->
                             app.getName() != null &&
                                     app.getName().toLowerCase().contains(lower)
                     )
                     .collect(Collectors.toList());
         }
src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java (1)

62-94: μ—‘μ…€ λ‹€μš΄λ‘œλ“œ: λŒ€μš©λŸ‰ 데이터면 λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰(Workbook) λ¦¬μŠ€ν¬κ°€ ν½λ‹ˆλ‹€
ExcelExporter.createExcelκ°€ XSSFWorkbook 기반이면 데이터가 λ§Žμ„ λ•Œ νž™μ„ 크게 μž‘μ•„λ¨Ήμ„ 수 μžˆμ–΄μ„œ, ν•„μš”ν•˜λ©΄ SXSSFWorkbook(슀트리밍) μ „ν™˜μ„ κ²€ν† ν•˜λŠ” 게 μ•ˆμ „ν•©λ‹ˆλ‹€.

Also applies to: 75-93

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 3157af1 and cfaf223.

πŸ“’ Files selected for processing (5)
  • src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java (2 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (4 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/template/dto/TemplateRequestDTO.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/template/entity/Template.java (1 hunks)
  • src/main/java/KUSITMS/WITHUS/domain/template/service/TemplateServiceImpl.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java (1)
src/main/java/KUSITMS/WITHUS/global/util/excel/ExcelExporter.java (1)
  • ExcelExporter (9-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-docker-image
πŸ”‡ Additional comments (1)
src/main/java/KUSITMS/WITHUS/domain/application/application/controller/AdminApplicationController.java (1)

45-60: κ΄€λ¦¬μž λͺ©λ‘ API: κΈ°λ³Έ 정렬을 LATEST/DESC둜 λ°”κΎΌ 건 μš”κ΅¬μ‚¬ν•­μ— λΆ€ν•©ν•©λ‹ˆλ‹€
ν•„ν„° νŒŒλΌλ―Έν„°λ„ μ„œλΉ„μŠ€λ‘œ 잘 μ „λ‹¬λ˜κ³  μžˆμ–΄μš”.

import KUSITMS.WITHUS.global.infra.upload.dto.FileResponseDTO;
import KUSITMS.WITHUS.global.infra.upload.service.FileUploadService;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟑 Minor

org.jetbrains.annotations.NotNull λ„μž…μ€ ν”„λ‘œμ νŠΈ ν‘œμ€€κ³Ό μΌμΉ˜ν•˜λŠ”μ§€ 확인 ν•„μš”
μ„œλ²„ μ½”λ“œ μ „λ°˜μ—μ„œ @NotNull을 μ–΄λ–€ μ–΄λ…Έν…Œμ΄μ…˜(예: jakarta.validation.constraints.NotNull, org.springframework.lang.NonNull)둜 ν†΅μΌν•˜λŠ”μ§€μ— 따라 일관성이 깨질 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ€– Prompt for AI Agents
In
src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java
around line 49, the file imports org.jetbrains.annotations.NotNull which may not
match the project's standard annotation; replace this import with the project's
agreed-upon nullability/validation annotation (e.g.,
jakarta.validation.constraints.NotNull or org.springframework.lang.NonNull) or
remove the import if unused, and update any @NotNull usages in this class to the
chosen annotation to keep consistency across the codebase.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (1)

49-49: 이전 λ¦¬λ·°μ—μ„œ μ§€μ λœ @NotNull μ–΄λ…Έν…Œμ΄μ…˜ μ΄μŠˆκ°€ μ—¬μ „νžˆ λ‚¨μ•„μžˆμŠ΅λ‹ˆλ‹€.

ν”„λ‘œμ νŠΈ μ „λ°˜μ˜ ν‘œμ€€ μ–΄λ…Έν…Œμ΄μ…˜(예: jakarta.validation.constraints.NotNull λ˜λŠ” org.springframework.lang.NonNull)κ³Ό μΌμΉ˜ν•˜λŠ”μ§€ 확인이 ν•„μš”ν•©λ‹ˆλ‹€.

🧹 Nitpick comments (1)
src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (1)

324-379: μ •λ ¬ 둜직이 μ€‘μ•™ν™”λ˜μ–΄ μ½”λ“œ μž¬μ‚¬μš©μ„±μ΄ ν–₯μƒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.

μƒˆλ‘œ μΆ”κ°€λœ LATEST μΌ€μ΄μŠ€(Lines 368-370)λŠ” createdAt을 κΈ°μ€€μœΌλ‘œ μ •λ ¬ν•˜λ©°, DESC λ°©ν–₯일 λ•Œ μ΅œμ‹ μˆœμœΌλ‘œ μ •λ ¬λ©λ‹ˆλ‹€.

μ°Έκ³ : 이 λ©”μ„œλ“œλŠ” μž…λ ₯ 리슀트λ₯Ό μ œμžλ¦¬μ—μ„œ μ •λ ¬ν•œ ν›„ λ™μΌν•œ 리슀트λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. μ΄λŠ” κΈ°λŠ₯μ μœΌλ‘œλŠ” λ¬Έμ œμ—†μ§€λ§Œ, λ°˜ν™˜λ¬Έμ„ μ œκ±°ν•˜κ³  void둜 λ³€κ²½ν•˜λŠ” 것이 μ˜λ„λ₯Ό 더 λͺ…ν™•νžˆ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Optional: λ©”μ„œλ“œλ₯Ό void둜 λ³€κ²½

-    @NotNull
-    private static List<Application> getSortedApps(AdminApplicationSortField sortBy, Sort.Direction direction, List<Application> allApps) {
+    private static void sortApps(AdminApplicationSortField sortBy, Sort.Direction direction, List<Application> allApps) {
         allApps.sort((a, b) -> {
             // ... sorting logic ...
         });
-        return allApps;
     }

그리고 호좜 뢀뢄을 λ‹€μŒκ³Ό 같이 λ³€κ²½:

-        List<Application> sortedApps = getSortedApps(sortBy, direction, allApps);
+        sortApps(sortBy, direction, allApps);
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between cfaf223 and eb009a7.

πŸ“’ Files selected for processing (1)
  • src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-docker-image
πŸ”‡ Additional comments (2)
src/main/java/KUSITMS/WITHUS/domain/application/application/service/ApplicationServiceImpl.java (2)

258-292: 이전 λ¦¬λ·°μ—μ„œ μ§€μ λœ λΆˆλ³€ 리슀트 및 NPE μ΄μŠˆκ°€ λͺ¨λ‘ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

  • collect(Collectors.toList())λ₯Ό μ‚¬μš©ν•˜μ—¬ κ°€λ³€ 리슀트 생성 βœ…
  • getName() null 체크 μΆ”κ°€ (Line 288) βœ…
  • trim() 및 Locale.ROOT μ‚¬μš©μœΌλ‘œ λ¬Έμžμ—΄ 비ꡐ 일관성 확보 βœ…

필터링 둜직이 μ •ν™•ν•˜κ³  μ•ˆμ „ν•˜κ²Œ κ΅¬ν˜„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.


469-559: μ—‘μ…€ 내보내기 λ©”μ„œλ“œκ°€ μ•ˆμ „ν•˜κ²Œ κ΅¬ν˜„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

이전 λ¦¬λ·°μ—μ„œ μ§€μ λœ λ¬Έμ œλ“€μ΄ λͺ¨λ‘ ν•΄κ²°λ˜μ—ˆμŠ΅λ‹ˆλ‹€:

  • getName() null 체크 포함 (Line 504) βœ…
  • 빈 리슀트 μ‘°κΈ° λ°˜ν™˜μœΌλ‘œ 빈 IN 쿼리 λ°©μ§€ (Lines 511-513) βœ…
  • Bulk 쑰회λ₯Ό ν†΅ν•œ μ„±λŠ₯ μ΅œμ ν™” (Lines 520-526) βœ…
  • κ΄€λ¦¬μž λͺ©λ‘ API와 λ™μΌν•œ ν•„ν„°/μ •λ ¬ 둜직 적용으둜 일관성 확보 βœ…

κ΅¬ν˜„μ΄ μ •ν™•ν•˜κ³  μ„±λŠ₯ 고렀사항도 잘 λ°˜μ˜λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

@EunjinWoo EunjinWoo merged commit 1b55b40 into develop Dec 13, 2025
3 checks passed
@EunjinWoo EunjinWoo changed the title πŸ› Fix: κ°œμ„ μ  λͺ¨μŒ 마무리 μˆ˜μ • πŸ› Fix: 3μ°¨ μŠ€ν”„λ¦°νŠΈ κ°œμ„ μ  μˆ˜μ • Dec 13, 2025
@EunjinWoo EunjinWoo changed the title πŸ› Fix: 3μ°¨ μŠ€ν”„λ¦°νŠΈ κ°œμ„ μ  μˆ˜μ • πŸ› Fix: 3μ°¨ μŠ€ν”„λ¦°νŠΈ κ°œμ„ μ μ„ μˆ˜μ •ν•œλ‹€ Dec 13, 2025
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.

1 participant