diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/controller/InvitationController.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/controller/InvitationController.java index fd643068..d530eb30 100644 --- a/src/backend/main-server/main/src/main/java/com/kickzo/main/controller/InvitationController.java +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/controller/InvitationController.java @@ -9,7 +9,7 @@ import com.kickzo.main.dto.request.RoomInviteRequestDto; import com.kickzo.main.service.InvitationService; -import com.kickzo.main.service.RoomService; +import com.kickzo.main.service.RoomQueryService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,7 +19,7 @@ @RequestMapping("/api/rooms/invitations") @RequiredArgsConstructor public class InvitationController { - private final RoomService roomService; + private final RoomQueryService roomQueryService; private final InvitationService invitationService; @PostMapping() @@ -35,7 +35,7 @@ public ResponseEntity acceptInvitation( @RequestHeader(value = "x-user-id") Long receiverId, @RequestBody RoomInviteRequestDto inviteRequestDto) { invitationService.acceptInvitation(receiverId, inviteRequestDto); - roomService.getRoomJoinResponse(inviteRequestDto.getRoomCode(), receiverId); + roomQueryService.getRoomJoinResponse(inviteRequestDto.getRoomCode(), receiverId); return ResponseEntity.ok("Invitation accepted"); } diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/controller/RoomController.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/controller/RoomController.java index 581ba38f..6bd73573 100644 --- a/src/backend/main-server/main/src/main/java/com/kickzo/main/controller/RoomController.java +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/controller/RoomController.java @@ -3,8 +3,10 @@ import java.util.List; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; @@ -20,6 +22,7 @@ import com.kickzo.main.dto.response.RoomEntryResponseDto; import com.kickzo.main.dto.response.UserInfoDto; import com.kickzo.main.service.PlaylistService; +import com.kickzo.main.service.RoomQueryService; import com.kickzo.main.service.RoomService; import com.kickzo.main.service.RoomUserService; @@ -34,6 +37,7 @@ public class RoomController implements RoomApi { private final RoomService roomService; + private final RoomQueryService roomQueryService; private final PlaylistService playlistService; private final RoomUserService roomUserService; @@ -44,7 +48,8 @@ public ResponseEntity joinRoom( @RequestBody RoomJoinRequestDto roomJoinRequestDto) { String roomCode = roomJoinRequestDto.getRoomCode(); log.info("Join Room : UserId = {}, RoomCode = {}", userId, roomCode); - RoomEntryResponseDto response = roomService.getRoomJoinResponse(roomCode, userId); + roomService.joinRoom(roomCode, userId); + RoomEntryResponseDto response = roomQueryService.getRoomJoinResponse(roomCode, userId); return ResponseEntity.ok(response); } @@ -86,6 +91,22 @@ public ResponseEntity changeUserRole( @GetMapping("/participants") public ResponseEntity> getRoomParticipants( @RequestParam Long roomId) { - return ResponseEntity.ok(roomService.getRoomParticipants(roomId)); + return ResponseEntity.ok(roomQueryService.getRoomParticipants(roomId)); + } + + @DeleteMapping("/leave/{roomId}") + public ResponseEntity userLeaveRoom( + @RequestHeader(value = "x-user-id") Long userId, + @PathVariable Long roomId){ + roomService.leaveRoom(roomId, userId); + return ResponseEntity.ok("Leave room successfully."); + } + + @DeleteMapping("/delete/{roomId}") + public ResponseEntity deleteRoom( + @RequestHeader(value = "x-user-id") Long userId, + @PathVariable Long roomId){ + roomService.deleteRoom(roomId, userId); + return ResponseEntity.ok("Room deleted successfully"); } } diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/enums/RoomRole.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/enums/RoomRole.java new file mode 100644 index 00000000..b92af3ce --- /dev/null +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/enums/RoomRole.java @@ -0,0 +1,14 @@ +package com.kickzo.main.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum RoomRole { + CREATOR(0), + MANAGER(1), + MEMBER(2); + + private final int value; +} diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/repository/RoomUserRepository.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/repository/RoomUserRepository.java index 3f3712b5..da060391 100644 --- a/src/backend/main-server/main/src/main/java/com/kickzo/main/repository/RoomUserRepository.java +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/repository/RoomUserRepository.java @@ -3,6 +3,7 @@ import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @@ -33,4 +34,8 @@ public interface RoomUserRepository extends JpaRepository @Query(value = "SELECT EXISTS (SELECT 1 FROM room_user ru WHERE ru.room_id = :roomId AND ru.user_id = :userId)", nativeQuery = true) Integer existsByUserIdAndRoomId(@Param("roomId") Long roomId, @Param("userId") Long userId); + + @Modifying + @Query(value = "DELETE FROM room_user ru WHERE ru.room_id = :roomId", nativeQuery = true) + void deleteByRoomId(@Param("roomId") Long roomId); } diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/repository/UserOutRedisRepository.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/repository/UserOutRedisRepository.java index 07ef1803..ebc9e9bd 100644 --- a/src/backend/main-server/main/src/main/java/com/kickzo/main/repository/UserOutRedisRepository.java +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/repository/UserOutRedisRepository.java @@ -19,4 +19,12 @@ public void removeUserFromRoom(Long roomId, Long userId) { String redisKey = "room:" + roomId + ":users"; redisActiveUsersTemplate.opsForSet().remove(redisKey, String.valueOf(userId)); } + + /** + * 특정 방(roomId) 전체 제거 + */ + public void removeRoom(Long roomId) { + String redisKey = "room:" + roomId + ":users"; + redisActiveUsersTemplate.delete(redisKey); + } } diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/service/MainPageService.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/service/MainPageService.java index 39453679..fdd25f31 100644 --- a/src/backend/main-server/main/src/main/java/com/kickzo/main/service/MainPageService.java +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/service/MainPageService.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.kickzo.main.enums.RoomRole; import com.kickzo.main.search.service.SearchService; import com.kickzo.main.dto.data.PlaylistItem; import com.kickzo.main.dto.request.CreateRoomRequestDto; @@ -41,7 +42,6 @@ public class MainPageService { private final SearchService searchService; private static final int MAX_ROOMS_PER_USER = 5; - private static final int ROLE_CREATOR = 0; // 메인 페이지 방 list 제공 @Transactional(readOnly = true) @@ -149,7 +149,7 @@ private Room saveNewRoom(String creatorNickname, CreateRoomRequestDto requestDto private void saveRoomUser(Long roomId, Long userId) { RoomUser roomUser = RoomUser.builder() .id(new RoomUserId(roomId, userId)) - .role(ROLE_CREATOR) // 0: creator 역할 + .role(RoomRole.CREATOR.getValue()) // 0: creator 역할 .joinedAt(LocalDateTime.now()) .build(); diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomQueryService.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomQueryService.java new file mode 100644 index 00000000..60a7ed19 --- /dev/null +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomQueryService.java @@ -0,0 +1,122 @@ +package com.kickzo.main.service; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.kickzo.main.repository.UserEnterRedisRepository; +import com.kickzo.main.dto.data.PlaylistItem; +import com.kickzo.main.dto.response.RoomDetailsDto; +import com.kickzo.main.dto.response.RoomEntryResponseDto; +import com.kickzo.main.dto.response.RoomInfoDto; +import com.kickzo.main.dto.response.UserInfoDto; +import com.kickzo.main.entity.Playlist; +import com.kickzo.main.exception.CustomErrorCode; +import com.kickzo.main.exception.CustomException; +import com.kickzo.main.repository.PlaylistRepository; +import com.kickzo.main.repository.RoomRepository; +import com.kickzo.main.repository.RoomUserRepository; +import com.kickzo.main.repository.UserRepository; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class RoomQueryService { + + private final RoomRepository roomRepository; + private final RoomUserRepository roomUserRepository; + private final PlaylistRepository playlistRepository; + private final UserRepository userRepository; + private final UserEnterRedisRepository userEnterRedisRepository; + + //방에 입장했을 때 방 정보 + 방 소속 유저 정보 + playlist 정보 제공 + public RoomEntryResponseDto getRoomJoinResponse(String roomCode, Long userId){ + int myRole = findUserRole(getRoomId(roomCode), userId); + RoomDetailsDto roomDetails = assembleRoomDetails(roomCode); + return new RoomEntryResponseDto(myRole, roomDetails); + } + + public Integer findUserRole(Long roomId, Long userId) { + return roomUserRepository.findRoleByUserIdAndRoomId(roomId, userId); + } + + public List getRoomParticipants(Long roomId) { + return fetchUserList(roomId); + } + + public Long getRoomId(String roomCode) { + return Optional.ofNullable(roomRepository.findRoomIdByRoomCode(roomCode)) + .orElseThrow(() -> new CustomException(CustomErrorCode.ROOM_NOT_FOUND)); + } + public String getUserProfileImage(Long userId) { + return userRepository.findProfileImageUrlById(userId); + } + + public String getUserNickname(Long userId) { + return userRepository.findNicknameById(userId); + } + + //주어진 역할(Role)과 방 코드를 기반으로 Room의 전체 세부 정보 생성 + private RoomDetailsDto assembleRoomDetails(String roomCode) { + Long roomId = getRoomId(roomCode); + + List userList = fetchUserList(roomId); + List roomInfo = fetchRoomInfo(roomId); + List playlist = fetchPlaylist(roomId); + + return new RoomDetailsDto(userList, roomInfo, playlist); + } + + // Room ID를 기준으로 방에 참여한 유저의 ID, Role, 닉네임, 프로필 이미지 조회 + private List fetchUserList(Long roomId) { + Set onlineUsers = userEnterRedisRepository.getOnlineUsers(roomId); + + List userIdRoles = roomUserRepository.findUsersByRoomId(roomId); + return userIdRoles.stream() + .map(userRole -> { + Long userId = (Long) userRole[0]; + int role = (int) userRole[1]; + String nickname = getUserNickname(userId); + String profileImageUrl = getUserProfileImage(userId); + boolean isJoined = onlineUsers != null && onlineUsers.contains(String.valueOf(userId)); // 온라인 여부 체크 + return new UserInfoDto(userId, role, nickname, profileImageUrl, isJoined); + }) + .collect(Collectors.toList()); + } + + // Room ID로 방의 정보를 조회하고 RoomInfoDto 리스트로 변환 + private List fetchRoomInfo(Long roomId) { + return roomRepository.findRoomById(roomId) + .stream() + .map(room -> RoomInfoDto.builder() + .roomId(room.getId()) + .code(room.getCode()) + .title(room.getTitle()) + .description(room.getDescription()) + .userCount(room.getUserCount()) + .creator(room.getCreator()) + .profileImageUrl(getCreatorProfileImage(room.getCreator())) + .build()) + .collect(Collectors.toList()); + } + + // Room ID를 기반으로 Playlist 정보를 JSON에서 List 형태로 변환 + private List fetchPlaylist(Long roomId) { + return playlistRepository.findByRoomId(roomId) + .map(Playlist::getOrderAsList) // JSON → List 변환 + .orElse(Collections.emptyList()); // Playlist가 없으면 빈 리스트 반환 + } + + private String getCreatorProfileImage(String creatorNickname) { + return userRepository.findProfileImageUrlByNickname(creatorNickname); + } +} diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomService.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomService.java index 03f39e1b..803434aa 100644 --- a/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomService.java +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomService.java @@ -1,62 +1,47 @@ package com.kickzo.main.service; import java.time.LocalDateTime; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.Optional; -import java.util.stream.Collectors; +import java.util.Objects; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.kickzo.main.dto.response.UserInfoDto; +import com.kickzo.main.entity.RoomUser; +import com.kickzo.main.entity.RoomUserId; +import com.kickzo.main.enums.RoomRole; +import com.kickzo.main.repository.RoomUserRepository; import com.kickzo.main.repository.UserEnterRedisRepository; +import com.kickzo.main.repository.UserOutRedisRepository; import com.kickzo.main.search.service.SearchService; -import com.kickzo.main.dto.data.PlaylistItem; import com.kickzo.main.dto.event.RoomUpdateEvent; import com.kickzo.main.dto.request.RoomUpdateRequestDto; -import com.kickzo.main.dto.response.RoomDetailsDto; -import com.kickzo.main.dto.response.RoomEntryResponseDto; -import com.kickzo.main.dto.response.RoomInfoDto; -import com.kickzo.main.dto.response.UserInfoDto; import com.kickzo.main.entity.Room; -import com.kickzo.main.entity.RoomUser; -import com.kickzo.main.entity.RoomUserId; -import com.kickzo.main.entity.Playlist; import com.kickzo.main.exception.CustomErrorCode; import com.kickzo.main.exception.CustomException; -import com.kickzo.main.repository.PlaylistRepository; import com.kickzo.main.repository.RoomRepository; -import com.kickzo.main.repository.RoomUserRepository; -import com.kickzo.main.repository.UserRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j @Service +@Transactional @RequiredArgsConstructor public class RoomService { - - private final RoomRepository roomRepository; - private final RoomUserRepository roomUserRepository; - private final PlaylistRepository playlistRepository; - private final UserRepository userRepository; private final SearchService searchService; private final KafkaProducerService kafkaProducerService; + private final RoomQueryService roomQueryService; + private final RoomRepository roomRepository; + private final RoomUserRepository roomUserRepository; private final UserEnterRedisRepository userEnterRedisRepository; - private static final int ROLE_MEMBER = 2; + private final UserOutRedisRepository userOutRedisRepository; - @Transactional - public RoomEntryResponseDto getRoomJoinResponse(String roomCode, Long userId){ - int myRole = determineUserRole(roomCode, userId); + public void joinRoom(String roomCode, Long userId) { // redis에 roomId와 userId 저장 - userEnterRoom(getRoomId(roomCode), userId); - RoomDetailsDto roomDetails = assembleRoomDetails(roomCode); - return new RoomEntryResponseDto(myRole, roomDetails); + userEnterRoom(roomQueryService.getRoomId(roomCode), userId); } - @Transactional public void updateRoomInfo(RoomUpdateRequestDto updateRequestDto) { Long roomId = updateRequestDto.getRoomId(); Room room = roomRepository.findById(roomId) @@ -90,118 +75,46 @@ public void updateRoomInfo(RoomUpdateRequestDto updateRequestDto) { kafkaProducerService.sendRoomUpdateMessage(event); } - @Transactional(readOnly = true) - public List getRoomParticipants(Long roomId) { - return fetchUserList(roomId); + // 방을 만든 사람이 나간다면,,? + public void leaveRoom(Long roomId, Long userId) { + Room room = roomRepository.findById(roomId) + .orElseThrow(() -> new CustomException(CustomErrorCode.ROOM_NOT_FOUND)); + room.decrementUserCount(); + roomRepository.save(room); + RoomUserId id = new RoomUserId(roomId, userId); + roomUserRepository.deleteById(id); + userOutRedisRepository.removeUserFromRoom(roomId, userId); } - /** - * roomCode에 따른 방의 정보와 유저 list 전달 - * 1. 사용자 역할(Role) 확인, 비로그인 유저인 경우 기본 Role(99) 반환 : determineUserRole - * 2. 사용자 역할(Role) 조회, 존재하지 않으면 새 사용자로 등록 후 기본 Role(ROLE_MEMBER) 반환 : findOrAssignUserRole - * 3. 주어진 역할(Role)과 방 코드를 기반으로 Room의 전체 세부 정보 생성 : assembleRoomDetails - * 4. Room ID를 기준으로 방에 참여한 유저의 ID, Role, 닉네임, 프로필 이미지 조회 : fetchUserList - * 5. Room ID로 방의 정보를 조회하고 RoomInfoDto 리스트로 변환 : fetchRoomInfo - * 6. Room ID를 기반으로 Playlist 정보를 JSON에서 List 형태로 변환 : fetchPlaylist - * 7. Room Code로 Room ID 조회, 존재하지 않으면 예외 발생 : getRoomId - * 8. 방 생성자의 닉네임을 기반으로 프로필 이미지 URL 조회, 없으면 기본 이미지 반환 : getCreatorProfileImage - * 9. 유저 ID를 기반으로 프로필 이미지 URL 조회, 없으면 기본 이미지 반환 : getUserProfileImage - * 10. Room ID를 기준으로 방의 유저 수를 1 증가시키고, 변경된 정보 저장 : saveUserCount - * 11. RoomUser 엔티티를 생성하여 새로운 사용자를 방에 추가하고 기본 Role(ROLE_MEMBER)로 저장 : saveNewRoomUser - * 12. Room에 join한 유저를 Redis에 저장하여 실시간 방 사용자 트래킹 : userEnterRoom - */ - private int determineUserRole(String roomCode, Long userId) { - if (userId == null) { - return 99; // 비로그인 유저는 role = 99 + public void deleteRoom(Long roomId, Long userId) { + // 삭제 권한 확인 + Integer role = roomUserRepository.findRoleByUserIdAndRoomId(roomId, userId); + if (role == null || !Objects.equals(role, RoomRole.CREATOR.getValue())){ + throw new CustomException(CustomErrorCode.INVALID_ACCESS_ROLE); } - Long roomId = getRoomId(roomCode); - return findOrAssignUserRole(roomId, userId); + roomRepository.deleteById(roomId); + roomUserRepository.deleteByRoomId(roomId); + userOutRedisRepository.removeRoom(roomId); } - private int findOrAssignUserRole(Long roomId, Long userId) { - // Step 1: 해당 방에서 유저의 역할(Role)을 찾음 - Integer role = roomUserRepository.findRoleByUserIdAndRoomId(roomId, userId); + // 새로 들어온 유저 db에 저장 및 Room에 join한 유저를 Redis에 저장하여 실시간 방 사용자 트래킹 + private void userEnterRoom(Long roomId, Long userId) { + assignUserRole(roomId, userId); + userEnterRedisRepository.addUserToRoom(roomId, userId); + sendRoomUserInfoToKafka(roomId, userId); + } + + // 현재 유저가 해당 방에 소속되어있는 지 확인 후 저장 + private void assignUserRole(Long roomId, Long userId) { + Integer role = roomQueryService.findUserRole(roomId, userId); if (role != null) { - // Step 2: 역할(Role)이 존재하면 반환 - return role; + return; } - // Step 3: 역할(Role)이 존재하지 않으면 새 사용자 추가 saveUserCount(roomId); saveNewRoomUser(roomId, userId); - //sendRoomUserInfoToKafka(roomId, userId); - return ROLE_MEMBER; - } - - private void sendRoomUserInfoToKafka(Long roomId, Long userId) { - String nickName = getUserNickname(userId); - String profileImageUrl = getUserProfileImage(userId); - kafkaProducerService.sendRoomUserInfo(roomId, new UserInfoDto(userId, ROLE_MEMBER, nickName, profileImageUrl, true)); - } - - private RoomDetailsDto assembleRoomDetails(String roomCode) { - Long roomId = getRoomId(roomCode); - - List userList = fetchUserList(roomId); - List roomInfo = fetchRoomInfo(roomId); - List playlist = fetchPlaylist(roomId); - - return new RoomDetailsDto(userList, roomInfo, playlist); - } - - private List fetchUserList(Long roomId) { - Set onlineUsers = userEnterRedisRepository.getOnlineUsers(roomId); - - List userIdRoles = roomUserRepository.findUsersByRoomId(roomId); - return userIdRoles.stream() - .map(userRole -> { - Long userId = (Long) userRole[0]; - int role = (int) userRole[1]; - String nickname = getUserNickname(userId); - String profileImageUrl = getUserProfileImage(userId); - boolean isJoined = onlineUsers != null && onlineUsers.contains(String.valueOf(userId)); // 온라인 여부 체크 - return new UserInfoDto(userId, role, nickname, profileImageUrl, isJoined); - }) - .collect(Collectors.toList()); - } - - private List fetchRoomInfo(Long roomId) { - return roomRepository.findRoomById(roomId) - .stream() - .map(room -> RoomInfoDto.builder() - .roomId(room.getId()) - .code(room.getCode()) - .title(room.getTitle()) - .description(room.getDescription()) - .userCount(room.getUserCount()) - .creator(room.getCreator()) - .profileImageUrl(getCreatorProfileImage(room.getCreator())) - .build()) - .collect(Collectors.toList()); - } - - private List fetchPlaylist(Long roomId) { - return playlistRepository.findByRoomId(roomId) - .map(Playlist::getOrderAsList) // JSON → List 변환 - .orElse(Collections.emptyList()); // Playlist가 없으면 빈 리스트 반환 - } - - private Long getRoomId(String roomCode) { - return Optional.ofNullable(roomRepository.findRoomIdByRoomCode(roomCode)) - .orElseThrow(() -> new CustomException(CustomErrorCode.ROOM_NOT_FOUND)); - } - - private String getCreatorProfileImage(String creatorNickname) { - return userRepository.findProfileImageUrlByNickname(creatorNickname); - } - - private String getUserProfileImage(Long userId) { - return userRepository.findProfileImageUrlById(userId); - } - - private String getUserNickname(Long userId) { - return userRepository.findNicknameById(userId); } + // Room ID를 기준으로 방의 유저 수를 1 증가시키고, 변경된 정보 저장 private void saveUserCount(Long roomId){ Room room = roomRepository.findById(roomId) .orElseThrow(() -> new CustomException(CustomErrorCode.ROOM_NOT_FOUND)); @@ -209,17 +122,20 @@ private void saveUserCount(Long roomId){ roomRepository.save(room); } + // RoomUser 엔티티를 생성하여 새로운 사용자를 방에 추가하고 기본 Role(ROLE_MEMBER)로 저장 private void saveNewRoomUser(Long roomId, Long userId) { RoomUser roomUser = RoomUser.builder() .id(new RoomUserId(roomId, userId)) - .role(ROLE_MEMBER) // 2: member 역할 + .role(RoomRole.MEMBER.getValue()) // 2: member 역할 .joinedAt(LocalDateTime.now()) .build(); roomUserRepository.save(roomUser); } - private void userEnterRoom(Long roomId, Long userId) { - userEnterRedisRepository.addUserToRoom(roomId, userId); - sendRoomUserInfoToKafka(roomId, userId); + // 새로운 유저가 들어왔음을 Kafka로 전송 + private void sendRoomUserInfoToKafka(Long roomId, Long userId) { + String nickName = roomQueryService.getUserNickname(userId); + String profileImageUrl = roomQueryService.getUserProfileImage(userId); + kafkaProducerService.sendRoomUserInfo(roomId, new UserInfoDto(userId, RoomRole.MEMBER.getValue(), nickName, profileImageUrl, true)); } } diff --git a/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomUserService.java b/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomUserService.java index 6c57eeb6..7dd4d7ff 100644 --- a/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomUserService.java +++ b/src/backend/main-server/main/src/main/java/com/kickzo/main/service/RoomUserService.java @@ -8,6 +8,7 @@ import com.kickzo.main.dto.request.RoleChangeRequestDto; import com.kickzo.main.entity.RoomUser; import com.kickzo.main.entity.RoomUserId; +import com.kickzo.main.enums.RoomRole; import com.kickzo.main.exception.CustomErrorCode; import com.kickzo.main.exception.CustomException; import com.kickzo.main.repository.RoomUserRepository; @@ -21,8 +22,6 @@ public class RoomUserService { private final RoomUserRepository roomUserRepository; private final KafkaProducerService kafkaProducerService; - private static final int ROLE_MEMBER = 2; - @Transactional public void changeUserRole(Long userId, RoleChangeRequestDto roleChangeRequestDto) { Long roomId = roleChangeRequestDto.getRoomId(); @@ -50,7 +49,7 @@ public void checkAccessRole(Long userId, Long roomId){ throw new CustomException(CustomErrorCode.ROOM_USER_NOT_FOUND); } - if (requester.get().getRole() == ROLE_MEMBER) { + if (requester.get().getRole() == RoomRole.MEMBER.getValue()) { throw new CustomException(CustomErrorCode.INVALID_ACCESS_ROLE); } }