Skip to content

feat(notification): notification 도메인 구성 #28 - #65

Open
wlyoon921 wants to merge 1 commit into
developfrom
feat/28-notification-common-api
Open

feat(notification): notification 도메인 구성 #28#65
wlyoon921 wants to merge 1 commit into
developfrom
feat/28-notification-common-api

Conversation

@wlyoon921

Copy link
Copy Markdown

Summary

notification 조회 기능의 domain/application 기반을 구성했습니다.
공지, QnA, 전형요강 domain model을 추가했습니다.
조회 use case를 위한 input/output port, command/result, service, exception을 정의했습니다.

Related Issue

Closes #28

Scope

In scope:

  • Notice domain model
  • Faq domain model
  • RecruitmentGuideline domain model
  • NotificationPort
  • NotificationRepository port
  • NotificationService
  • NotificationNotFoundException
  • notification-application Bazel 의존성

Out of scope:

  • REST controller
  • JPA 저장소 구현
  • admin 등록/수정/삭제 API
  • 파일 서비스 연동
  • bootstrap 실행 설정
  • 게시 예약/상태 변경
  • 도메인 이벤트

Implementation

공지 목록/상세, QnA 목록/상세, 전형요강 조회 흐름을 application service로 구성했습니다.
NotificationService는 repository port에만 의존하도록 구성했습니다.
공지 등록, 수정, 삭제는 admin API 범위이므로 포함하지 않았습니다.

이 PR은 현재 전달받은 notification 조회 API 명세와 ERD 기준으로 공지/QnA/전형요강 조회에 필요한 도메인 골격을 우선 구성했습니다.
이슈 원문에 포함된 게시 예약, 상태 변경, 도메인 이벤트는 admin 등록/수정/삭제 API 범위와 함께 후속 작업으로 분리합니다.

Testing

  • Unit test code: 후속 PR에서 추가
  • Integration tests: 후속 PR에서 추가
  • Manual verification: 후속 PR에서 build/test 수행 예정

Deployment Notes

Feature flag: 없음
Migration required: 없음
Rollout considerations:

  • 실제 데이터 조회는 후속 persistence adapter PR에 의존합니다.
  • 파일 첨부 및 전형요강 파일 다운로드는 configuration/document 서비스 연동 범위입니다.

Checklist

  • Matches product/tech requirements
  • Backward compatibility considered
  • API success flow verified in a running environment
  • Real persistence adapter connected

@wlyoon921
wlyoon921 requested review from kusuri12-09 and tlgms July 30, 2026 11:33
@wlyoon921 wlyoon921 self-assigned this Jul 30, 2026
@wlyoon921 wlyoon921 linked an issue Jul 30, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
📝 Walkthrough

사용자는 공지사항, FAQ, 전형요강을 조회할 수 있는 애플리케이션 기반을 사용할 수 있습니다. REST API와 실제 저장소 연동은 포함하지 않습니다.

주요 변경

  • Notice, Faq, RecruitmentGuideline, RecruitmentSchedule 도메인 모델을 추가했습니다.
  • NotificationPort에 공지사항·FAQ 목록 및 상세 조회와 전형요강 조회 기능을 정의했습니다.
  • 조회 요청과 결과를 위한 Command, Result, PageResult 모델을 추가했습니다.
  • NoticeRepository, FaqRepository, RecruitmentGuidelineRepository 출력 포트를 추가했습니다.
  • NotificationService가 저장소 포트에만 의존하도록 구성했습니다.
  • 조회 대상이 없을 때 NotificationNotFoundException을 발생시킵니다.
  • 페이지 번호와 크기를 검증하고 목록 결과를 PageResult로 변환합니다.
  • 애플리케이션 모듈에 Spring Boot starter와 notification domain 의존성을 추가했습니다.

위험 영역

  • 실제 persistence adapter가 없으므로 저장소 구현과 데이터 조회 동작은 검증되지 않았습니다.
  • REST controller가 없으므로 외부 API 계약과 HTTP 오류 응답은 확정되지 않았습니다.
  • 페이지 범위 제한, 정렬, 예외 변환은 후속 테스트가 필요합니다.
  • 게시 상태, 예약 게시, 숨김 상태 변경 규칙은 아직 구현되지 않았습니다.

