Skip to content

feat: 신규 동아리 등록 요청 API 추가#636

Open
dh2906 wants to merge 14 commits into
developfrom
feature/club-registration-request
Open

feat: 신규 동아리 등록 요청 API 추가#636
dh2906 wants to merge 14 commits into
developfrom
feature/club-registration-request

Conversation

@dh2906
Copy link
Copy Markdown
Contributor

@dh2906 dh2906 commented May 23, 2026

🔍 개요

  • 비로그인 유저가 신규 동아리 등록 요청을 제출할 수 있는 API를 추가합니다.
  • 제출된 요청은 DB에 저장하고, 기존 가입/탈퇴 알림과 같은 Slack 채널로 요청 내용을 전달합니다.

🚀 주요 변경 내용

  • 동아리 등록 요청 및 요청 미디어 저장 테이블을 추가했습니다.
  • POST /clubs/registration-requests 공개 API와 입력 검증을 추가했습니다.
  • 요청 저장 후 Slack 알림이 전송되도록 이벤트 리스너와 메시지 템플릿을 연결했습니다.
  • club 이모지 컬럼을 nullable로 추가하고 생성 요청에서 선택 입력할 수 있게 했습니다.
  • 웹사이트 전용 WebClub, WebUniversity 모델 패키지를 domain.website.model로 이동했습니다.

💬 참고 사항

  • club_registration_request.introduce는 2000자 제한 입력을 저장하기 위해 TEXT로 정의했습니다.
  • 사진 및 영상은 URL 문자열 기준 최대 5개까지 저장합니다.
  • 주요 검증으로 등록 요청 API/서비스/Slack 리스너 테스트, club 이모지 관련 테스트, website API 테스트, compile/checkstyle을 확인했습니다.

✅ Checklist (완료 조건)

  • 코드 스타일 가이드 준수
  • 테스트 코드 포함됨
  • Reviewers / Assignees / Labels 지정 완료
  • 보안 및 민감 정보 검증 (API 키, 환경 변수, 개인정보 등)

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

Review Change Stack

Warning

Review limit reached

@dh2906, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 14 minutes and 35 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 52dd62df-0823-42a6-bdc5-076ae0b99108

📥 Commits

Reviewing files that changed from the base of the PR and between 9778edb and 115f00c.

📒 Files selected for processing (12)
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestController.java
  • src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java
  • src/main/java/gg/agit/konect/domain/club/event/ClubRegistrationRequestedEvent.java
  • src/main/java/gg/agit/konect/domain/club/model/ClubRegistrationRequest.java
  • src/main/java/gg/agit/konect/domain/club/model/ClubRegistrationRequestImage.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubRegistrationRequestService.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java
  • src/main/java/gg/agit/konect/infrastructure/slack/listener/ClubRegistrationRequestSlackListener.java
  • src/main/resources/db/migration/V77__create_club_registration_request.sql
  • src/test/java/gg/agit/konect/integration/domain/club/ClubRegistrationRequestApiTest.java
  • src/test/java/gg/agit/konect/unit/domain/club/service/ClubRegistrationRequestServiceTest.java
  • src/test/java/gg/agit/konect/unit/infrastructure/slack/listener/ClubRegistrationRequestSlackListenerTest.java
📝 Walkthrough

Walkthrough

이 PR은 비로그인 사용자가 동아리 등록 요청을 제출할 수 있는 새로운 API 엔드포인트를 추가하고, 웹 도메인 모델을 패키지 구조 개선을 위해 마이그레이션합니다. 동아리 등록 요청은 데이터베이스에 PENDING 상태로 저장되며 Slack 알림으로 관리자에게 전달됩니다.

Changes

Club Registration Request Feature

