-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IDLE-476] 웹소켓, Redis pub/sub을 이용한 채팅 전송 기능 (#217)
* [IDLE-476] 웹소켓 dependency 추가 * [IDLE-476] 웹소켓, Redis pub/sub을 이용한 채팅 전송 기능 * [IDLE-476] 불필요 클래스 제거 * [IDLE-476] 채팅 메세지 생성 책임을 하위 도메인에서 생성하도록 수정 * [IDLE-476] hash 역직렬화 시 필요한 처리를 Serializer 설정 추가 * [IDLE-476] json 역직렬화 시, 특수문자 허용 * [IDLE-476] websocket stomp 엔드포인트 노출 설정 변경 * [IDLE-476] 채팅 메세지 길이 정책 적용
- Loading branch information
Showing
14 changed files
with
275 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
idle-application/src/main/kotlin/com/swm/idle/application/chat/domain/ChatMessageService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.swm.idle.application.chat.domain | ||
|
||
import com.swm.idle.domain.chat.entity.jpa.ChatMessage | ||
import com.swm.idle.domain.chat.enums.SenderType | ||
import org.springframework.stereotype.Service | ||
import java.util.* | ||
|
||
@Service | ||
class ChatMessageService { | ||
|
||
fun createByUser(roomId: UUID, userId: UUID, contents: List<ChatMessage.Content>): ChatMessage { | ||
return ChatMessage( | ||
roomId = roomId, | ||
senderId = userId, | ||
senderType = SenderType.USER, | ||
contents = contents | ||
) | ||
} | ||
|
||
} |
33 changes: 33 additions & 0 deletions
33
...lication/src/main/kotlin/com/swm/idle/application/chat/facade/ChatMessageFacadeService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.swm.idle.application.chat.facade | ||
|
||
import com.swm.idle.application.chat.domain.ChatMessageService | ||
import com.swm.idle.domain.chat.entity.jpa.ChatMessage | ||
import com.swm.idle.domain.chat.event.ChatMessageRedisPublisher | ||
import org.springframework.stereotype.Service | ||
import java.util.* | ||
|
||
@Service | ||
class ChatMessageFacadeService( | ||
private val chatMessageRedisPublisher: ChatMessageRedisPublisher, | ||
private val chatMessageService: ChatMessageService, | ||
) { | ||
|
||
fun sendTextMessage( | ||
roomId: UUID, | ||
senderId: UUID, | ||
contents: List<ChatMessage.Content>, | ||
) { | ||
chatMessageService.createByUser( | ||
roomId = roomId, | ||
userId = senderId, | ||
contents = contents, | ||
).also { | ||
chatMessageRedisPublisher.publish(it) | ||
} | ||
} | ||
|
||
fun saveMessage(chatMessage: ChatMessage) { | ||
// TODO : 메세지 저장 로직 구현 | ||
} | ||
|
||
} |
7 changes: 7 additions & 0 deletions
7
...application/src/main/kotlin/com/swm/idle/application/chat/facade/ChatRoomFacadeService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.swm.idle.application.chat.facade | ||
|
||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class ChatRoomFacadeService { | ||
} |
41 changes: 41 additions & 0 deletions
41
idle-domain/src/main/kotlin/com/swm/idle/domain/chat/config/ChatMessageRedisConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package com.swm.idle.domain.chat.config | ||
|
||
import com.swm.idle.domain.chat.event.ChatMessageRedisConsumer | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.data.redis.connection.RedisConnectionFactory | ||
import org.springframework.data.redis.listener.ChannelTopic | ||
import org.springframework.data.redis.listener.RedisMessageListenerContainer | ||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter | ||
|
||
@Configuration | ||
class ChatMessageRedisConfig { | ||
|
||
@Bean | ||
fun redisListenerContainer( | ||
connectionFactory: RedisConnectionFactory, | ||
messageListenerAdapter: MessageListenerAdapter, | ||
): RedisMessageListenerContainer { | ||
val container = RedisMessageListenerContainer() | ||
container.setConnectionFactory(connectionFactory) | ||
container.addMessageListener(messageListenerAdapter, chatChannelTopic()) | ||
return container | ||
} | ||
|
||
@Bean | ||
fun messageListenerAdapter(chatMessageRedisConsumer: ChatMessageRedisConsumer): MessageListenerAdapter { | ||
return MessageListenerAdapter(chatMessageRedisConsumer) | ||
} | ||
|
||
@Bean | ||
fun chatChannelTopic(): ChannelTopic { | ||
return ChannelTopic(CHAT_MESSAGE) | ||
} | ||
|
||
companion object { | ||
|
||
const val CHAT_MESSAGE = "chat_message" | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
idle-domain/src/main/kotlin/com/swm/idle/domain/chat/event/ChatMessageRedisConsumer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.swm.idle.domain.chat.event | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import com.fasterxml.jackson.module.kotlin.readValue | ||
import com.swm.idle.domain.chat.entity.jpa.ChatMessage | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.springframework.context.ApplicationEventPublisher | ||
import org.springframework.data.redis.connection.Message | ||
import org.springframework.data.redis.connection.MessageListener | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class ChatMessageRedisConsumer( | ||
private val applicationEventPublisher: ApplicationEventPublisher, | ||
private val objectMapper: ObjectMapper, | ||
) : MessageListener { | ||
|
||
val logger = KotlinLogging.logger {} | ||
|
||
override fun onMessage( | ||
message: Message, | ||
pattern: ByteArray?, | ||
) { | ||
logger.debug { "Received message: $message" } | ||
|
||
objectMapper.readValue<ChatMessage>(message.body) | ||
.also { applicationEventPublisher.publishEvent(it) } | ||
} | ||
|
||
} |
22 changes: 22 additions & 0 deletions
22
idle-domain/src/main/kotlin/com/swm/idle/domain/chat/event/ChatMessageRedisPublisher.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.swm.idle.domain.chat.event | ||
|
||
import com.swm.idle.domain.chat.config.ChatMessageRedisConfig | ||
import com.swm.idle.domain.chat.entity.jpa.ChatMessage | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.springframework.data.redis.core.RedisTemplate | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class ChatMessageRedisPublisher( | ||
private val redisTemplate: RedisTemplate<String, Any>, | ||
) { | ||
|
||
private val logger = KotlinLogging.logger {} | ||
|
||
fun publish(chatMessage: ChatMessage) { | ||
logger.info { "RedisPublisher 도달 " } | ||
|
||
redisTemplate.convertAndSend(ChatMessageRedisConfig.CHAT_MESSAGE, chatMessage) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
idle-presentation/src/main/kotlin/com/swm/idle/presentation/chat/config/WebSocketConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.swm.idle.presentation.chat.config | ||
|
||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.messaging.simp.config.MessageBrokerRegistry | ||
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 | ||
@EnableWebSocketMessageBroker | ||
class WebSocketConfig : WebSocketMessageBrokerConfigurer { | ||
|
||
override fun registerStompEndpoints(registry: StompEndpointRegistry) { | ||
registry | ||
.addEndpoint("/websocket") | ||
.setAllowedOriginPatterns("*") | ||
} | ||
|
||
override fun configureMessageBroker(registry: MessageBrokerRegistry) { | ||
registry.enableSimpleBroker("/topic") | ||
registry.setApplicationDestinationPrefixes("/app") | ||
} | ||
|
||
} |
30 changes: 30 additions & 0 deletions
30
...sentation/src/main/kotlin/com/swm/idle/presentation/chat/controller/ChatMessageHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.swm.idle.presentation.chat.controller | ||
|
||
import com.swm.idle.application.chat.facade.ChatMessageFacadeService | ||
import com.swm.idle.domain.chat.entity.jpa.ChatMessage | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.springframework.context.event.EventListener | ||
import org.springframework.messaging.simp.SimpMessageSendingOperations | ||
import org.springframework.stereotype.Controller | ||
|
||
@Controller | ||
class ChatMessageHandler( | ||
private val simpMessageSendingOperations: SimpMessageSendingOperations, | ||
private val chatMessageFacadeService: ChatMessageFacadeService, | ||
) { | ||
|
||
private val logger = KotlinLogging.logger { } | ||
|
||
@EventListener | ||
fun handleChatMessage(chatMessage: ChatMessage) { | ||
logger.info { "Handler까지 도달 " } | ||
|
||
simpMessageSendingOperations.convertAndSend( | ||
"/topic/chat-rooms/${chatMessage.roomId}", | ||
chatMessage | ||
) | ||
|
||
chatMessageFacadeService.saveMessage(chatMessage) | ||
} | ||
|
||
} |
30 changes: 30 additions & 0 deletions
30
...tion/src/main/kotlin/com/swm/idle/presentation/chat/controller/ChatWebSocketController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.swm.idle.presentation.chat.controller | ||
|
||
import com.swm.idle.application.chat.facade.ChatMessageFacadeService | ||
import com.swm.idle.support.common.uuid.UuidCreator | ||
import com.swm.idle.support.transfer.chat.SendChatMessageRequest | ||
import org.springframework.messaging.handler.annotation.DestinationVariable | ||
import org.springframework.messaging.handler.annotation.MessageMapping | ||
import org.springframework.messaging.handler.annotation.SendTo | ||
import org.springframework.stereotype.Controller | ||
import java.util.* | ||
|
||
@Controller | ||
class ChatWebSocketController( | ||
private val chatMessageService: ChatMessageFacadeService, | ||
) { | ||
|
||
@MessageMapping("/chat-rooms/{roomId}") | ||
@SendTo("/topic/chat-rooms/{roomId}") | ||
fun sendTextMessage( | ||
@DestinationVariable roomId: UUID, | ||
request: SendChatMessageRequest, | ||
) { | ||
chatMessageService.sendTextMessage( | ||
roomId = roomId, | ||
senderId = UuidCreator.create(), // TODO: 토큰 인증 구현 | ||
contents = request.contents, | ||
) | ||
} | ||
|
||
} |
7 changes: 7 additions & 0 deletions
7
...ort/transfer/src/main/kotlin/com/swm/idle/support/transfer/chat/SendChatMessageRequest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.swm.idle.support.transfer.chat | ||
|
||
import com.swm.idle.domain.chat.entity.jpa.ChatMessage | ||
|
||
data class SendChatMessageRequest( | ||
val contents: List<ChatMessage.Content>, | ||
) |