마이그레이션 및 호환성

  • 신규 notification application/domain 기반을 추가하므로 기존 API 호환성 변경은 없습니다.
  • 후속 작업에서 repository adapter가 각 출력 포트의 nullable 및 목록 계약을 구현해야 합니다.
  • REST 연동 시 NotificationPort의 입력·출력 모델과 NotificationNotFoundException의 오류 매핑을 유지해야 합니다.

검증 체크리스트 및 롤아웃

  • 도메인 모델 변환 테스트 추가
  • 페이지 검증 및 경계값 테스트 추가
  • 조회 대상 없음 예외 테스트 추가
  • repository adapter 연동 테스트 추가
  • REST controller와 오류 응답 계약 검증
  • 테스트 완료 후 notification 조회 API를 단계적으로 롤아웃
  • 게시 상태 및 도메인 이벤트 기능은 별도 작업으로 배포

Walkthrough

공지사항, FAQ, 채용 안내의 도메인 모델과 조회 계약을 추가했습니다. NotificationService는 저장소 포트를 통해 데이터를 조회하고 페이지 결과와 상세 결과로 변환합니다.

Changes

알림 조회 기능

Layer / File(s) Summary
알림 도메인 모델
systems/notification/notification-domain/src/main/kotlin/.../model/*
공지사항, FAQ, 채용 안내와 모집 일정을 표현하는 데이터 클래스를 추가했습니다.
조회 계약과 저장소 포트
systems/notification/notification-application/src/main/kotlin/.../port/*
페이지 명령, 목록·상세 결과, 채용 결과, 입력 포트와 저장소 포트를 추가했습니다.
알림 조회 서비스
systems/notification/notification-application/src/main/kotlin/.../service/NotificationService.kt, .../exception/NotificationNotFoundException.kt, systems/notification/notification-application/deps.bzl
공지사항과 FAQ 목록을 정렬하고 페이지 결과로 변환합니다. 상세 대상과 현재 채용 안내가 없으면 NotificationNotFoundException을 발생시킵니다. 필요한 Spring Boot 및 도메인 의존성을 추가했습니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: feature, kotlin, bazel

Suggested reviewers: tlgms

Sequence Diagram(s)

sequenceDiagram
  participant NotificationPort
  participant NotificationService
  participant NoticeRepository
  NotificationPort->>NotificationService: getNotices(ReadNotificationPageCommand)
  NotificationService->>NoticeRepository: findAll()
  NoticeRepository-->>NotificationService: List<Notice>
  NotificationService-->>NotificationPort: PageResult<NoticeSummaryResult>
Loading
🚥 Pre-merge checks | ✅ 5 | ❌ 5

❌ Failed checks (5 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning 도메인 모델은 추가했지만 #28의 값 객체, 상태 변경·게시 예약 규칙, 도메인 이벤트를 구현하지 않았습니다. 값 객체, 임시저장·게시·숨김 상태 변경, 게시 예약 규칙, 생성·상태 변경 도메인 이벤트를 구현하고 도메인 계층 독립성을 유지하십시오.
Out of Scope Changes check ⚠️ Warning #28의 도메인 계층 범위를 넘어 Application port, command/result, service, exception 및 저장소 port를 함께 추가했습니다. Application 계층과 저장소 port 변경을 별도 PR로 분리하거나, #28에 해당 범위를 명시한 연결 이슈를 추가하십시오.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 85.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Kotlin Layer Boundary ⚠️ Warning domain 파일에는 adapter/bootstrap import가 없지만, NotificationService가 org.springframework.stereotype.Service와 @Service를 직접 사용하며 application의 프레임워크 의존성에 대한 정당화가 없습니다. NotificationService에서 Spring import와 @Service를 제거하고 bootstrap 또는 adapter 계층에서 빈 등록을 담당하게 하십시오.
Behavior Change Needs Tests ⚠️ Warning Kotlin 운영 로직과 모델이 추가되었지만 같은 PR의 notification 테스트 변경은 없습니다. 설명도 테스트 불필요 사유가 아니라 후속 PR 연기만 명시합니다. notification-application과 notification-domain에 NotificationService의 조회·페이징·예외 검증 및 새 모델 테스트를 추가하고, PR 설명의 후속 연기 항목을 갱신하십시오.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 Conventional Commit 형식이며 변경 범위와 연결 이슈 #28을 명확히 나타냅니다.
Description check ✅ Passed 설명이 Notification 조회 기반 구성과 포함·제외 범위를 변경 사항과 관련 있게 설명합니다.
Go Error Context ✅ Passed PR 변경 파일은 Kotlin 14개와 .bzl 1개뿐이며, 변경된 Go 파일과 저장소 내 Go 파일이 없습니다. 따라서 Go 오류 래핑 검사는 적용되지 않습니다.
Bazel Formatting ✅ Passed notification-application/deps.bzl은 기존 4칸 들여쓰기와 정렬 형식을 따르며 공백·괄호 오류가 없습니다. 의존성 라벨은 존재하는 :main 타깃을 사용하고 저장소 전체 명명 규칙과 일치합니다.
Todo Must Reference Issue ✅ Passed HEAD(9ddabb0)의 부모 대비 추가 라인과 변경 파일에서 TODO/FIXME 주석을 찾지 못했습니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/28-notification-common-api
  • 🛠️ cleanup stale imports
  • 🛠️ harden error messages
  • 🛠️ test clarity pass

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.

@kusuri12-09

kusuri12-09 commented Aug 9, 2026

Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt`:
- Around line 3-6: NotificationService.toPage calculates page * size as an
overflowing Int, allowing negative indices to reach subList. Update toPage to
perform offset arithmetic in Long, clamp the resulting offset to the available
list-size range, and preserve valid pagination behavior; add a regression test
covering page = Int.MAX_VALUE with size = 2.

In
`@systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt`:
- Around line 5-7: Replace the all-items repository contracts with paginated
queries that accept page parameters and return both the page contents and total
count; in NoticeRepository, define deterministic createdAt DESC, id DESC
ordering. Apply this to
systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt
lines 5-7 and FaqRepository.kt lines 5-7. Update NotificationService in
systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt
lines 26-38 to map the repository page directly into the result DTO, removing
full-list sorting and subList pagination.

In
`@systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt`:
- Around line 103-107: Update the pagination index calculation in the
notification service method containing fromIndex and toIndex to perform page ×
size using Long before coercing to the collection size, preventing Int overflow
and invalid subList indices. Inspect ReadNotificationPageCommand validation and
add or preserve appropriate upper-bound validation for page and size if absent,
while keeping nonnegative page and positive size requirements.
- Around line 18-20: Remove the org.springframework.stereotype.Service import
and `@Service` annotation from NotificationService so it remains a plain Kotlin
class; register it as a bean from bootstrap configuration or a factory. Also
remove the Spring Boot starter dependency from
systems/notification/notification-application/deps.bzl (lines 1-4) after
eliminating the application-layer Spring usage.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 95749a1b-42fd-4067-9da6-1baff28ffed6

📥 Commits

Reviewing files that changed from the base of the PR and between 7ff684b and 9ddabb0.

📒 Files selected for processing (15)
  • systems/notification/notification-application/deps.bzl
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/exception/NotificationNotFoundException.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/NotificationPort.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/FaqResults.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/NoticeResults.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/PageResult.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/RecruitmentGuidelineResult.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/FaqRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/RecruitmentGuidelineRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Faq.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Notice.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/RecruitmentGuideline.kt
📜 Review details
🧰 Additional context used
📓 Path-based instructions (7)
**/{BUILD.bazel,*.bzl}

