Skip to content

[FEAT] 연애관 채팅 프로필 공개 요청 구현#71

Open
Sehi55 wants to merge 18 commits into
developfrom
feat/loveview-profile-request
Open

[FEAT] 연애관 채팅 프로필 공개 요청 구현#71
Sehi55 wants to merge 18 commits into
developfrom
feat/loveview-profile-request

Conversation

@Sehi55

@Sehi55 Sehi55 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

변경 사항

  • 러브뷰 채팅방에서 프로필 공개 요청 API 추가
  • 메시지 10개 이상인 경우에만 프로필 공개 요청 가능하도록 검증 추가
  • 프로필 공개 요청/수락/거절 알림 이벤트 저장을 위해 notification 타입 제약 확장

주요 구현

  • POST /api/loveview/profile/request/{chatRoomId} 추가
  • 프로필 요청 생성 전 현재 상태가 READY인지 검증
  • PHOTO_REQUEST_RECEIVED, PHOTO_REQUEST_ACCEPTED, PHOTO_REQUEST_REJECTED 이벤트 저장 가능하도록 DB 제약 수정

Summary by CodeRabbit

  • New Features

    • 채팅방에서 프로필 사진 공개 요청을 보낼 수 있게 되었습니다.
    • 요청 가능 상태가 아니면 미리 안내 메시지와 함께 요청이 차단됩니다.
  • Bug Fixes

    • 거절 처리 응답 문구를 더 정확하게 수정했습니다.
    • 알림 유형 저장 방식이 개선되어 기존 알림 데이터와의 호환성이 향상되었습니다.

kimjuneon and others added 16 commits February 21, 2026 12:47
[Feature] 사용자 사진 관리 기능 구현 및 GCP 배포 전환
[Fix] 배포 시 이미지 환경변수 전달 방식 수정
이미지 계산 방식 개선
[Fix] 배포 단계에서 이미지 주소를 직접 생성
fix: 배포 시 compose 환경변수 로드 보강
fix: compose 실행 시 이미지 변수를 직접 전달
호감/메시지 응답 흐름 및 상대 프로필 과금 로직 개선
관리자 콘솔 및 운영 관리 기능 추가
관리자 회원 사진과 멤버십 표시 수정
운영 환경 SQL 로그 비활성화
수동 배포 실행 버튼 추가
채팅 서비스 구현 및 개선
@Sehi55 Sehi55 self-assigned this Jul 1, 2026
@Sehi55 Sehi55 added the enhancement New feature or request label Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

프로필 사진 요청 생성 시 사전 상태 검증 로직과 새 요청 생성 엔드포인트가 추가되고, 거절 응답 문구가 수정되었습니다. 또한 Notification의 type 필드를 문자열 enum으로 매핑하도록 변경하고, 이를 반영해 DB 컬럼 타입 전환 및 CHECK 제약을 재정의하는 마이그레이션이 추가되었습니다.

Changes

프로필 사진 요청 흐름

Layer / File(s) Summary
요청 상태 검증 로직 추가
PhotoRequestService.java
createPhotoRequest 호출 시 getPhotoRequestStatus로 READY 상태 여부를 먼저 확인하고, 아니면 IllegalStateException을 발생시킵니다.
요청 생성 엔드포인트 추가 및 거절 메시지 수정
PhotoRequestController.java
POST /request/{chatRoomId} 엔드포인트가 추가되어 서비스 호출 후 성공 응답을 반환하며, rejectPhotoRequest의 응답 문구가 "거절하였습니다."로 수정되었습니다.

알림 타입 문자열 저장 전환

Layer / File(s) Summary
Notification 엔티티 매핑 변경
Notification.java
type 필드에 @Enumerated(EnumType.STRING)과 @Column(name="type", length=50)이 추가되었습니다.
notification.type 컬럼 전환 및 제약 재정의
V19__change_notification_type_check.sql
type 컬럼을 VARCHAR(50)로 변환하고 기존 숫자값을 문자열 상수로 재매핑하며, notification_type_check CHECK 제약을 새로 추가했습니다.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant PhotoRequestController
  participant PhotoRequestService

  Client->>PhotoRequestController: POST /request/{chatRoomId}
  PhotoRequestController->>PhotoRequestService: createPhotoRequest(chatRoomId, userId)
  PhotoRequestService->>PhotoRequestService: getPhotoRequestStatus(roomId, userId)
  alt 상태가 READY가 아님
    PhotoRequestService-->>PhotoRequestController: IllegalStateException
    PhotoRequestController-->>Client: 오류 응답
  else 상태가 READY
    PhotoRequestService-->>PhotoRequestController: 처리 완료
    PhotoRequestController-->>Client: 200 OK ("프로필 사진 공개를 요청했습니다.")
  end
Loading

Possibly related PRs

  • mannabom/mannabomServer#70: 동일한 PhotoRequestService/PhotoRequestController의 프로필 사진 요청 기능 로직과 엔드포인트를 다룹니다.

Poem