Layer / File(s) Summary
API Contract and Data Transfer Object
src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestApi.java, src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java
ClubRegistrationRequestApi 인터페이스와 ClubRegistrationRequestDto 레코드를 정의하여 동아리 등록 요청 API 계약을 확립하고, 각 필드에 유효성 검증 및 Swagger 문서화 어노테이션을 포함합니다.
Club Registration Entity Model
src/main/java/gg/agit/konect/domain/club/model/ClubRegistrationRequest.java
ClubRegistrationRequest JPA 엔티티를 정의하며 RegistrationStatus enum과 함께 JSON 컬럼 매핑을 포함하고, 새 인스턴스의 기본 상태를 PENDING으로 설정합니다.
Repository and Database Persistence
src/main/java/gg/agit/konect/domain/club/repository/ClubRegistrationRequestRepository.java, src/main/resources/db/migration/V77__create_club_registration_request.sql
Spring Data JPA 리포지토리 인터페이스와 데이터베이스 마이그레이션 스크립트를 통해 동아리 등록 요청을 영속화합니다.
Service Business Logic
src/main/java/gg/agit/konect/domain/club/service/ClubRegistrationRequestService.java
DTO를 엔티티로 변환하여 저장하고 저장된 ID와 요청 정보를 사용하여 Slack 알림을 전송하는 register() 메서드를 구현합니다.
REST Controller and Endpoint
src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestController.java
/clubs/registration-requests POST 엔드포인트를 구현하여 검증된 요청 DTO를 서비스에 전달하고 성공 시 200 OK를 반환합니다.
Slack Notification Integration
src/main/java/gg/agit/konect/infrastructure/slack/enums/SlackMessageTemplate.java, src/main/java/gg/agit/konect/infrastructure/slack/service/SlackNotificationService.java
CLUB_REGISTRATION_REQUEST 메시지 템플릿을 추가하고 notifyClubRegistrationRequest() 메서드로 Slack 이벤트 웹훅을 통해 관리자에게 알림을 전송합니다.
Security Configuration
src/main/java/gg/agit/konect/global/config/SecurityPaths.java
PUBLIC_PATHS/clubs/registration-requests를 추가하여 비인증 사용자의 엔드포인트 접근을 허용합니다.
Integration Tests
src/test/java/gg/agit/konect/integration/domain/club/ClubRegistrationRequestApiTest.java
성공 케이스와 필수값 누락, 이미지 개수 초과, 소개 길이 초과 등 검증 실패 케이스를 검증하는 4개 테스트 메서드를 포함합니다.

Web Domain Package Refactoring

Layer / File(s) Summary
Model Class Package Migration
src/main/java/gg/agit/konect/domain/website/model/WebClub.java, src/main/java/gg/agit/konect/domain/website/model/WebUniversity.java
WebClubWebUniversity 모델의 패키지를 domain.web.model에서 domain.website.model로 변경합니다.
DTO and Service Import Updates
src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubDetailResponse.java, src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java, src/main/java/gg/agit/konect/domain/website/service/WebsiteService.java
웹 관련 DTO와 서비스의 import 경로를 새 패키지로 업데이트합니다.
Repository and QueryDSL Configuration Update
src/main/java/gg/agit/konect/domain/website/repository/WebsiteQueryRepository.java
QueryDSL Q타입 static import와 모델 import를 새 패키지 경로로 변경합니다.
Test Fixture Updates
src/test/java/gg/agit/konect/integration/domain/website/WebsiteApiTest.java, src/test/java/gg/agit/konect/support/fixture/WebClubFixture.java, src/test/java/gg/agit/konect/support/fixture/WebUniversityFixture.java
테스트 클래스와 픽스처의 import 경로를 새 패키지로 업데이트합니다.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Controller as ClubRegistrationRequestController
  participant Service as ClubRegistrationRequestService
  participant Repo as Repository
  participant Slack as SlackNotificationService
  participant DB as Database

  Client->>Controller: POST /clubs/registration-requests<br/>ClubRegistrationRequestDto
  Controller->>Controller: `@Valid` validation
  Controller->>Service: register(dto)
  Service->>Service: build ClubRegistrationRequest<br/>with PENDING status
  Service->>Repo: save(entity)
  Repo->>DB: INSERT club_registration_request
  DB-->>Repo: entity with id
  Repo-->>Service: saved entity
  Service->>Slack: notifyClubRegistrationRequest<br/>(id, details)
  Slack->>Slack: format message template
  Slack-->>Service: message sent
  Service-->>Controller: void
  Controller-->>Client: 200 OK
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

  • BCSDLab/KONECT_BACK_END#623: 유사하게 SecurityPaths.PUBLIC_PATHS를 수정하여 새로운 공개 엔드포인트 경로(/website/**)를 허용하는 변경을 포함합니다.