📄 CodeRabbit inference engine (Custom checks)

In BUILD.bazel and .bzl files, require buildifier-compatible formatting and stable target naming

Files:

  • systems/notification/notification-application/deps.bzl
**/*.bzl

⚙️ CodeRabbit configuration file

**/*.bzl: Apply Bazel Starlark (.bzl) style guidance.

Readability and docs:

  • Keep file/module docstrings and docstrings for public functions/macros.
  • Use descriptive parameter names and document attribute intent.

API design:

  • Macros should take a name argument and derive generated target names from it.
  • Prefer keyword arguments when calling macros for clarity and stability.
  • Keep macro side effects predictable and visible.

Encapsulation:

  • Use private visibility for helper targets created by macros unless explicitly public.
  • Avoid exposing internal implementation targets unintentionally.

Tooling:

  • Enforce buildifier formatting and lint compliance.

Files:

  • systems/notification/notification-application/deps.bzl
**/*.{kt,go}

📄 CodeRabbit inference engine (Custom checks)

If production logic is changed in Kotlin or Go files, require corresponding test updates in the same subsystem unless the PR description explicitly justifies why tests are unnecessary

Files:

  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/FaqRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/PageResult.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Faq.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/RecruitmentGuideline.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/exception/NotificationNotFoundException.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/NotificationPort.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Notice.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/NoticeResults.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/RecruitmentGuidelineResult.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/RecruitmentGuidelineRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/FaqResults.kt
**/*-application/**/*.{java,kt,scala,groovy}

