From f0aa092dda387d11e77cd1e9e0200042b38aae96 Mon Sep 17 00:00:00 2001 From: loseminho Date: Thu, 16 Oct 2025 10:56:57 +0900 Subject: [PATCH] =?UTF-8?q?Hotfix/loseminho=20:=20terminated=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=A1=B0=ED=9A=8C=20=EC=A0=9C=EA=B1=B0=20(#314)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 스더티룸 권한에 대한 로직 개선 * fix: ci에서 통과 못한 테스트코드 수정 * fix:rest api와 웹소켓 중간 경로 통합 * fix:rest api와 웹소켓 중간 경로 통합 * fix: 에러 확인을 위한 통합테스트 추가, Room.create()메서드 수정 * refactor, feat : 조회 분할 * refactor: redis 로직 최적화 및 중복 검증 로직 제거 * fix: 에러 번호 수정 * feat: 스터디룸 방 비밀번호 변경 및 삭제 기능 구현 * fix:app-dev 제거 * feat: 웹소켓 기반 소극적 하트비트 * feat: 스터디룸 썸네일 기능 추가 및 webrtc 설정 변경에서 주석처리 * fix:소극적 하트비트 사용 주석처리 * Feat: 스터디 룸 내에 고양이 아바타 시스템과 프로필 이미지 url 연동 * fix: 기존 작성되어있던 test 코드 수정 * test: 아바타 테스트 코드 완료 * refactor: 프론트엔드 요청 사항에 따른 스터디룸 조회 마스킹 제거 * feat: 스터디룸 방 초대 코드 시스템 * Infra: main branch 로컬 환경과 운영 환경 동기화 * Infra: docker-compose 파일 수정 - Redis 버전 업그레이드 기존: 6.2 -> 변경: 7.0 * Fix: 백엔드 CD 파일 수정 - 자동화 시, 잘못된 도메인으로 호스트 ID 검증하는 오류 해결 * Infra: EC2 환경변수 수정 - 잘못 표기한 도메인 네임 변경 * Chore: CD 파일 수정 - Github Actions commandLine 인식 문제로 인해 set -Eeuo pipefail 줄바꿈 * Chore: 백엔드 CD 파일 수정 - 인스턴스 ID 체크 삭제 * Infra: 백엔드 CD 파일 수정 - .env 파일 추가시, $DOT_ENV_PROD -> $DOT_ENV 로 변경 * Infra: 도커 컴포즈 수정 - mysql 사용자 정보 변경 * Infra: 운영환경 설정 - application-prod.yml 과 application.yml 동기화 * Fix: SecurityConfig 수정 - H2 DB 허용 X * test,fix: 방 초대에 대한 테스트 코드 작성 및 에러 수정 * fix: 스터디룸 파일 업로드 맵핑 형식으로 변환 * fix: 병합충돌 제어 수정 * fix: 병합충돌 제어 * fix: 스터디 룸 내 프론트엔드 요구 사항 및 오류사항 수정 * feat: 방 즐겨찾기, 방 공지사항 구현 * fix: mockbean 수정 * fix: 테스트에서 빠진 비로그인 사용자 추가 * hotfix: 누락된 사용자 추방에 대한 컨트롤러 추가 * hotfix: VISITOR도 추방 가능하도록 수정 * fix: 누락된 테스트코드 추가 및 테스트코드 로직 수정 * refactor: 아바타 시스템 db와 분리 및 테스트 코드 수정 * fix: 턴서버 dev에 맞춤 * hotfix: 추방 후 추방당한 유저에게 개인 메시지 전송 로직 추가 * fix: 웹소켓 메세지 전송 * fix: 병합 오류 제어 * test: 테스트코드 수정 * refactor: 스터디룸 파일 업로드 s3 + fileAttachment + Mapping 제거 방식으로 수정 * feat: 방 내 방명록 기능 추가 * hotfix:로젝 내 웹소켓 세션 제거 * hotfix: 방 조회 시 terminated 상태는 조회 안되도록 --------- Co-authored-by: namgigun --- .../repository/RoomRepositoryImpl.java | 61 ++++++++++++------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/back/domain/studyroom/repository/RoomRepositoryImpl.java b/src/main/java/com/back/domain/studyroom/repository/RoomRepositoryImpl.java index 77e38e99..96b36ce7 100644 --- a/src/main/java/com/back/domain/studyroom/repository/RoomRepositoryImpl.java +++ b/src/main/java/com/back/domain/studyroom/repository/RoomRepositoryImpl.java @@ -33,12 +33,12 @@ public class RoomRepositoryImpl implements RoomRepositoryCustom { private final QUser user = QUser.user; /** - * 공개 방 중 입장 가능한 방들 조회 (페이징) + * 공개 방 중 입장 가능한 방들 조회 (페이징, TERMINATED 제외) * 조회 조건: * - 비공개가 아닌 방 (isPrivate = false) * - 활성화된 방 (isActive = true) * - 입장 가능한 상태 (WAITING 또는 ACTIVE) - * + * * 참고: 정원 체크는 Redis 기반으로 프론트엔드/서비스에서 수행 * @param pageable 페이징 정보 * @return 페이징된 방 목록 @@ -52,7 +52,8 @@ public Page findJoinablePublicRooms(Pageable pageable) { .where( room.isPrivate.eq(false), room.isActive.eq(true), - room.status.in(RoomStatus.WAITING, RoomStatus.ACTIVE) + room.status.in(RoomStatus.WAITING, RoomStatus.ACTIVE), // WAITING, ACTIVE만 (TERMINATED, PAUSED 제외) + room.status.ne(RoomStatus.TERMINATED) // TERMINATED 명시적 제외 ) .orderBy(room.createdAt.desc()) .offset(pageable.getOffset()) @@ -66,7 +67,8 @@ public Page findJoinablePublicRooms(Pageable pageable) { .where( room.isPrivate.eq(false), room.isActive.eq(true), - room.status.in(RoomStatus.WAITING, RoomStatus.ACTIVE) + room.status.in(RoomStatus.WAITING, RoomStatus.ACTIVE), + room.status.ne(RoomStatus.TERMINATED) ) .fetchOne(); @@ -74,7 +76,7 @@ public Page findJoinablePublicRooms(Pageable pageable) { } /** - * 사용자가 참여 중인 방 조회 (MEMBER 이상만) + * 사용자가 참여 중인 방 조회 (MEMBER 이상만, TERMINATED 제외) * 조회 조건: * - 특정 사용자가 MEMBER 이상으로 등록된 방 (VISITOR 제외) * - DB에 저장된 멤버십만 조회 @@ -89,7 +91,8 @@ public List findRoomsByUserId(Long userId) { .join(room.roomMembers, roomMember) // 멤버 조인 .where( roomMember.user.id.eq(userId), - roomMember.role.ne(com.back.domain.studyroom.entity.RoomRole.VISITOR) // VISITOR 제외 + roomMember.role.ne(com.back.domain.studyroom.entity.RoomRole.VISITOR), // VISITOR 제외 + room.status.ne(RoomStatus.TERMINATED) // TERMINATED 제외 ) .fetch(); } @@ -160,7 +163,7 @@ public Page findRoomsWithFilters(String title, RoomStatus status, Boolean } /** - * 인기 방 조회 (참가자 수 기준) - 공개+비공개 포함 + * 인기 방 조회 (참가자 수 기준, TERMINATED 제외) * * 참고: 참가자 수는 Redis에서 조회하므로 DB에서는 정렬 불가 * 서비스 레이어에서 Redis 데이터로 정렬 필요 @@ -177,7 +180,8 @@ public Page findPopularRooms(Pageable pageable) { .selectFrom(room) .leftJoin(room.createdBy, user).fetchJoin() // N+1 방지 .where( - room.isActive.eq(true) + room.isActive.eq(true), + room.status.ne(RoomStatus.TERMINATED) // TERMINATED 제외 ) .orderBy(room.createdAt.desc()) // 최신순 (서비스에서 Redis 기반으로 재정렬) .offset(pageable.getOffset()) @@ -189,7 +193,8 @@ public Page findPopularRooms(Pageable pageable) { .select(room.count()) .from(room) .where( - room.isActive.eq(true) + room.isActive.eq(true), + room.status.ne(RoomStatus.TERMINATED) // TERMINATED 제외 ) .fetchOne(); @@ -272,14 +277,14 @@ public Optional findByIdWithLock(Long roomId) { } /** - * 모든 방 조회 (공개 + 비공개 전체) + * 모든 방 조회 (공개 + 비공개 전체, TERMINATED 제외) * 조회 조건: * - 모든 방 (공개 + 비공개) * 정렬: * 1. 열린 방(WAITING, ACTIVE) 우선 * 2. 닫힌 방(PAUSED, TERMINATED) 뒤로 * 3. 최신 생성순 - * + * * 비공개 방은 컨트롤러/서비스 레이어에서 정보 마스킹 합니당 */ @Override @@ -287,8 +292,11 @@ public Page findAllRooms(Pageable pageable) { List rooms = queryFactory .selectFrom(room) .leftJoin(room.createdBy, user).fetchJoin() + .where( + room.status.ne(RoomStatus.TERMINATED) // TERMINATED 제외 + ) .orderBy( - // 열린 방 우선 (0), 닫힌 방 뒤로 (1) + // 열린 방 우선 (0), 일시정지 방 뒤로 (1) room.status.when(RoomStatus.WAITING).then(0) .when(RoomStatus.ACTIVE).then(0) .otherwise(1).asc(), @@ -302,13 +310,16 @@ public Page findAllRooms(Pageable pageable) { Long totalCount = queryFactory .select(room.count()) .from(room) + .where( + room.status.ne(RoomStatus.TERMINATED) // TERMINATED 제외 + ) .fetchOne(); return new PageImpl<>(rooms, pageable, totalCount != null ? totalCount : 0); } /** - * 공개 방 전체 조회 + * 공개 방 전체 조회 (TERMINATED 제외) * 조회 조건: * - isPrivate = false * - includeInactive에 따라 닫힌 방 포함 여부 결정 @@ -316,9 +327,10 @@ public Page findAllRooms(Pageable pageable) { */ @Override public Page findPublicRoomsWithStatus(boolean includeInactive, Pageable pageable) { - BooleanExpression whereClause = room.isPrivate.eq(false); + BooleanExpression whereClause = room.isPrivate.eq(false) + .and(room.status.ne(RoomStatus.TERMINATED)); // TERMINATED 제외 - // 닫힌 방 제외 옵션 + // 일시정지 방 제외 옵션 if (!includeInactive) { whereClause = whereClause.and( room.status.in(RoomStatus.WAITING, RoomStatus.ACTIVE) @@ -349,7 +361,7 @@ public Page findPublicRoomsWithStatus(boolean includeInactive, Pageable pa } /** - * 내가 멤버인 비공개 방 조회 + * 내가 멤버인 비공개 방 조회 (TERMINATED 제외) * 조회 조건: * - isPrivate = true * - 내가 멤버로 등록된 방 @@ -359,9 +371,10 @@ public Page findPublicRoomsWithStatus(boolean includeInactive, Pageable pa @Override public Page findMyPrivateRooms(Long userId, boolean includeInactive, Pageable pageable) { BooleanExpression whereClause = room.isPrivate.eq(true) - .and(roomMember.user.id.eq(userId)); + .and(roomMember.user.id.eq(userId)) + .and(room.status.ne(RoomStatus.TERMINATED)); // TERMINATED 제외 - // 닫힌 방 제외 옵션 + // 일시정지 방 제외 옵션 if (!includeInactive) { whereClause = whereClause.and( room.status.in(RoomStatus.WAITING, RoomStatus.ACTIVE) @@ -394,7 +407,7 @@ public Page findMyPrivateRooms(Long userId, boolean includeInactive, Pagea } /** - * 내가 호스트(방장)인 방 조회 + * 내가 호스트(방장)인 방 조회 (TERMINATED 제외) * 조회 조건: * - room.createdBy.id = userId * 정렬: 열린 방 우선 → 최신순 @@ -404,7 +417,10 @@ public Page findRoomsByHostId(Long userId, Pageable pageable) { List rooms = queryFactory .selectFrom(room) .leftJoin(room.createdBy, user).fetchJoin() - .where(room.createdBy.id.eq(userId)) + .where( + room.createdBy.id.eq(userId), + room.status.ne(RoomStatus.TERMINATED) // TERMINATED 제외 + ) .orderBy( room.status.when(RoomStatus.WAITING).then(0) .when(RoomStatus.ACTIVE).then(0) @@ -418,7 +434,10 @@ public Page findRoomsByHostId(Long userId, Pageable pageable) { Long totalCount = queryFactory .select(room.count()) .from(room) - .where(room.createdBy.id.eq(userId)) + .where( + room.createdBy.id.eq(userId), + room.status.ne(RoomStatus.TERMINATED) // TERMINATED 제외 + ) .fetchOne(); return new PageImpl<>(rooms, pageable, totalCount != null ? totalCount : 0);