feat: 모임방/기록/투표/오늘의 한마디 신고 API 추가 - #376
Conversation
Comment, Feed에 이어 Room, Record, Vote, AttendanceCheck 도메인에도 신고 API를 추가하고 신고 횟수만 증가시키도록 구현. - Room, AttendanceCheck: report_count 컬럼이 없어 마이그레이션 추가 - Record, Vote: posts 테이블(단일 테이블 상속)에 Feed가 쓰던 report_count 컬럼이 이미 있어 엔티티 매핑만 추가 - posts.report_count의 기존 NULL 값(Record/Vote)을 0으로 백필하고 rooms/attendance_checks와 함께 NOT NULL 제약 추가 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Walkthrough방, 기록, 투표, 출석 체크에 신고 횟수 필드와 증가 로직을 추가했습니다. 각 신고 API는 갱신된 식별자와 신고 횟수를 반환합니다. 데이터베이스 마이그레이션과 통합 테스트도 추가했습니다. Changes신고 횟수 데이터 모델과 영속성
방 신고 처리 흐름
기록·투표·출석 체크 신고 처리
신고 API 오류 계약과 통합 검증
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant RoomPostCommandController
participant ReportService
participant JPAEntity
Client->>RoomPostCommandController: 신고 요청
RoomPostCommandController->>ReportService: 신고 대상 ID 전달
ReportService->>JPAEntity: 대상 조회 및 reportCount 증가
JPAEntity-->>ReportService: 갱신된 신고 횟수
ReportService-->>RoomPostCommandController: 신고 결과 반환
RoomPostCommandController-->>Client: 식별자와 reportCount 응답
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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 |
Test Results512 tests 512 ✅ 49s ⏱️ Results for commit e7b79eb. |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 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/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java`:
- Around line 92-102: 중첩 경로의 방 소속 검증이 누락되어 하위 리소스만으로 처리되는 문제를 수정하십시오.
RoomPostCommandController의 92-102행에서는 roomId와 recordId를 함께 recordReportUseCase에
전달하고, 168-178행과 213-225행에서도 각각 roomId와 voteId, roomId와 attendanceCheckId를 함께
전달하도록 관련 use case 계약과 서비스를 변경해 소속이 다르면 대상 없음 오류를 반환하십시오.
src/test/java/konkuk/thip/roompost/adapter/in/web/RecordReportApiTest.java
106-118행에는 다른 방의 기록 신고 시 404를 반환하고 신고 횟수가 변경되지 않는 테스트를 추가하십시오.
In
`@src/main/java/konkuk/thip/roompost/adapter/out/persistence/AttendanceCheckCommandPersistenceAdapter.java`:
- Around line 50-56: Update AttendanceCheckCommandPersistenceAdapter.update to
avoid the read-then-save lost update by using a database-level atomic increment
of report_count for every reporting path. Check the affected-row count and throw
EntityNotFoundException with ATTENDANCE_CHECK_NOT_FOUND when no row is updated;
alternatively, apply `@Version-based` optimistic locking with retries. Add a
concurrent-report test that verifies all increments are accumulated.
In
`@src/main/java/konkuk/thip/roompost/application/service/AttendanceCheckReportService.java`:
- Around line 20-22: Update reportAttendanceCheck() and the
attendanceCheckCommandPort update flow to preserve concurrent report_count
increments: use a row lock, an atomic database increment, or `@Version-based`
optimistic-lock retry. Ensure concurrent requests cannot overwrite each other’s
increaseReportCount() result.
In
`@src/main/java/konkuk/thip/roompost/application/service/RecordReportService.java`:
- Around line 20-22: Update reportRecord() to make report-count increments
concurrency-safe: replace the current getByIdOrThrow(), increaseReportCount(),
and update() read-modify-write flow with an atomic increment query, or ensure
the lookup uses a PESSIMISTIC_WRITE row lock throughout the transaction.
Preserve the existing behavior of identifying the record by recordId and
propagating the not-found failure.
In
`@src/main/java/konkuk/thip/roompost/application/service/VoteReportService.java`:
- Around line 20-22: VoteReportService.reportVote()의 증가-저장 흐름이 동시 신고에서 갱신을 유실하지
않도록 보호하십시오. VoteJpaEntity와 voteCommandPort.updateVote() 저장 경로를 확인해 `@Version` 기반
낙관적 잠금과 재시도를 적용하거나, report_count를 데이터베이스에서 원자적으로 증가시키는 전용 갱신을 사용하십시오. 동시 요청에서도
신고 횟수가 모두 누적되는 테스트를 추가하십시오.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 874904d5-5aa9-4330-83db-3a2a4db2599c
📒 Files selected for processing (39)
src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.javasrc/main/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntity.javasrc/main/java/konkuk/thip/room/adapter/in/web/RoomCommandController.javasrc/main/java/konkuk/thip/room/adapter/in/web/response/RoomReportResponse.javasrc/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.javasrc/main/java/konkuk/thip/room/adapter/out/mapper/RoomMapper.javasrc/main/java/konkuk/thip/room/application/port/in/RoomReportUseCase.javasrc/main/java/konkuk/thip/room/application/port/in/dto/RoomReportResult.javasrc/main/java/konkuk/thip/room/application/service/RoomReportService.javasrc/main/java/konkuk/thip/room/domain/Room.javasrc/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.javasrc/main/java/konkuk/thip/roompost/adapter/in/web/response/AttendanceCheckReportResponse.javasrc/main/java/konkuk/thip/roompost/adapter/in/web/response/RecordReportResponse.javasrc/main/java/konkuk/thip/roompost/adapter/in/web/response/VoteReportResponse.javasrc/main/java/konkuk/thip/roompost/adapter/out/jpa/AttendanceCheckJpaEntity.javasrc/main/java/konkuk/thip/roompost/adapter/out/jpa/RecordJpaEntity.javasrc/main/java/konkuk/thip/roompost/adapter/out/jpa/VoteJpaEntity.javasrc/main/java/konkuk/thip/roompost/adapter/out/mapper/AttendanceCheckMapper.javasrc/main/java/konkuk/thip/roompost/adapter/out/mapper/RecordMapper.javasrc/main/java/konkuk/thip/roompost/adapter/out/mapper/VoteMapper.javasrc/main/java/konkuk/thip/roompost/adapter/out/persistence/AttendanceCheckCommandPersistenceAdapter.javasrc/main/java/konkuk/thip/roompost/application/port/in/AttendanceCheckReportUseCase.javasrc/main/java/konkuk/thip/roompost/application/port/in/RecordReportUseCase.javasrc/main/java/konkuk/thip/roompost/application/port/in/VoteReportUseCase.javasrc/main/java/konkuk/thip/roompost/application/port/in/dto/attendancecheck/AttendanceCheckReportResult.javasrc/main/java/konkuk/thip/roompost/application/port/in/dto/record/RecordReportResult.javasrc/main/java/konkuk/thip/roompost/application/port/in/dto/vote/VoteReportResult.javasrc/main/java/konkuk/thip/roompost/application/port/out/AttendanceCheckCommandPort.javasrc/main/java/konkuk/thip/roompost/application/service/AttendanceCheckReportService.javasrc/main/java/konkuk/thip/roompost/application/service/RecordReportService.javasrc/main/java/konkuk/thip/roompost/application/service/VoteReportService.javasrc/main/java/konkuk/thip/roompost/domain/AttendanceCheck.javasrc/main/java/konkuk/thip/roompost/domain/Record.javasrc/main/java/konkuk/thip/roompost/domain/Vote.javasrc/main/resources/db/migration/V260807__Add_report_count_to_rooms_and_attendance_checks.sqlsrc/test/java/konkuk/thip/room/adapter/in/web/RoomReportApiTest.javasrc/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckReportApiTest.javasrc/test/java/konkuk/thip/roompost/adapter/in/web/RecordReportApiTest.javasrc/test/java/konkuk/thip/roompost/adapter/in/web/VoteReportApiTest.java
| @Operation( | ||
| summary = "기록 신고", | ||
| description = "사용자가 기록을 신고합니다. 신고 횟수만 증가하며 별도의 처리는 이루어지지 않습니다." | ||
| ) | ||
| @ExceptionDescription(RECORD_REPORT) | ||
| @PostMapping("/rooms/{roomId}/record/{recordId}/report") | ||
| public BaseResponse<RecordReportResponse> reportRecord( | ||
| @Parameter(description = "신고할 방 ID", example = "1") @PathVariable("roomId") final Long roomId, | ||
| @Parameter(description = "신고하려는 기록 ID", example = "1") @PathVariable("recordId") final Long recordId) { | ||
| return BaseResponse.ok(RecordReportResponse.of(recordReportUseCase.reportRecord(recordId))); | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
중첩 경로의 roomId 소속을 검증하십시오.
세 엔드포인트는 {roomId}를 받지만 use case에는 하위 리소스 ID만 전달합니다. 따라서 POST /rooms/A/record/B/report에서 기록 B가 방 A에 속하지 않아도 B의 신고 횟수가 증가합니다. 하위 리소스의 방 ID가 경로의 roomId와 다르면 대상 없음 오류를 반환하도록 use case 계약과 서비스를 변경하십시오.
src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L92-L102:roomId와recordId를 함께 use case에 전달하십시오.src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L168-L178:roomId와voteId를 함께 use case에 전달하십시오.src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L213-L225:roomId와attendanceCheckId를 함께 use case에 전달하십시오.src/test/java/konkuk/thip/roompost/adapter/in/web/RecordReportApiTest.java#L106-L118: 다른 방에 속한 기록을 신고하면 404를 반환하고 신고 횟수를 변경하지 않는 테스트를 추가하십시오.
📍 Affects 2 files
src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L92-L102(this comment)src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L168-L178src/main/java/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java#L213-L225src/test/java/konkuk/thip/roompost/adapter/in/web/RecordReportApiTest.java#L106-L118
🤖 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/konkuk/thip/roompost/adapter/in/web/RoomPostCommandController.java`
around lines 92 - 102, 중첩 경로의 방 소속 검증이 누락되어 하위 리소스만으로 처리되는 문제를 수정하십시오.
RoomPostCommandController의 92-102행에서는 roomId와 recordId를 함께 recordReportUseCase에
전달하고, 168-178행과 213-225행에서도 각각 roomId와 voteId, roomId와 attendanceCheckId를 함께
전달하도록 관련 use case 계약과 서비스를 변경해 소속이 다르면 대상 없음 오류를 반환하십시오.
src/test/java/konkuk/thip/roompost/adapter/in/web/RecordReportApiTest.java
106-118행에는 다른 방의 기록 신고 시 404를 반환하고 신고 횟수가 변경되지 않는 테스트를 추가하십시오.
| @Override | ||
| public void update(AttendanceCheck attendanceCheck) { | ||
| AttendanceCheckJpaEntity attendanceCheckJpaEntity = attendanceCheckJpaRepository.findByAttendanceCheckId(attendanceCheck.getId()).orElseThrow( | ||
| () -> new EntityNotFoundException(ATTENDANCE_CHECK_NOT_FOUND) | ||
| ); | ||
|
|
||
| attendanceCheckJpaRepository.save(attendanceCheckJpaEntity.updateFrom(attendanceCheck)); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
신고 횟수 증가를 원자 연산으로 변경하십시오.
Line 52의 조회와 Line 56의 저장 사이에 잠금 또는 버전 검사가 없습니다. 두 요청이 reportCount = N을 동시에 읽으면 둘 다 N + 1을 저장합니다. 기대값 N + 2 대신 N + 1이 저장됩니다.
모든 신고 경로에서 report_count = report_count + 1 원자 UPDATE를 사용하십시오. 영향 행 수가 0이면 ATTENDANCE_CHECK_NOT_FOUND를 반환하십시오. 또는 @Version과 재시도를 사용하십시오. 동시 요청 누적 테스트도 추가하십시오.
🤖 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/konkuk/thip/roompost/adapter/out/persistence/AttendanceCheckCommandPersistenceAdapter.java`
around lines 50 - 56, Update AttendanceCheckCommandPersistenceAdapter.update to
avoid the read-then-save lost update by using a database-level atomic increment
of report_count for every reporting path. Check the affected-row count and throw
EntityNotFoundException with ATTENDANCE_CHECK_NOT_FOUND when no row is updated;
alternatively, apply `@Version-based` optimistic locking with retries. Add a
concurrent-report test that verifies all increments are accumulated.
| AttendanceCheck attendanceCheck = attendanceCheckCommandPort.getByIdOrThrow(attendanceCheckId); | ||
| attendanceCheck.increaseReportCount(); | ||
| attendanceCheckCommandPort.update(attendanceCheck); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
ast-grep outline src/main/java/konkuk/thip/roompost/application/service/AttendanceCheckReportService.java --items all
ast-grep outline src/main/java/konkuk/thip/roompost/adapter/out/persistence/AttendanceCheckCommandPersistenceAdapter.java --items all
rg -n -C 4 -P '`@Version`|`@Lock`|PESSIMISTIC|report_count|reportCount|update\(AttendanceCheck|findByAttendanceCheckId' \
src/main/java/konkuk/thip/roompostRepository: THIP-TextHip/THIP-Server
Length of output: 35771
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,90p' src/main/java/konkuk/thip/roompost/application/service/AttendanceCheckReportService.java
sed -n '44,58p' src/main/java/konkuk/thip/roompost/adapter/out/persistence/AttendanceCheckCommandPersistenceAdapter.java
rg -n -C 3 'reportAttendanceCheck|attendanceCheckCommandPort\.report|reportAttendanceCheck\(' src/main/java/konkuk/thip/roompostRepository: THIP-TextHip/THIP-Server
Length of output: 5164
동시 신고에서 report_count 증가분을 보존해야 합니다.
reportAttendanceCheck()가 조회 afterward 값에 1을 더한 뒤 update()가 또 다시 엔티티에서 reportCount를 덮어써 저장합니다. 두 트랜잭션이 같은 값을 읽으면 둘 다 같은 값으로 저장하고 1회 증가분이 누락됩니다.
행 잠금, DB 원자적 증가 쿼리, 또는 @Version 기반 재시도를 추가하십시오.
🤖 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/konkuk/thip/roompost/application/service/AttendanceCheckReportService.java`
around lines 20 - 22, Update reportAttendanceCheck() and the
attendanceCheckCommandPort update flow to preserve concurrent report_count
increments: use a row lock, an atomic database increment, or `@Version-based`
optimistic-lock retry. Ensure concurrent requests cannot overwrite each other’s
increaseReportCount() result.
| Record record = recordCommandPort.getByIdOrThrow(recordId); | ||
| record.increaseReportCount(); | ||
| recordCommandPort.update(record); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
ast-grep outline src/main/java/konkuk/thip/roompost/application/service/RecordReportService.java --items all
rg -n -C 5 -P 'interface\s+RecordCommandPort|class\s+\w*Record\w*Persistence\w*Adapter|void\s+update\(Record|`@Version`|`@Lock`|PESSIMISTIC|report_count|reportCount' \
src/main/java/konkuk/thip/roompostRepository: THIP-TextHip/THIP-Server
Length of output: 37797
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
sed -n '1,140p' src/main/java/konkuk/thip/roompost/application/service/RecordReportService.java
printf '\n--- RecordCommand persistence ---\n'
sed -n '80,105p' src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java
printf '\n--- RecordJpaRepository ---\n'
cat -n src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordJpaRepository.java
printf '\n--- RecordCommandPort ---\n'
cat -n src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java
printf '\n--- Record domain ---\n'
sed -n '1,95p' src/main/java/konkuk/thip/roompost/domain/Record.java
printf '\n--- all RecordCommandPersistenceAdapter methods ---\n'
rg -n -A6 -B2 'public\s+\w+\s+(save|update|delete|softDelete|increaseReportCount)' src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.javaRepository: THIP-TextHip/THIP-Server
Length of output: 9596
동시 신고 증가를 원자적으로 보호하십시오.
reportRecord()의 조회-증가-저장 흐름에서 findById()는 PESSIMISTIC_WRITE 잠금을 사용하지 않습니다. update()도 별도 조회 후 새 도메인 값을 덮어써서 별도 잠금 없이 저장하므로, 동시 신고 요청이 서로 겹치면 신고 횟수가 손실될 수 있습니다. 증가 문법을 원자 쿼리로 처리하거나 행 잠금을 적용하십시오.
🤖 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/konkuk/thip/roompost/application/service/RecordReportService.java`
around lines 20 - 22, Update reportRecord() to make report-count increments
concurrency-safe: replace the current getByIdOrThrow(), increaseReportCount(),
and update() read-modify-write flow with an atomic increment query, or ensure
the lookup uses a PESSIMISTIC_WRITE row lock throughout the transaction.
Preserve the existing behavior of identifying the record by recordId and
propagating the not-found failure.
| Vote vote = voteCommandPort.getByIdOrThrow(voteId); | ||
| vote.increaseReportCount(); | ||
| voteCommandPort.updateVote(vote); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Vote 엔티티의 버전 컬럼 및 신고 횟수 매핑을 확인한다.
ast-grep outline \
src/main/java/konkuk/thip/roompost/adapter/out/jpa/VoteJpaEntity.java \
--items all
# Vote 저장 경로가 원자적 UPDATE 또는 낙관적 잠금을 사용하는지 확인한다.
rg -n -C 4 \
'`@Version`|reportCount|report_count|updateVote\s*\(|`@Modifying`|UPDATE\s+' \
src/main/java/konkuk/thip/roompost
# 신고 횟수 증가의 동시성 테스트 유무를 확인한다.
rg -n -C 3 \
'reportVote|ExecutorService|CompletableFuture|CountDownLatch|reportCount' \
src/test/java/konkuk/thip/roompostRepository: THIP-TextHip/THIP-Server
Length of output: 50380
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Vote entity/mapper/pertistence relevant sections =="
sed -n '1,120p' src/main/java/konkuk/thip/roompost/domain/Vote.java
echo
sed -n '1,90p' src/main/java/konkuk/thip/roompost/adapter/out/jpa/VoteJpaEntity.java
echo
sed -n '190,210p' src/main/java/konkuk/thip/roompost/adapter/out/persistence/VoteCommandPersistenceAdapter.java
echo
rg -n '`@Version`|Lock(\\.|\\(|Pessimistic|Optimistic)|Pessimistic|Optimistic|PessimisticLock|OptimisticLock|report_count\\s*=.*report_count|reportCount\\s*=.*(reportCount|current|old)' src/main/java/konkuk/thip/roompost
echo
echo "== VoteReport tests mentioning concurrency/reportCount =="
rg -n -C 4 'reportVote|report_count|reportCount|ExecutorService|CompletableFuture|CountDownLatch|Thread|concurr|race|concurrent' src/test/java/konkuk/thip/roompost/application/service src/test/java/konkuk/thip/roompost/adapter/in/web src/test/java/konkuk/thip/roompost/adapter/out || trueRepository: THIP-TextHip/THIP-Server
Length of output: 6548
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== VoteCommandPersistenceAdapter updateVote =="
sed -n '190,210p' src/main/java/konkuk/thip/roompost/adapter/out/persistence/VoteCommandPersistenceAdapter.java
echo
echo "== Lock/version/update counters in vote/package =="
rg -n --no-heading '`@Version`|Lock\.|`@Lock`|Pessimistic|Optimistic|PessimisticLock|OptimisticLock|report_count\s*=.*report_count|reportCount\s*=.*(reportCount|current|old)' src/main/java/konkuk/thip/roompost
echo
echo "== VoteReport test concurrency/reportCount references =="
rg -n -C 3 --no-heading 'reportVote|report_count|reportCount|ExecutorService|CompletableFuture|CountDownLatch|Thread|concurr|race|concurrent' src/test/java || trueRepository: THIP-TextHip/THIP-Server
Length of output: 34605
동시 투표 신고에서 report_count 누적을 보호하십시오.
VoteReportService.reportVote()가 메모리에서 reportCount++ 후 save()를 호출하지만, VoteJpaEntity에는 @Version이 없고 저장 경로도 save()로 덮어쓰는 구조입니다. 동일한 report_count 값을 읽은 두 트랜잭션이면 실제 신고가 2번이어도 1번만 저장될 수 있습니다. @Version 낙관적 잠금의 재시도 또는 report_count = report_count + 1의 원자적 갱신을 추가하고, 동시 요청 테스트를 병행하십시오.
🤖 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/konkuk/thip/roompost/application/service/VoteReportService.java`
around lines 20 - 22, VoteReportService.reportVote()의 증가-저장 흐름이 동시 신고에서 갱신을 유실하지
않도록 보호하십시오. VoteJpaEntity와 voteCommandPort.updateVote() 저장 경로를 확인해 `@Version` 기반
낙관적 잠금과 재시도를 적용하거나, report_count를 데이터베이스에서 원자적으로 증가시키는 전용 갱신을 사용하십시오. 동시 요청에서도
신고 횟수가 모두 누적되는 테스트를 추가하십시오.
Summary
report_count컬럼이 없어 마이그레이션으로 추가posts테이블(단일 테이블 상속)에 Feed가 쓰던report_count컬럼이 이미 존재해 엔티티 매핑만 추가posts.report_count의 기존 NULL 값(Record/Vote 로우)을 0으로 백필하고, rooms/attendance_checks와 함께 NOT NULL 제약 추가Endpoints
POST /rooms/{roomId}/reportPOST /rooms/{roomId}/record/{recordId}/reportPOST /rooms/{roomId}/vote/{voteId}/reportPOST /rooms/{roomId}/daily-greeting/{attendanceCheckId}/reportTest plan
RoomReportApiTest,RecordReportApiTest,VoteReportApiTest,AttendanceCheckReportApiTest🤖 Generated with Claude Code
Summary by CodeRabbit
새 기능
데이터 개선
테스트