📄 CodeRabbit inference engine (Custom checks)

For files under *-application modules, flag direct dependency on infrastructure-specific framework classes unless justified

Files:

  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/FaqRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/PageResult.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/exception/NotificationNotFoundException.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/NotificationPort.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/NoticeResults.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/RecruitmentGuidelineResult.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/RecruitmentGuidelineRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/FaqResults.kt
**/*.{java,kt,scala,groovy,go,js,ts,tsx,jsx,py,rb,rs,cpp,c,h,hpp,cs}

📄 CodeRabbit inference engine (Custom checks)

Flag TODO/FIXME comments introduced by this PR that do not include an issue reference in the form #123 or a full tracker key like PROJ-123

Files:

  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/FaqRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/PageResult.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Faq.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/RecruitmentGuideline.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/exception/NotificationNotFoundException.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/NotificationPort.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Notice.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/NoticeResults.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/RecruitmentGuidelineResult.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/RecruitmentGuidelineRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/FaqResults.kt
**/*.kt

⚙️ CodeRabbit configuration file

**/*.kt: Apply Kotlin Official Coding Conventions.

Formatting and structure:

  • Use 4 spaces for indentation; no tabs.
  • Keep files focused and readable; avoid horizontal alignment for spacing.
  • Place related declarations together and keep overloads adjacent.
  • Keep implementation member order stable and logical for readability.

Naming:

  • Package names are lowercase and do not use underscores.
  • Class/object names use UpperCamelCase.
  • Functions/properties/local variables use lowerCamelCase.
  • Constants use UPPER_SNAKE_CASE only for true constants.

API and null-safety:

  • Avoid platform type leakage in public APIs.
  • Use explicit types in public APIs when inference obscures meaning.
  • Prefer immutable values (val) over mutable values (var) unless mutation is required.
  • Flag nullable flows that can be replaced with safer modeling.

Imports and idioms:

  • Avoid wildcard imports unless justified by language/tooling conventions.
  • Prefer expression bodies for short, clear functions.
  • Prefer standard library idioms over custom utility wrappers when equivalent.

Architecture and tests:

  • Respect module boundaries (domain/application/adapter/bootstrap layering).
  • Highlight behavior-changing code that lacks corresponding unit/integration tests.
  • Ask for deterministic tests and meaningful assertions, not only happy-path checks.

Files:

  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/FaqRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/PageResult.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Faq.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/RecruitmentGuideline.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/exception/NotificationNotFoundException.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/NotificationPort.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Notice.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/NoticeResults.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/RecruitmentGuidelineResult.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/RecruitmentGuidelineRepository.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/FaqResults.kt
**/*-domain/**/*.{java,kt,scala,groovy}

📄 CodeRabbit inference engine (Custom checks)

For files under *-domain modules, fail if imports reference adapter or bootstrap packages

Files:

  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Faq.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/RecruitmentGuideline.kt
  • systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Notice.kt
🔇 Additional comments (10)
systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Faq.kt (1)

1-13: LGTM!

systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/Notice.kt (1)

1-13: LGTM!

systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/RecruitmentGuidelineRepository.kt (1)