Suggested labels

기능, 테스트

Poem

🐰 동아리 가입 요청이 날아오네,
데이터베이스에 쏙 저장되고,
Slack 메시지로 관리자 호출~
패키지는 깔끔하게 정리되어,
모두가 행복한 리팩토링이야! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 변경 세트의 주요 내용을 명확하게 설명하고 있습니다. 신규 동아리 등록 요청 API 추가라는 핵심 변경 사항을 간결하고 구체적으로 전달합니다.
Description check ✅ Passed 설명이 변경 세트와 충분히 관련성이 있습니다. 동아리 등록 요청 API 추가, DB 저장, Slack 알림, 패키지 이동 등 변경 내용의 주요 부분들을 다루고 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/club-registration-request

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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 23, 2026

🧪 JaCoCo Coverage Report (Changed Files)

Summary

  • Overall Coverage: 79.9% ✅
  • Covered Lines: 155 / 194
  • Changed Files: 17

Coverage by File

Class Coverage Lines Status
SlackMessageTemplate
gg.agit.konect.infrastructure.slack.enums
0.0% 0/11
SlackNotificationService
gg.agit.konect.infrastructure.slack.service
0.0% 0/24
WebsiteQueryRepository
gg.agit.konect.domain.website.repository
95.6% 87/91
WebsiteService
gg.agit.konect.domain.website.service
100.0% 27/27
ClubRegistrationRequestedEvent
gg.agit.konect.domain.club.event
100.0% 10/10
ClubRegistrationRequestController
gg.agit.konect.domain.club.controller
100.0% 2/2
ClubRegistrationRequestSlackListener
gg.agit.konect.infrastructure.slack.listener
100.0% 14/14
ClubRegistrationRequestService
gg.agit.konect.domain.club.service
100.0% 15/15

📊 View Workflow Run

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: 4

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/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java (1)

17-18: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

[LEVEL: medium] university 필드 required 문서화가 실제 응답과 불일치합니다.
문제: Line 17에서 requiredMode = REQUIRED로 선언했지만 Line 143의 recent()universitynull을 반환합니다.
영향: /konect/clubs/recent를 OpenAPI 스키마 기준으로 사용하는 클라이언트에서 non-null 가정이 깨져 검증/역직렬화 오류가 발생할 수 있으니 NOT_REQUIRED로 문서를 수정하거나 recent 전용 DTO로 분리해 계약을 일치시켜 주세요; Based on learnings: Schema(requiredMode = REQUIRED) 필드는 코드/DB에서 non-null 보장이 필요합니다.

Also applies to: 141-144

🤖 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 `@src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java`
around lines 17 - 18, The Schema for the university field in
WebsiteClubsResponse is marked required (requiredMode = REQUIRED) but recent()
returns null for university; change the contract to match runtime behavior by
either setting the university field's `@Schema`(requiredMode = NOT_REQUIRED) in
WebsiteClubsResponse or create a dedicated DTO (e.g.,
WebsiteClubsRecentResponse) used by recent() where university is nullable;
update usages of WebsiteClubsResponse/recent() to use the chosen approach so
OpenAPI matches actual responses.
🤖 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
`@src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestController.java`:
- Line 31: The controller currently returns 200 for create requests; update the
POST handler in ClubRegistrationRequestController to return 201 by replacing
ResponseEntity.ok().build() with
ResponseEntity.status(HttpStatus.CREATED).build(), and import or reference
HttpStatus as needed so the create endpoint follows REST semantics.

