✨ Feat: 동호회 가입 신청서 작성 기능 추가 및 신청 조회 API 개선#59
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review infoConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
Walkthrough클럽 가입 신청에 사용자 메시지 저장을 추가하고, 단일 신청 조회 엔드포인트를 추가하며 대기 중 신청 목록 응답을 요약 DTO로 변경했습니다. 관련 엔티티, 서비스, 컨트롤러 및 DTO들이 이에 맞춰 수정되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller
participant Service
participant Repository
participant Entity
rect rgba(100, 200, 100, 0.5)
Note over Client,Entity: 메시지 포함 가입 신청
Client->>Controller: POST /clubs/{clubId}/join-requests\n(JoinClubApplicationRequest)
Controller->>Service: requestJoin(clubId, userId, message)
Service->>Repository: save(JoinClubRequest with message)
Repository->>Entity: persist entity
Service->>Service: JoinClubRequestResponse.from(entity)
Service-->>Controller: JoinClubRequestResponse
Controller-->>Client: BaseResponse<JoinClubRequestResponse>
end
rect rgba(150, 150, 200, 0.5)
Note over Client,Entity: 특정 신청 조회
Client->>Controller: GET /join-requests/{requestId}
Controller->>Service: getJoinRequest(requestId, userId)
Service->>Repository: findById(requestId)
Repository-->>Service: JoinClubRequest entity
Service->>Service: 권한 검증(리더 또는 신청자)
Service->>Service: JoinClubRequestResponse.from(entity)
Service-->>Controller: JoinClubRequestResponse
Controller-->>Client: BaseResponse<JoinClubRequestResponse>
end
rect rgba(200, 150, 100, 0.5)
Note over Client,Entity: 대기 중인 신청 목록 조회
Client->>Controller: GET /clubs/{clubId}/join-requests
Controller->>Service: getPendingRequests(clubId, leaderId)
Service->>Repository: findPendingByClubId(clubId)
Repository-->>Service: List<JoinClubRequest>
Service->>Service: map to JoinClubRequestSummaryResponse.from(...)
Service-->>Controller: List<JoinClubRequestSummaryResponse>
Controller-->>Client: BaseResponse<List<JoinClubRequestSummaryResponse>>
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/main/java/com/be/sportizebe/domain/notification/service/JoinClubRequestServiceImpl.java (1)
38-67: 서비스 계층에서도 message 방어 검증을 두는 것을 권장합니다.현재는 컨트롤러 검증 경로를 우회하는 호출에서
null/blank/길이 초과가 DB 제약 예외로 전파될 수 있습니다. 서비스에서 한 번 더 검증(및 trim 저장)하면 장애 형태를 더 예측 가능하게 만들 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/be/sportizebe/domain/notification/service/JoinClubRequestServiceImpl.java` around lines 38 - 67, In requestJoin within JoinClubRequestServiceImpl, add defensive validation for the incoming message before building JoinClubRequest: trim the message, check for null or blank and enforce a maximum length (introduce a MAX_MESSAGE_LENGTH constant in the class), and if invalid throw a CustomException (e.g., JoinClubRequestErrorCode.INVALID_MESSAGE or an appropriate existing error code); finally pass the trimmed message to JoinClubRequest.builder().message(...) so stored values are normalized and service-only callers cannot bypass controller validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/java/com/be/sportizebe/domain/notification/entity/JoinClubRequest.java`:
- Around line 40-41: The JoinClubRequest entity declares the field message as
`@Column`(nullable = false) but there is no DB migration framework or scripts; set
up a migration tool (Flyway or Liquibase), then add a migration that (1) adds
the message column to the join_club_request table (allow NULL initially or add
with DEFAULT ''), (2) backfill existing rows with a safe default (e.g. update
message = '' where message IS NULL), and (3) alter the column to NOT NULL (or
create it with NOT NULL only after backfill); ensure the migration file is
committed and the application configured to run migrations on deploy so
JoinClubRequest.message matches the DB schema.
---
Nitpick comments:
In
`@src/main/java/com/be/sportizebe/domain/notification/service/JoinClubRequestServiceImpl.java`:
- Around line 38-67: In requestJoin within JoinClubRequestServiceImpl, add
defensive validation for the incoming message before building JoinClubRequest:
trim the message, check for null or blank and enforce a maximum length
(introduce a MAX_MESSAGE_LENGTH constant in the class), and if invalid throw a
CustomException (e.g., JoinClubRequestErrorCode.INVALID_MESSAGE or an
appropriate existing error code); finally pass the trimmed message to
JoinClubRequest.builder().message(...) so stored values are normalized and
service-only callers cannot bypass controller validation.
ℹ️ Review info
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/main/java/com/be/sportizebe/domain/notification/controller/JoinClubRequestController.javasrc/main/java/com/be/sportizebe/domain/notification/dto/request/JoinClubApplicationRequest.javasrc/main/java/com/be/sportizebe/domain/notification/dto/response/JoinClubRequestResponse.javasrc/main/java/com/be/sportizebe/domain/notification/dto/response/JoinClubRequestSummaryResponse.javasrc/main/java/com/be/sportizebe/domain/notification/entity/JoinClubRequest.javasrc/main/java/com/be/sportizebe/domain/notification/service/JoinClubRequestService.javasrc/main/java/com/be/sportizebe/domain/notification/service/JoinClubRequestServiceImpl.java
| @Column(nullable = false, columnDefinition = "TEXT") | ||
| private String message; // 가입 신청서 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find migration-related directories and files
find . -type d \( -name migrations -o -name db -o -name liquibase -o -name flyway -o -name sql \) 2>/dev/null | head -20Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Look for migration file patterns in common locations
find . -name "*.sql" -o -name "*.xml" | grep -i -E "(migration|flyway|liquibase|db)" | head -30Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check for Flyway or Liquibase configuration in build files and properties
find . -name "*.gradle" -o -name "*.gradle.kts" -o -name "application*.yml" -o -name "application*.yaml" -o -name "application*.properties" | xargs grep -l "flyway\|liquibase" 2>/dev/nullRepository: Sportize/be
Length of output: 39
🏁 Script executed:
# Search for join_club_request related code and migrations
rg -i "join_club_request" --type-list | head -20Repository: Sportize/be
Length of output: 444
🏁 Script executed:
# Get repository structure overview
ls -laRepository: Sportize/be
Length of output: 1171
🏁 Script executed:
# Explore src directory structure
find src -type f -name "*.sql" -o -name "*.xml" | head -30Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check for Flyway or Liquibase configuration in gradle and properties files
cat build.gradleRepository: Sportize/be
Length of output: 1969
🏁 Script executed:
# Look for application properties/yml files
find src -name "application*.yml" -o -name "application*.properties" | head -10Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Search for join_club_request in the codebase
rg "join_club_request" -iRepository: Sportize/be
Length of output: 399
🏁 Script executed:
# Check the JoinClubRequest entity file to understand the current state
cat -n src/main/java/com/be/sportizebe/domain/notification/entity/JoinClubRequest.javaRepository: Sportize/be
Length of output: 1917
🏁 Script executed:
# Check if there's a migrations directory or database schema directory
find src -type d -name "*migration*" -o -type d -name "*db*" -o -type d -name "*sql*" -o -type d -name "*schema*"Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Look for all SQL files in the project
find . -name "*.sql" -type fRepository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check application.yml/properties in resources directory
find src -path "*/resources/*" -name "application*" -type fRepository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check for database configuration in resources
ls -la src/main/resources/ 2>/dev/null || echo "Resources directory not found or empty"Repository: Sportize/be
Length of output: 161
🏁 Script executed:
# Search for any references to Flyway, Liquibase, or migration in all files
rg -i "flyway|liquibase|migration" --type-listRepository: Sportize/be
Length of output: 444
🏁 Script executed:
# Try a simpler search for migration configuration
rg "flyway|liquibase|migration" -iRepository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check complete src directory structure
tree src -L 5 --dirsfirstRepository: Sportize/be
Length of output: 277
🏁 Script executed:
# Check if there's a resources directory with application properties
find src/main -type f -name "*" | grep -i -E "(application|config|properties|yml|yaml)" | head -20Repository: Sportize/be
Length of output: 690
🏁 Script executed:
# Look for any database initialization or schema files
find . -type f \( -name "*.sql" -o -name "schema.*" -o -name "data.*" \) 2>/dev/nullRepository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check git history for any migration-related commits or files
git log --name-only --oneline | grep -i -E "(migration|flyway|liquibase|\.sql)" | head -20Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Verify if there's any Spring Boot auto-ddl or hibernate configuration
rg "spring.jpa.hibernate|spring.jpa.database|ddl-auto" -iRepository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check if Hibernate is configured to auto-create tables
find src/main -name "*.java" | xargs rg "spring.jpa|hibernate|ddl-auto" 2>/dev/null | head -20Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Verify if application properties exist anywhere in the project
find . -name "application*" -o -name "application*.yml" -o -name "application*.properties" 2>/dev/nullRepository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check if there's any database configuration in the codebase
rg "@Configuration|@EnableAutoConfiguration" -A 10 | grep -i "database\|datasource\|jpa\|hibernate" | head -20Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Final comprehensive check - list all directories in src/main
find src/main -type d | sortRepository: Sportize/be
Length of output: 6104
🏁 Script executed:
# Check git history to see if message field is newly added
git log -p -- src/main/java/com/be/sportizebe/domain/notification/entity/JoinClubRequest.java | head -100Repository: Sportize/be
Length of output: 37
🏁 Script executed:
# Check the current status of the file in git
git show HEAD:src/main/java/com/be/sportizebe/domain/notification/entity/JoinClubRequest.javaRepository: Sportize/be
Length of output: 1518
🏁 Script executed:
# Check if there are any unstaged changes to this file
git diff src/main/java/com/be/sportizebe/domain/notification/entity/JoinClubRequest.javaRepository: Sportize/be
Length of output: 37
데이터베이스 마이그레이션 프레임워크 및 스크립트가 누락되었습니다.
코드상 message 필드는 nullable = false로 정의되어 있으나, 프로젝트에 Flyway나 Liquibase 같은 마이그레이션 도구가 설정되어 있지 않으며 마이그레이션 스크립트도 없습니다.
운영 데이터베이스에 기존 join_club_request 데이터가 있을 경우, 스키마 변경 시 다음 순서로 진행해야 합니다:
- 마이그레이션 프레임워크(Flyway/Liquibase) 설정
- 마이그레이션 스크립트 작성:
message컬럼 추가 → 기존 행 백필(DEFAULT ''등) →NOT NULL제약 적용 - 마이그레이션 파일을 통해 안전하게 배포
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/be/sportizebe/domain/notification/entity/JoinClubRequest.java`
around lines 40 - 41, The JoinClubRequest entity declares the field message as
`@Column`(nullable = false) but there is no DB migration framework or scripts; set
up a migration tool (Flyway or Liquibase), then add a migration that (1) adds
the message column to the join_club_request table (allow NULL initially or add
with DEFAULT ''), (2) backfill existing rows with a safe default (e.g. update
message = '' where message IS NULL), and (3) alter the column to NOT NULL (or
create it with NOT NULL only after backfill); ensure the migration file is
committed and the application configured to run migrations on deploy so
JoinClubRequest.message matches the DB schema.
#️⃣ Issue Number
📝 요약(Summary)
🛠️ PR 유형
어떤 변경 사항이 있나요?
📸스크린샷 (선택)
💬 공유사항 to 리뷰어
✅ PR Checklist
PR이 다음 요구 사항을 충족하는지 확인하세요.
Summary by CodeRabbit
New Features
Improvements