1-7: LGTM!

systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/exception/NotificationNotFoundException.kt (1)

1-5: LGTM!

systems/notification/notification-domain/src/main/kotlin/hs/kr/entrydsm/notification/domain/model/RecruitmentGuideline.kt (1)

1-19: LGTM!

systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/PageResult.kt (1)

1-10: LGTM!

systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/NoticeResults.kt (1)

1-20: LGTM!

systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/FaqResults.kt (1)

1-20: LGTM!

systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/result/RecruitmentGuidelineResult.kt (1)

1-19: LGTM!

systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/NotificationPort.kt (1)

1-17: LGTM!

Comment on lines +3 to +6
data class ReadNotificationPageCommand(
val page: Int = 0,
val size: Int = 10,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

페이지 오프셋 계산의 Int 오버플로를 방지하세요.

ReadNotificationPageCommandpage * sizeInt 범위를 넘지 않는다는 보장을 제공하지 않습니다. 제공된 NotificationService.toPagepage >= 0size > 0만 확인한 뒤 command.page * command.sizeInt로 계산합니다. page = Int.MAX_VALUE, size = 2는 검증을 통과하지만 곱셈 결과가 -2가 됩니다. coerceAtMost(size)는 하한을 보정하지 않으므로 음수 인덱스가 subList로 전달되고 IndexOutOfBoundsException이 발생합니다.

NotificationService.toPage에서 오프셋 계산을 Long으로 수행한 뒤 목록 크기 범위로 제한하세요. 또는 command 생성 시 안전한 page * size 범위를 검증하세요. 해당 경계 입력에 대한 회귀 테스트도 추가하세요.

수정 예시
-        val fromIndex = (command.page * command.size).coerceAtMost(size)
-        val toIndex = (fromIndex + command.size).coerceAtMost(size)
+        val totalSize = size.toLong()
+        val fromIndex = (command.page.toLong() * command.size)
+            .coerceIn(0L, totalSize)
+            .toInt()
+        val toIndex = (fromIndex.toLong() + command.size)
+            .coerceIn(fromIndex.toLong(), totalSize)
+            .toInt()
경계값 검증 스크립트
#!/bin/bash
set -euo pipefail

command_file="$(fd -t f 'ReadNotificationPageCommand.kt' . | head -n 1)"
service_file="$(fd -t f 'NotificationService.kt' . | head -n 1)"

rg -n -C 4 \
  'ReadNotificationPageCommand|fromIndex|toIndex|subList|command\.page|command\.size' \
  "$command_file" "$service_file"

python - <<'PY'
import ctypes

page = 2**31 - 1
size = 2
product = ctypes.c_int32(page * size).value
assert product == -2
print(f"32-bit product: {product}")
PY
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt`
around lines 3 - 6, NotificationService.toPage calculates page * size as an
overflowing Int, allowing negative indices to reach subList. Update toPage to
perform offset arithmetic in Long, clamp the resulting offset to the available
list-size range, and preserve valid pagination behavior; add a regression test
covering page = Int.MAX_VALUE with size = 2.

Comment on lines +5 to +7
interface NoticeRepository {
fun findAll(): List<Notice>
fun findById(id: Long): Notice?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

페이지 조회를 repository 계약으로 내려야 합니다.

현재 포트는 모든 공지와 FAQ를 반환합니다. 서비스는 전체 목록을 정렬한 뒤 일부만 반환합니다. 실제 persistence adapter는 LIMIT, OFFSET, 정렬, 전체 건수를 데이터 저장소에서 처리할 수 없습니다. 데이터가 증가하면 요청마다 메모리와 CPU 사용량이 전체 데이터 크기에 비례합니다.

  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt#L5-L7: 페이지 인자와 전체 건수를 포함하는 페이지 조회 계약으로 findAll()을 대체하십시오. 공지 정렬은 createdAt DESC, id DESC처럼 결정적으로 정의하십시오.
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/FaqRepository.kt#L5-L7: 페이지 인자와 전체 건수를 포함하는 페이지 조회 계약으로 findAll()을 대체하십시오.
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt#L26-L38: repository가 반환한 페이지를 결과 DTO로 변환하십시오. 전체 목록 정렬과 subList() 페이지 처리를 제거하십시오.
📍 Affects 3 files
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt#L5-L7 (this comment)
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/FaqRepository.kt#L5-L7
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt#L26-L38
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt`
around lines 5 - 7, Replace the all-items repository contracts with paginated
queries that accept page parameters and return both the page contents and total
count; in NoticeRepository, define deterministic createdAt DESC, id DESC
ordering. Apply this to
systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/out/NoticeRepository.kt
lines 5-7 and FaqRepository.kt lines 5-7. Update NotificationService in
systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt
lines 26-38 to map the repository page directly into the result DTO, removing
full-list sorting and subList pagination.

Comment on lines +18 to +20
import org.springframework.stereotype.Service

@Service

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

application 계층에서 Spring 의존성을 제거해야 합니다.

NotificationService는 Spring @Service에 직접 의존합니다. 이 변경 때문에 application 모듈도 Spring Boot starter에 의존합니다. 서비스는 일반 Kotlin 클래스로 유지하고, bootstrap 모듈의 configuration 또는 factory에서 bean으로 등록해야 합니다.

  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt#L18-L20: org.springframework.stereotype.Service import와 @Service를 제거하십시오.
  • systems/notification/notification-application/deps.bzl#L1-L4: application 서비스에서 Spring 사용을 제거한 뒤 Spring Boot starter 의존성을 제거하십시오.

코딩 가이드라인에 따라 “For files under *-application modules, flag direct dependency on infrastructure-specific framework classes unless justified” 규칙을 적용했습니다.

#!/bin/bash
set -euo pipefail

fd -e kt . -x rg -n -C 3 'import org\.springframework|`@Service`|`@Configuration`|`@Bean`' {}
📍 Affects 2 files
  • systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt#L18-L20 (this comment)
  • systems/notification/notification-application/deps.bzl#L1-L4
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt`
around lines 18 - 20, Remove the org.springframework.stereotype.Service import
and `@Service` annotation from NotificationService so it remains a plain Kotlin
class; register it as a bean from bootstrap configuration or a factory. Also
remove the Spring Boot starter dependency from
systems/notification/notification-application/deps.bzl (lines 1-4) after
eliminating the application-layer Spring usage.

Comment on lines +103 to +107
require(command.page >= 0) { "page must be greater than or equal to 0" }
require(command.size > 0) { "size must be greater than 0" }

val fromIndex = (command.page * command.size).coerceAtMost(size)
val toIndex = (fromIndex + command.size).coerceAtMost(size)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

페이지 인덱스 계산을 Long으로 변경해야 합니다.

Line 106은 command.page * command.sizeInt로 계산합니다. 두 값이 모두 검증을 통과해도 곱셈은 overflow할 수 있습니다. 이 경우 음수 인덱스가 subList()에 전달되어 요청이 실패합니다.

수정 예시
-        val fromIndex = (command.page * command.size).coerceAtMost(size)
-        val toIndex = (fromIndex + command.size).coerceAtMost(size)
+        val fromIndex = (command.page.toLong() * command.size)
+            .coerceAtMost(size.toLong())
+            .toInt()
+        val toIndex = (fromIndex.toLong() + command.size)
+            .coerceAtMost(size.toLong())
+            .toInt()

ReadNotificationPageCommand에 상한 검증이 있는지도 함께 확인해야 합니다.

#!/bin/bash
set -euo pipefail

ast-grep outline systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt --items all
rg -n -C 3 'page:|size:|require\(' systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/port/in/command/ReadNotificationPageCommand.kt
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@systems/notification/notification-application/src/main/kotlin/hs/kr/entrydsm/notification/application/service/NotificationService.kt`
around lines 103 - 107, Update the pagination index calculation in the
notification service method containing fromIndex and toIndex to perform page ×
size using Long before coercing to the collection size, preventing Int overflow
and invalid subList indices. Inspect ReadNotificationPageCommand validation and
add or preserve appropriate upper-bound validation for page and size if absent,
while keeping nonnegative page and positive size requirements.

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.

notification 도메인 개발

2 participants