In
`@src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java`:
- Around line 49-52: The DTO field imageUrls in ClubRegistrationRequestDto is
annotated `@NotNull` but the entity column image_urls and service null-handling
allow nulls, causing a contract mismatch; either remove the `@NotNull` (and update
the `@Schema` requiredMode from REQUIRED to optional/not required) so the DTO
accepts absent images while keeping `@Size`(max=5), or make the requirement
consistent by marking the DB column non-null, removing null-handling in the
service, and keeping `@NotNull` on imageUrls—pick one approach and apply it
consistently across ClubRegistrationRequestDto (imageUrls), the entity
(image_urls nullability), and the service null checks.

In
`@src/main/java/gg/agit/konect/domain/club/service/ClubRegistrationRequestService.java`:
- Around line 35-44: The Slack notification is being called inside the DB
transaction (slackNotificationService.notifyClubRegistrationRequest with
saved.getId() and request.* fields), so Slack failures can roll back the save;
move notification out of the transactional boundary by publishing an event after
saving (e.g., create and publish a ClubRegistrationRequestedEvent containing
saved.getId() and the request data) and handle it in a listener annotated with
`@TransactionalEventListener`(phase = AFTER_COMMIT) or via an async executor;
ensure the listener calls slackNotificationService.notifyClubRegistrationRequest
and isolates failures (catch/log and implement retry/backoff) so notification
errors don’t propagate back to the save flow.

In `@src/main/java/gg/agit/konect/global/config/SecurityPaths.java`:
- Line 16: 현재 PUBLIC_PATHS에 있는 "/clubs/registration-requests"를 단순 경로 허용으로 두면 모든
HTTP 메서드가 인증 없이 허용될 수 있으니 SecurityConfig에서 메서드 수준으로 제한하세요: PUBLIC_PATHS에서 해당
문자열을 제거하고 SecurityConfig의 해당 보안 체인에 requestMatchers(HttpMethod.POST,
"/clubs/registration-requests").permitAll()을 추가해 POST만 익명 접근을 허용하도록 변경하며, 다른
메서드는 적절한 권한 검사(예: authenticated() 또는 hasRole(...))로 처리되도록 구성하세요.

---

Outside diff comments:
In `@src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java`:
- Around line 17-18: The Schema for the university field in WebsiteClubsResponse
is marked required (requiredMode = REQUIRED) but recent() returns null for
university; change the contract to match runtime behavior by either setting the
university field's `@Schema`(requiredMode = NOT_REQUIRED) in WebsiteClubsResponse
or create a dedicated DTO (e.g., WebsiteClubsRecentResponse) used by recent()
where university is nullable; update usages of WebsiteClubsResponse/recent() to
use the chosen approach so OpenAPI matches actual responses.
🪄 Autofix (Beta)

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

Run ID: fa4db8ba-8e2e-4970-b9fb-a4e32021cf7f

📥 Commits

Reviewing files that changed from the base of the PR and between f227c02 and 9778edb.

📒 Files selected for processing (20)
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestApi.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestController.java
  • src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java
  • src/main/java/gg/agit/konect/domain/club/model/ClubRegistrationRequest.java
  • src/main/java/gg/agit/konect/domain/club/repository/ClubRegistrationRequestRepository.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubRegistrationRequestService.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubDetailResponse.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java
  • src/main/java/gg/agit/konect/domain/website/model/WebClub.java
  • src/main/java/gg/agit/konect/domain/website/model/WebUniversity.java
  • src/main/java/gg/agit/konect/domain/website/repository/WebsiteQueryRepository.java
  • src/main/java/gg/agit/konect/domain/website/service/WebsiteService.java
  • src/main/java/gg/agit/konect/global/config/SecurityPaths.java
  • src/main/java/gg/agit/konect/infrastructure/slack/enums/SlackMessageTemplate.java
  • src/main/java/gg/agit/konect/infrastructure/slack/service/SlackNotificationService.java
  • src/main/resources/db/migration/V77__create_club_registration_request.sql
  • src/test/java/gg/agit/konect/integration/domain/club/ClubRegistrationRequestApiTest.java
  • src/test/java/gg/agit/konect/integration/domain/website/WebsiteApiTest.java
  • src/test/java/gg/agit/konect/support/fixture/WebClubFixture.java
  • src/test/java/gg/agit/konect/support/fixture/WebUniversityFixture.java