토끼가 콩콩, 사진을 요청해요 🐰
READY 상태인지 살펴보고서
새 엔드포인트로 폴짝 뛰어가
타입도 이제는 글자로 저장하죠
마이그레이션까지 깔끔하게 완료! 🥕

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 연애관 채팅에서 프로필 공개 요청 기능 추가라는 핵심 변경을 정확하고 간결하게 요약합니다.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/loveview-profile-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.

@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: 1

🧹 Nitpick comments (2)
manabom/src/main/java/mannabom_server/manabom/application/matching/service/PhotoRequestService.java (1)

73-92: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

중복 쿼리 및 도달 불가능한 분기 정리 필요

createPhotoRequest에서 getPhotoRequestStatus(roomId, userId)를 호출하면 내부적으로 findRoomById, validateLoveViewChatRoom, validateActiveMember, photoRequestRepository.findTopByHistoryIdOrderByIdDesc가 다시 실행됩니다. 이는 이미 73-77번 줄에서 수행한 조회/검증과 중복되어 트랜잭션당 불필요한 DB 조회가 두 배로 늘어납니다.

또한 getPhotoRequestStatus의 로직(라인 54-68)을 따라가 보면, currentStatus == LoveViewPhotoStatus.READY가 되는 경우는 latestOpt가 비어있거나 상태가 REJECTED이면서 메시지 수가 10개 이상인 경우뿐입니다. 즉 READY 검증(79-82번 줄)을 통과한 이후에는 88-92번 줄의 latestOpt.get().getStatus() != PhotoRequestStatus.REJECTED 조건이 항상 거짓이 되어 해당 분기가 도달 불가능한 죽은 코드가 됩니다.

getPhotoRequestStatus가 사용한 latestOpt를 반환하거나 재사용할 수 있도록 리팩터링하여 중복 조회를 없애고, 도달 불가능해진 88-92번 줄의 검증을 정리하는 것을 권장합니다.

♻️ 리팩터링 방향 예시
-        LoveViewPhotoStatus currentStatus = getPhotoRequestStatus(roomId, userId);
-        if (currentStatus != LoveViewPhotoStatus.READY) {
-            throw new IllegalStateException("아직 프로필 사진을 요청할 수 있는 상태가 아닙니다.");
-        }
-
-        LoveViewRecommendHistory loveView = room.getLoveView();
-        Long loveViewId = loveView.getId();
-
-        Optional<LoveViewPhotoRequest> latestOpt = photoRequestRepository.findTopByHistoryIdOrderByIdDesc(loveViewId);
-        if(latestOpt.isPresent()){
-            if(latestOpt.get().getStatus()!=PhotoRequestStatus.REJECTED){
-                throw new IllegalStateException("프로필 요청이 중복되었거나 이미 수락된 상태입니다.");
-            }
-        }
+        LoveViewRecommendHistory loveView = room.getLoveView();
+        Long loveViewId = loveView.getId();
+        Optional<LoveViewPhotoRequest> latestOpt = photoRequestRepository.findTopByHistoryIdOrderByIdDesc(loveViewId);
+        LoveViewPhotoStatus currentStatus = resolveStatus(room, userId, latestOpt);
+        if (currentStatus != LoveViewPhotoStatus.READY) {
+            throw new IllegalStateException("아직 프로필 사진을 요청할 수 있는 상태가 아닙니다.");
+        }

(위와 같이 상태 판별 로직을 latestOpt 재사용이 가능한 private 메서드로 추출하고, getPhotoRequestStatuscreatePhotoRequest 모두에서 활용하도록 리팩터링을 제안합니다.)

🤖 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
`@manabom/src/main/java/mannabom_server/manabom/application/matching/service/PhotoRequestService.java`
around lines 73 - 92, `createPhotoRequest` has duplicated
room/member/latest-request lookups because `getPhotoRequestStatus(roomId,
userId)` re-runs the same queries already done earlier, and the later
`latestOpt` status check is dead code once `READY` has been verified. Refactor
`PhotoRequestService#createPhotoRequest` and `getPhotoRequestStatus` to share
the same fetched `LoveViewPhotoRequest`/status data (for example by extracting a
private helper that returns both status and latest request), remove the repeated
repository call, and delete the unreachable `latestOpt.get().getStatus() !=
PhotoRequestStatus.REJECTED` branch.
manabom/src/main/resources/db/migration/V18__extend_notification_type_check.sql (1)

1-9: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy lift

enum 순서 의존성을 줄이세요

Notification.type가 ordinal로 DB에 저장되고 이 CHECK도 그 값에 맞춰져 있습니다. 지금은 맞지만, SseEventName의 순서 변경이나 중간 삽입이 곧바로 스키마 불일치로 이어지므로 고정 코드값이나 STRING 매핑으로 바꾸는 편이 안전합니다.

