diff --git a/be/build.gradle b/be/build.gradle index 9d01f983..b4b4a7ff 100644 --- a/be/build.gradle +++ b/be/build.gradle @@ -52,6 +52,14 @@ dependencies { // fcm implementation 'com.google.firebase:firebase-admin:9.2.0' + + // websocket + implementation 'org.springframework.boot:spring-boot-starter-websocket' + implementation 'org.webjars:stomp-websocket:2.3.3-1' + implementation 'org.webjars:sockjs-client:1.1.2' + + // redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' } tasks.named('bootBuildImage') { diff --git a/be/src/main/java/yeonba/be/chatting/controller/ChattingController.java b/be/src/main/java/yeonba/be/chatting/controller/ChatController.java similarity index 58% rename from be/src/main/java/yeonba/be/chatting/controller/ChattingController.java rename to be/src/main/java/yeonba/be/chatting/controller/ChatController.java index cb15645e..4d4ffeec 100644 --- a/be/src/main/java/yeonba/be/chatting/controller/ChattingController.java +++ b/be/src/main/java/yeonba/be/chatting/controller/ChatController.java @@ -5,27 +5,63 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; +import java.util.Set; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; import org.springframework.http.ResponseEntity; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.ResponseBody; +import yeonba.be.chatting.dto.request.ChatPublishRequest; +import yeonba.be.chatting.dto.response.ChatMessageResponse; import yeonba.be.chatting.dto.response.ChatRoomResponse; import yeonba.be.chatting.service.ChatService; import yeonba.be.util.CustomResponse; @Tag(name = "Chatting", description = "채팅 API") -@RestController +@Slf4j +@Controller @RequiredArgsConstructor -public class ChattingController { +public class ChatController { private final ChatService chatService; - @Operation(summary = "채팅 목록 조회", description = "자신이 참여 중인 채팅 목록을 조회할 수 있습니다.") + @MessageMapping("/chat") + public void chat(ChatPublishRequest request) { + + log.info("chatting test log {}", request.getContent()); + + chatService.publish(request); + } + + @Operation(summary = "채팅 메시지 목록 조회", description = "특정 채팅방의 메시지 목록을 조회할 수 있습니다.") + @ApiResponse(responseCode = "200", description = "채팅 메시지 목록 조회 성공") + @ResponseBody + @GetMapping("/chat-rooms/{roomId}/messages") + public ResponseEntity>> getChatMessages( + @RequestAttribute("userId") long userId, + @Parameter(description = "채팅방 ID", example = "1") + @PathVariable long roomId) { + + List response = chatService.getChatMessages(userId, roomId); + + return ResponseEntity + .ok() + .body(new CustomResponse<>(response)); + } + + @Operation(summary = "채팅방 목록 조회", description = "자신이 참여 중인 채팅 목록을 조회할 수 있습니다.") @ApiResponse(responseCode = "200", description = "참여 중인 채팅 목록 조회 성공") - @GetMapping("/chattings") + @ResponseBody + @GetMapping("/chat-rooms") public ResponseEntity>> getChatRooms( @RequestAttribute("userId") long userId) { @@ -38,6 +74,7 @@ public ResponseEntity>> getChatRooms( @Operation(summary = "채팅 요청", description = "다른 사용자에게 채팅을 요청할 수 있습니다.") @ApiResponse(responseCode = "200", description = "채팅 요청 정상 처리") + @ResponseBody @PostMapping("/users/{partnerId}/chat") public ResponseEntity> requestChat( @RequestAttribute("userId") long userId, @@ -53,6 +90,7 @@ public ResponseEntity> requestChat( @Operation(summary = "채팅 요청 수락", description = "요청받은 채팅을 수락할 수 있습니다.") @ApiResponse(responseCode = "200", description = "채팅 요청 수락 정상 처리") + @ResponseBody @PostMapping("/notifications/{notificationId}/chat") public ResponseEntity> acceptRequestedChat( @RequestAttribute("userId") long userId, diff --git a/be/src/main/java/yeonba/be/chatting/dto/request/ChatPublishRequest.java b/be/src/main/java/yeonba/be/chatting/dto/request/ChatPublishRequest.java new file mode 100644 index 00000000..ade1c49e --- /dev/null +++ b/be/src/main/java/yeonba/be/chatting/dto/request/ChatPublishRequest.java @@ -0,0 +1,15 @@ +package yeonba.be.chatting.dto.request; + +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Getter; + +@Getter +public class ChatPublishRequest implements Serializable { + + private long roomId; + private long userId; + private String userName; + private String content; + private LocalDateTime sentAt; +} diff --git a/be/src/main/java/yeonba/be/chatting/dto/request/ChatSubscribeResponse.java b/be/src/main/java/yeonba/be/chatting/dto/request/ChatSubscribeResponse.java new file mode 100644 index 00000000..6e734bd4 --- /dev/null +++ b/be/src/main/java/yeonba/be/chatting/dto/request/ChatSubscribeResponse.java @@ -0,0 +1,15 @@ +package yeonba.be.chatting.dto.request; + +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Getter; + +@Getter +public class ChatSubscribeResponse implements Serializable { + + private long roomId; + private long userId; + private String userName; + private String content; + private LocalDateTime sentAt; +} diff --git a/be/src/main/java/yeonba/be/chatting/dto/request/ChattingSendMessageRequest.java b/be/src/main/java/yeonba/be/chatting/dto/request/ChattingSendMessageRequest.java deleted file mode 100644 index 56fc2c85..00000000 --- a/be/src/main/java/yeonba/be/chatting/dto/request/ChattingSendMessageRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package yeonba.be.chatting.dto.request; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class ChattingSendMessageRequest { - - @Schema( - type = "string", - description = "메시지 내용", - example = "밥 먹었어?" - ) - private String content; -} diff --git a/be/src/main/java/yeonba/be/chatting/dto/response/ChatMessageResponse.java b/be/src/main/java/yeonba/be/chatting/dto/response/ChatMessageResponse.java new file mode 100644 index 00000000..10a7b0d1 --- /dev/null +++ b/be/src/main/java/yeonba/be/chatting/dto/response/ChatMessageResponse.java @@ -0,0 +1,15 @@ +package yeonba.be.chatting.dto.response; + +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ChatMessageResponse { + + private long userId; + private String userName; + private String content; + private LocalDateTime sentAt; +} diff --git a/be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java b/be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java index 33ba4dfb..3f4a2e7a 100644 --- a/be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java +++ b/be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java @@ -53,12 +53,13 @@ public class ChatMessage { private LocalDateTime deletedAt; - public ChatMessage(ChatRoom chatRoom, User sender, User receiver, String content) { + public ChatMessage(ChatRoom chatRoom, User sender, User receiver, String content, LocalDateTime sentAt) { this.chatRoom = chatRoom; this.sender = sender; this.receiver = receiver; this.content = content; + this.sentAt = sentAt; this.read = false; } } diff --git a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageCommand.java b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageCommand.java index c7a9e5ae..f9137e37 100644 --- a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageCommand.java +++ b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageCommand.java @@ -10,7 +10,7 @@ public class ChatMessageCommand { private final ChatMessageRepository chatMessageRepository; - public ChatMessage createChatMessage(ChatMessage message) { + public ChatMessage save(ChatMessage message) { return chatMessageRepository.save(message); } diff --git a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageQuery.java b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageQuery.java index 1ea9beb4..ac9ddaf7 100644 --- a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageQuery.java +++ b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageQuery.java @@ -1,8 +1,10 @@ package yeonba.be.chatting.repository.chatmessage; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import yeonba.be.chatting.entity.ChatMessage; +import yeonba.be.chatting.entity.ChatRoom; @Component @RequiredArgsConstructor @@ -19,4 +21,9 @@ public int countUnreadMessagesByChatRoomId(long chatRoomId) { return chatMessageRepository.countByChatRoomIdAndReadIsFalse(chatRoomId); } + + public List findAllByChatRoom(ChatRoom chatRoom) { + + return chatMessageRepository.findAllByChatRoomOrderBySentAtDesc(chatRoom); + } } diff --git a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageRepository.java b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageRepository.java index 0205b255..4bcc60a3 100644 --- a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageRepository.java +++ b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageRepository.java @@ -1,8 +1,10 @@ package yeonba.be.chatting.repository.chatmessage; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import yeonba.be.chatting.entity.ChatMessage; +import yeonba.be.chatting.entity.ChatRoom; @Repository public interface ChatMessageRepository extends JpaRepository { @@ -10,4 +12,6 @@ public interface ChatMessageRepository extends JpaRepository ChatMessage findFirstByChatRoomIdOrderBySentAtDesc(long chatRoomId); int countByChatRoomIdAndReadIsFalse(long chatRoomId); + + List findAllByChatRoomOrderBySentAtDesc(ChatRoom chatRoom); } diff --git a/be/src/main/java/yeonba/be/chatting/repository/chatroom/ChatRoomQuery.java b/be/src/main/java/yeonba/be/chatting/repository/chatroom/ChatRoomQuery.java index 01915f92..681b0339 100644 --- a/be/src/main/java/yeonba/be/chatting/repository/chatroom/ChatRoomQuery.java +++ b/be/src/main/java/yeonba/be/chatting/repository/chatroom/ChatRoomQuery.java @@ -15,6 +15,12 @@ public class ChatRoomQuery { private final ChatRoomRepository chatRoomRepository; + public ChatRoom findById(long id) { + + return chatRoomRepository.findById(id) + .orElseThrow(() -> new GeneralException(NOT_FOUND_CHAT_ROOM)); + } + public List findAllBy(User user) { return chatRoomRepository.findAllByUserAndActiveIsTrue(user); diff --git a/be/src/main/java/yeonba/be/chatting/service/ChatService.java b/be/src/main/java/yeonba/be/chatting/service/ChatService.java index 078d52fc..f56ad3f9 100644 --- a/be/src/main/java/yeonba/be/chatting/service/ChatService.java +++ b/be/src/main/java/yeonba/be/chatting/service/ChatService.java @@ -4,9 +4,14 @@ import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import yeonba.be.chatting.dto.request.ChatPublishRequest; +import yeonba.be.chatting.dto.response.ChatMessageResponse; import yeonba.be.chatting.dto.response.ChatRoomResponse; import yeonba.be.chatting.entity.ChatMessage; import yeonba.be.chatting.entity.ChatRoom; @@ -14,7 +19,9 @@ import yeonba.be.chatting.repository.chatmessage.ChatMessageQuery; import yeonba.be.chatting.repository.chatroom.ChatRoomCommand; import yeonba.be.chatting.repository.chatroom.ChatRoomQuery; +import yeonba.be.chatting.repository.chatroom.ChatRoomRepository; import yeonba.be.exception.BlockException; +import yeonba.be.exception.ChatException; import yeonba.be.exception.GeneralException; import yeonba.be.exception.NotificationException; import yeonba.be.notification.entity.Notification; @@ -26,6 +33,7 @@ import yeonba.be.user.repository.block.BlockQuery; import yeonba.be.user.repository.user.UserQuery; +@Slf4j @Service @RequiredArgsConstructor public class ChatService { @@ -36,9 +44,47 @@ public class ChatService { private final ChatMessageQuery chatMessageQuery; private final UserQuery userQuery; private final BlockQuery blockQuery; - private final NotificationQuery notificationQuey; + private final NotificationQuery notificationQuery; private final ApplicationEventPublisher eventPublisher; + private final RedisChattingPublisher redisChattingPublisher; + private final RedisChattingSubscriber adapter; + private final RedisMessageListenerContainer container; + + @Transactional + public void publish(ChatPublishRequest request) { + + ChatRoom chatRoom = chatRoomQuery.findById(request.getRoomId()); + User sender = userQuery.findById(request.getUserId()); + User receiver = chatRoom.getSender().equals(sender) ? chatRoom.getReceiver() + : chatRoom.getSender(); + + // TODO: 메시지 Pub/Sub과 메시지 저장 로직 비동기 처리(id, user 등 request, response 변경 가능) + redisChattingPublisher.publish(new ChannelTopic(String.valueOf(request.getRoomId())), + request); + chatMessageCommand.save( + new ChatMessage(chatRoom, sender, receiver, request.getContent(), request.getSentAt())); + } + + @Transactional(readOnly = true) + public List getChatMessages(long userId, long roomId) { + + User user = userQuery.findById(userId); + + ChatRoom chatRoom = chatRoomQuery.findById(roomId); + + if (!user.equals(chatRoom.getSender()) && !user.equals(chatRoom.getReceiver())) { + throw new GeneralException(ChatException.NOT_YOUR_CHAT_ROOM); + } + + List chatMessages = chatMessageQuery.findAllByChatRoom(chatRoom); + + return chatMessages.stream() + .map(chatMessage -> new ChatMessageResponse(chatMessage.getSender().getId(), + chatMessage.getSender().getNickname(), + chatMessage.getContent(), chatMessage.getSentAt())) + .toList(); + } @Transactional(readOnly = true) public List getChatRooms(long userId) { @@ -89,9 +135,10 @@ public void requestChat(long senderId, long receiverId) { eventPublisher.publishEvent(notificationSendEvent); } + @Transactional public void acceptRequestedChat(long userId, long notificationId) { - Notification notification = notificationQuey.findById(notificationId); + Notification notification = notificationQuery.findById(notificationId); // 채팅 요청 알림인지 검증 if (!notification.getType().isChattingRequest()) { @@ -105,15 +152,22 @@ public void acceptRequestedChat(long userId, long notificationId) { // 본인에게 온 채팅 요청인지 검증 if (receiver.equals(userQuery.findById(userId))) { - throw new GeneralException(NotificationException.NOT_YOUR_CHATTING_REQUEST_NOTIFICATION); + throw new GeneralException( + NotificationException.NOT_YOUR_CHATTING_REQUEST_NOTIFICATION); } // 채팅방 활성화 ChatRoom chatRoom = chatRoomQuery.findBy(sender, receiver); chatRoom.activeRoom(); - String activeRoom = "채팅방이 활성화되었습니다."; - chatMessageCommand.createChatMessage(new ChatMessage(chatRoom, sender, receiver, activeRoom)); + String activeRoom = "채팅방이 생성되었습니다."; + + chatMessageCommand.save( + new ChatMessage(chatRoom, sender, receiver, activeRoom, LocalDateTime.now())); + + // 메시지 수신을 위한 Redis Pub/Sub 구독 + container.addMessageListener(adapter, new ChannelTopic(String.valueOf(chatRoom.getId()))); + log.info("channel topic 생성 {}", chatRoom.getId()); NotificationSendEvent notificationSendEvent = new NotificationSendEvent( NotificationType.CHATTING_REQUEST_ACCEPTED, receiver, sender, diff --git a/be/src/main/java/yeonba/be/chatting/service/RedisChattingPublisher.java b/be/src/main/java/yeonba/be/chatting/service/RedisChattingPublisher.java new file mode 100644 index 00000000..60a525c2 --- /dev/null +++ b/be/src/main/java/yeonba/be/chatting/service/RedisChattingPublisher.java @@ -0,0 +1,19 @@ +package yeonba.be.chatting.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.stereotype.Service; +import yeonba.be.chatting.dto.request.ChatPublishRequest; + +@Service +@RequiredArgsConstructor +public class RedisChattingPublisher { + + private final RedisTemplate redisTemplate; + + public void publish(ChannelTopic topic, ChatPublishRequest request) { + + redisTemplate.convertAndSend(topic.getTopic(), request); + } +} diff --git a/be/src/main/java/yeonba/be/chatting/service/RedisChattingSubscriber.java b/be/src/main/java/yeonba/be/chatting/service/RedisChattingSubscriber.java new file mode 100644 index 00000000..515159ff --- /dev/null +++ b/be/src/main/java/yeonba/be/chatting/service/RedisChattingSubscriber.java @@ -0,0 +1,42 @@ +package yeonba.be.chatting.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.messaging.simp.SimpMessageSendingOperations; +import org.springframework.stereotype.Service; +import yeonba.be.chatting.dto.request.ChatSubscribeResponse; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RedisChattingSubscriber implements MessageListener { + + private final ObjectMapper objectMapper; + private final RedisTemplate redisTemplate; + private final SimpMessageSendingOperations messagingTemplate; + + @Override + public void onMessage(Message message, byte[] pattern) { + + try { + + // redis에서 발행된 데이터를 받아 deserialize + String publishedMessage = (String) redisTemplate.getStringSerializer() + .deserialize(message.getBody()); + + // ChatMessage 객채로 맵핑 + ChatSubscribeResponse response = objectMapper.readValue(publishedMessage, ChatSubscribeResponse.class); + + log.info("Chatting message received: {}", response.getContent()); + + // Websocket 구독자에게 채팅 메시지 Send + messagingTemplate.convertAndSend("/chat/sub/room/" + response.getRoomId(), response); + } catch (Exception e) { + log.error(e.getMessage()); + } + } +} diff --git a/be/src/main/java/yeonba/be/config/RedisConfig.java b/be/src/main/java/yeonba/be/config/RedisConfig.java new file mode 100644 index 00000000..e71f7708 --- /dev/null +++ b/be/src/main/java/yeonba/be/config/RedisConfig.java @@ -0,0 +1,61 @@ +package yeonba.be.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import yeonba.be.chatting.service.RedisChattingSubscriber; + +@Configuration +@RequiredArgsConstructor +public class RedisConfig { + + private final ObjectMapper objectMapper; + + /** + * redis pub/sub 메시지 처리 listener 설정 + */ + @Bean + public RedisMessageListenerContainer redisMessageListenerContainer( + RedisConnectionFactory connectionFactory) { + + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + container.setConnectionFactory(connectionFactory); + return container; + } + + /** + * 어플리케이션에서 사용할 redisTemplate 설정 + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(connectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper)); + return redisTemplate; + } + + @Bean + public RedisTemplate stringIntegerRedisTemplate(RedisConnectionFactory connectionFactory) { + + var redisTemplate = new RedisTemplate(); + redisTemplate.setConnectionFactory(connectionFactory); + + return redisTemplate; + } + + @Bean + public MessageListenerAdapter messageListenerAdapter(RedisChattingSubscriber subscriber) { + + return new MessageListenerAdapter(subscriber, "onMessage"); + } +} diff --git a/be/src/main/java/yeonba/be/config/WebSocketConfig.java b/be/src/main/java/yeonba/be/config/WebSocketConfig.java new file mode 100644 index 00000000..334d91bc --- /dev/null +++ b/be/src/main/java/yeonba/be/config/WebSocketConfig.java @@ -0,0 +1,28 @@ +package yeonba.be.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; + +@Configuration +@EnableWebSocket +@EnableWebSocketMessageBroker +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + + config.enableSimpleBroker("/chat/sub"); + config.setApplicationDestinationPrefixes("/chat/pub"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + + registry.addEndpoint("/chat") + .withSockJS(); + } +} diff --git a/be/src/main/java/yeonba/be/exception/ChatException.java b/be/src/main/java/yeonba/be/exception/ChatException.java index f1df029b..3bb5783b 100644 --- a/be/src/main/java/yeonba/be/exception/ChatException.java +++ b/be/src/main/java/yeonba/be/exception/ChatException.java @@ -4,6 +4,10 @@ public enum ChatException implements BaseException { + NOT_YOUR_CHAT_ROOM( + HttpStatus.BAD_REQUEST, + "해당 채팅방에 대한 권한이 없습니다."), + NOT_FOUND_CHAT_ROOM( HttpStatus.BAD_REQUEST, "요청된 채팅방이 없습니다."); diff --git a/be/src/main/resources/application.yml b/be/src/main/resources/application.yml index e8db33a9..e048178f 100644 --- a/be/src/main/resources/application.yml +++ b/be/src/main/resources/application.yml @@ -12,4 +12,11 @@ spring: properties: hibernate: show_sql: false - format_sql: false \ No newline at end of file + format_sql: false + + data: + redis: + host: ${REDIS_HOST} + port: ${REDIS_PORT} + password: ${REDIS_PASSWORD} + timeout: 60000