📜 Review details
⏰ 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). (2)
  • GitHub Check: coverage
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.java

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.java: Java 코드에서 import로 해결할 수 있는 경우 FQCN(Full Qualified Class Name)을 사용하지 않도록 지적한다
JPA/QueryDSL 조회 변경 시 N+1, 잘못된 fetch join, count 쿼리 왜곡, pagination 깨짐, distinct 누락을 확인한다
권한 로직은 관리자 우회, 요청자와 대상자 관계, 클럽/채팅방/공지/일정의 소속 검증이 빠지지 않았는지 확인한다
soft delete, 탈퇴 사용자, 차단/제외 조건, 중복 제거가 필요한 조회에서는 응답에 노출되면 안 되는 데이터가 포함되는지 확인한다
DTO 응답 변경은 기존 클라이언트가 기대하는 필드명, nullability, enum/string 값, 정렬 순서를 깨지 않는지 확인한다
조건이 2개 이상 결합된 비즈니스 규칙, 권한 조건, soft delete 제외, 중복 제거, fallback 우선순위, 대표값 선택, DTO 변환, count 쿼리 분리, fetch join 선택 이유처럼 코드만으로 의도가 숨겨지는 지점에는 주석을 권장한다
단순 생성자 호출, 필드 매핑, 컬렉션 반환, 이름만으로 명확한 분기에는 주석을 요구하지 않는다

Files:

  • src/main/java/gg/agit/konect/domain/website/model/WebClub.java
  • src/main/java/gg/agit/konect/domain/club/repository/ClubRegistrationRequestRepository.java
  • src/test/java/gg/agit/konect/integration/domain/website/WebsiteApiTest.java
  • src/test/java/gg/agit/konect/support/fixture/WebUniversityFixture.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestApi.java
  • src/main/java/gg/agit/konect/domain/website/service/WebsiteService.java
  • src/main/java/gg/agit/konect/infrastructure/slack/service/SlackNotificationService.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubDetailResponse.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubRegistrationRequestService.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestController.java
  • src/main/java/gg/agit/konect/domain/website/repository/WebsiteQueryRepository.java
  • src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java
  • src/test/java/gg/agit/konect/support/fixture/WebClubFixture.java
  • src/test/java/gg/agit/konect/integration/domain/club/ClubRegistrationRequestApiTest.java
  • src/main/java/gg/agit/konect/domain/club/model/ClubRegistrationRequest.java
  • src/main/java/gg/agit/konect/domain/website/model/WebUniversity.java
  • src/main/java/gg/agit/konect/global/config/SecurityPaths.java
  • src/main/java/gg/agit/konect/infrastructure/slack/enums/SlackMessageTemplate.java
**/*.{sql,java}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

데이터베이스 변경에서는 마이그레이션 순서, 기존 데이터 호환성, nullable/default 처리, 롤백 난이도, 인덱스 필요성을 확인한다

Files:

  • src/main/java/gg/agit/konect/domain/website/model/WebClub.java
  • src/main/java/gg/agit/konect/domain/club/repository/ClubRegistrationRequestRepository.java
  • src/test/java/gg/agit/konect/integration/domain/website/WebsiteApiTest.java
  • src/main/resources/db/migration/V77__create_club_registration_request.sql
  • src/test/java/gg/agit/konect/support/fixture/WebUniversityFixture.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestApi.java
  • src/main/java/gg/agit/konect/domain/website/service/WebsiteService.java
  • src/main/java/gg/agit/konect/infrastructure/slack/service/SlackNotificationService.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubDetailResponse.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubRegistrationRequestService.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestController.java
  • src/main/java/gg/agit/konect/domain/website/repository/WebsiteQueryRepository.java
  • src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java
  • src/test/java/gg/agit/konect/support/fixture/WebClubFixture.java
  • src/test/java/gg/agit/konect/integration/domain/club/ClubRegistrationRequestApiTest.java
  • src/main/java/gg/agit/konect/domain/club/model/ClubRegistrationRequest.java
  • src/main/java/gg/agit/konect/domain/website/model/WebUniversity.java
  • src/main/java/gg/agit/konect/global/config/SecurityPaths.java
  • src/main/java/gg/agit/konect/infrastructure/slack/enums/SlackMessageTemplate.java
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.

  • 코멘트는 반드시 한국어로 작성한다.
  • 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
  • 각 코멘트 첫 줄에 심각도를 [LEVEL: high|medium|low] 형식으로 반드시 표기한다.
  • 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
  • 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
  • 가능하면 재현 조건 및 실패 시나리오도 포함한다.
  • 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
  • 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
  • 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
  • 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
  • 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.

Files:

  • src/main/java/gg/agit/konect/domain/website/model/WebClub.java
  • src/main/java/gg/agit/konect/domain/club/repository/ClubRegistrationRequestRepository.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestApi.java
  • src/main/java/gg/agit/konect/domain/website/service/WebsiteService.java
  • src/main/java/gg/agit/konect/infrastructure/slack/service/SlackNotificationService.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubDetailResponse.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubRegistrationRequestService.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestController.java
  • src/main/java/gg/agit/konect/domain/website/repository/WebsiteQueryRepository.java
  • src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java
  • src/main/java/gg/agit/konect/domain/club/model/ClubRegistrationRequest.java
  • src/main/java/gg/agit/konect/domain/website/model/WebUniversity.java
  • src/main/java/gg/agit/konect/global/config/SecurityPaths.java
  • src/main/java/gg/agit/konect/infrastructure/slack/enums/SlackMessageTemplate.java
**/*

⚙️ CodeRabbit configuration file

**/*: 공통 리뷰 톤 가이드:

  • 모든 코멘트는 첫 줄에 [LEVEL: ...] 태그를 포함한다.
  • 과장된 표현 없이 사실 기반으로 작성한다.
  • 한 코멘트에는 하나의 이슈만 다룬다.
  • 코드 예시가 필요하면 최소 수정 예시를 제시한다.
  • 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.

Files:

  • src/main/java/gg/agit/konect/domain/website/model/WebClub.java
  • src/main/java/gg/agit/konect/domain/club/repository/ClubRegistrationRequestRepository.java
  • src/test/java/gg/agit/konect/integration/domain/website/WebsiteApiTest.java
  • src/main/resources/db/migration/V77__create_club_registration_request.sql
  • src/test/java/gg/agit/konect/support/fixture/WebUniversityFixture.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestApi.java
  • src/main/java/gg/agit/konect/domain/website/service/WebsiteService.java
  • src/main/java/gg/agit/konect/infrastructure/slack/service/SlackNotificationService.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubDetailResponse.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubRegistrationRequestService.java
  • src/main/java/gg/agit/konect/domain/club/controller/ClubRegistrationRequestController.java
  • src/main/java/gg/agit/konect/domain/website/repository/WebsiteQueryRepository.java
  • src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java
  • src/test/java/gg/agit/konect/support/fixture/WebClubFixture.java
  • src/test/java/gg/agit/konect/integration/domain/club/ClubRegistrationRequestApiTest.java
  • src/main/java/gg/agit/konect/domain/club/model/ClubRegistrationRequest.java
  • src/main/java/gg/agit/konect/domain/website/model/WebUniversity.java
  • src/main/java/gg/agit/konect/global/config/SecurityPaths.java
  • src/main/java/gg/agit/konect/infrastructure/slack/enums/SlackMessageTemplate.java
**/db/migration/*.sql

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Flyway 마이그레이션 파일은 파일명 버전 순서, 기존 운영 데이터 backfill, NOT NULL 추가 순서, 기본값 처리를 확인한다

Files:

  • src/main/resources/db/migration/V77__create_club_registration_request.sql
src/main/resources/db/migration/**/*.sql

⚙️ CodeRabbit configuration file

src/main/resources/db/migration/**/*.sql: Flyway 마이그레이션 리뷰 규칙:

  • 버전 파일명 규칙(V{number}__{description}.sql) 위반 여부를 우선 확인한다.
  • 이미 배포된 마이그레이션 수정/재번호 부여 위험이 있으면 반드시 차단 코멘트를 남긴다.
  • 파괴적 변경(drop, rename 등)은 롤백 가능성과 운영 영향 관점에서 검토한다.

Files:

  • src/main/resources/db/migration/V77__create_club_registration_request.sql
🧠 Learnings (1)
📚 Learning: 2026-05-18T05:03:20.120Z
Learnt from: dh2906
Repo: BCSDLab/KONECT_BACK_END PR: 625
File: src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java:0-0
Timestamp: 2026-05-18T05:03:20.120Z
Learning: 응답 DTO(또는 그 하위 클래스)의 필드에 `Schema(requiredMode = REQUIRED)`(또는 OpenAPI에서 필드를 required로 문서화)한다고 가정한 경우, 실제 런타임 계약이 비어있지 않음을 코드/DB로 보장해야 합니다. 구체적으로는 해당 값이 매핑되는 DB 컬럼이 `NOT NULL`이고(필요 시 Flyway 마이그레이션에서 기존 행 백필 후 `NOT NULL` 전환), 엔티티/필드에 `NotNull` 및 `Column(nullable = false)`(또는 동등한 검증/매핑 제약)가 선언되어 있으며, DTO/응답에서도 null이 허용되지 않도록 보장(검증/타입)하세요. 이 제약이 없는 상태에서 required로 문서화하면 리뷰 시 불일치로 플래그합니다.

Applied to files:

  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubsResponse.java
  • src/main/java/gg/agit/konect/domain/website/dto/WebsiteClubDetailResponse.java
  • src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java
🔇 Additional comments (1)
src/test/java/gg/agit/konect/support/fixture/WebUniversityFixture.java (1)

7-7: LGTM!

Comment thread src/main/java/gg/agit/konect/domain/club/dto/ClubRegistrationRequestDto.java Outdated
Comment thread src/main/java/gg/agit/konect/global/config/SecurityPaths.java Outdated
- 생성 요청은 201 응답으로 맞춰 클라이언트가 리소스 생성 성공을 일관되게 판단할 수 있게 정리

- 사진 및 영상은 최대 개수 제한만 유지해 무첨부 요청을 허용하는 API 계약과 저장 로직을 일치

- Slack 알림은 커밋 이후 이벤트 리스너에서 처리해 외부 연동 실패가 등록 저장을 롤백하지 않도록 분리

- 공개 접근은 경로 전체 예외 대신 @publicapi 메서드 단위로 제한해 같은 경로의 향후 메서드가 자동 공개되지 않도록 정리

- 실제 null 반환 가능성이 있는 웹사이트 동아리 응답의 대학 정보 문서화를 선택값으로 맞춤
@dh2906
Copy link
Copy Markdown
Contributor Author

dh2906 commented May 23, 2026

WebsiteClubsResponse의 university 필드가 required로 문서화되어 있지만 recent()는 null을 반환합니다.

Addressed: 실제 런타임 계약에 맞춰 WebsiteClubsResponse.university의 OpenAPI requiredModeNOT_REQUIRED로 변경했습니다. recent() 응답에서는 대학 컨텍스트가 없기 때문에 기존 DTO를 유지하되 문서화만 null 허용으로 정렬했습니다.

- Builder 문자열 출력에서 요청 엔티티 연관관계를 제외해 불필요한 객체 그래프 노출을 피함

- 기능 동작은 유지하면서 정적 분석 경고만 좁게 해소
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