🤖 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
`@manabom/src/main/resources/db/migration/V18__extend_notification_type_check.sql`
around lines 1 - 9, `notification_type_check` and the `Notification.type`
mapping currently depend on `SseEventName` ordinals, so a future enum reorder or
insertion will break schema consistency. Update the persistence/migration design
used by `Notification.type` and the related enum mapping to use stable explicit
codes or STRING-based storage instead of ordinal values, and adjust the
`notification_type_check` constraint to validate those stable values rather than
a positional range.
🤖 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
`@manabom/src/main/resources/db/migration/V18__extend_notification_type_check.sql`:
- Around line 7-9: `notification.type` is still tied to enum ordinal storage,
and the current CHECK constraint only allows a positional range, so enum
reordering or inserts can silently change meaning. Update the `Notification`
mapping to stop using ordinal semantics by switching `type` to
`@Enumerated(EnumType.STRING)` or a fixed `int code` with a converter, then
adjust the `notification_type_check` migration/constraint to match the new
stable representation instead of `0..9`.

---

Nitpick comments:
In
`@manabom/src/main/java/mannabom_server/manabom/application/matching/service/PhotoRequestService.java`:
- Around line 73-92: `createPhotoRequest` has duplicated
room/member/latest-request lookups because `getPhotoRequestStatus(roomId,
userId)` re-runs the same queries already done earlier, and the later
`latestOpt` status check is dead code once `READY` has been verified. Refactor
`PhotoRequestService#createPhotoRequest` and `getPhotoRequestStatus` to share
the same fetched `LoveViewPhotoRequest`/status data (for example by extracting a
private helper that returns both status and latest request), remove the repeated
repository call, and delete the unreachable `latestOpt.get().getStatus() !=
PhotoRequestStatus.REJECTED` branch.

In
`@manabom/src/main/resources/db/migration/V18__extend_notification_type_check.sql`:
- Around line 1-9: `notification_type_check` and the `Notification.type` mapping
currently depend on `SseEventName` ordinals, so a future enum reorder or
insertion will break schema consistency. Update the persistence/migration design
used by `Notification.type` and the related enum mapping to use stable explicit
codes or STRING-based storage instead of ordinal values, and adjust the
`notification_type_check` constraint to validate those stable values rather than
a positional range.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0166a592-05d5-4144-8f0b-2afc688a5112

📥 Commits

Reviewing files that changed from the base of the PR and between e8a28f3 and b669f43.

📒 Files selected for processing (3)
  • manabom/src/main/java/mannabom_server/manabom/application/matching/service/PhotoRequestService.java
  • manabom/src/main/java/mannabom_server/manabom/presentation/matching/controller/PhotoRequestController.java
  • manabom/src/main/resources/db/migration/V18__extend_notification_type_check.sql

Comment thread manabom/src/main/resources/db/migration/V18__extend_notification_type_check.sql Outdated

@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.

🧹 Nitpick comments (1)
manabom/src/main/resources/db/migration/V19__change_notification_type_check.sql (1)

1-17: 🚀 Performance & Scalability | 🔵 Trivial

대용량 테이블에서 ALTER COLUMN TYPE은 전체 재작성 + 배타적 락을 유발

USING 절을 사용한 컬럼 타입 변경은 Postgres에서 테이블 전체를 재작성하며 ACCESS EXCLUSIVE 락을 획득합니다. notification 테이블 규모가 커질 경우 배포 시 다운타임을 유발할 수 있으니, 트래픽이 적은 시간대에 실행하거나 테이블 크기를 사전에 확인하는 것을 권장합니다.

🤖 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
`@manabom/src/main/resources/db/migration/V19__change_notification_type_check.sql`
around lines 1 - 17, The V19 notification migration changes notification.type
with ALTER COLUMN TYPE and a USING CASE, which triggers a full table rewrite and
ACCESS EXCLUSIVE lock on the notification table. Update this migration to
account for the heavy lock impact by either gating the deployment to a
low-traffic maintenance window or adding an explicit pre-check/operational note
based on notification table size before running the change. Reference the
V19__change_notification_type_check.sql migration and its ALTER TABLE
notification block so it’s easy to locate.
🤖 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.

Nitpick comments:
In
`@manabom/src/main/resources/db/migration/V19__change_notification_type_check.sql`:
- Around line 1-17: The V19 notification migration changes notification.type
with ALTER COLUMN TYPE and a USING CASE, which triggers a full table rewrite and
ACCESS EXCLUSIVE lock on the notification table. Update this migration to
account for the heavy lock impact by either gating the deployment to a
low-traffic maintenance window or adding an explicit pre-check/operational note
based on notification table size before running the change. Reference the
V19__change_notification_type_check.sql migration and its ALTER TABLE
notification block so it’s easy to locate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: df1f8058-4715-4a9a-934a-e246a5f85240

📥 Commits

Reviewing files that changed from the base of the PR and between b669f43 and a0033f5.

📒 Files selected for processing (2)
  • manabom/src/main/java/mannabom_server/manabom/domain/notification/entity/Notification.java
  • manabom/src/main/resources/db/migration/V19__change_notification_type_check.sql

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants