@Slf4j
@RequiredArgsConstructor
@Controller
public class ChatController {
private final ChatMessageService chatMessageService;
@MessageMapping("/chats/join/{postId}")
@SendTo("/sub/chats/room/{postId}")
public ChatMessageResponse join(
@DestinationVariable(value = "postId") String postId,
ChatMessageRequest req
) {
String content = req.sender() + "님이 입장하셨습니다.";
return new ChatMessageResponse(content);
}
@MessageMapping("/chats/message/{postId}")
@SendTo("/sub/chats/room/{postId}")
public ChatMessageResponse message(
@DestinationVariable(value = "postId") String postId,
ChatMessageRequest req
) {
String content = req.content();
String username = req.sender();
chatMessageService.saveChatMessage(postId, username, content);
return new ChatMessageResponse(content);
}
}
Java
복사
public record ChatMessageRequest(String content, String sender) {
}
Java
복사
public record ChatMessageResponse(String content) {
}
Java
복사
@Getter
@NoArgsConstructor
@Document(collection = "chat_message")
public class ChatMessage extends BaseTime {
@Id
private String id;
@Field
private String postId;
@Field
private String sender;
@Field
private String content;
@Field
private String userId;
@Builder
public ChatMessage(String postId, String sender, String content, String userId) {
this.postId = postId;
this.sender = sender;
this.content = content;
this.userId = userId;
}
}
Java
복사
@Getter
@NoArgsConstructor
@Entity
@Table(name = "tb_chatroom")
public class ChatRoom {
@Id
private Long postId;
public ChatRoom(Long postId) {
this.postId = postId;
}
}
Java
복사
public interface ChatMessageRepository extends MongoRepository<ChatMessage, Long> {
}
Java
복사
public interface ChatRoomRepository extends JpaRepository<ChatRoom, Long> {
}
Java
복사
@RequiredArgsConstructor
@Service
public class ChatMessageServiceImpl implements ChatMessageService {
private final ChatMessageRepository chatMessageRepository;
private final UserRepository userRepository;
@Override
public void saveChatMessage(String postId, String sender, String content) {
User user = findByNickname(sender);
ChatMessage chatMessage = ChatMessage.builder()
.postId(postId)
.sender(sender)
.content(content)
.userId(String.valueOf(user.getId()))
.build();
chatMessageRepository.save(chatMessage);
}
private User findByNickname(String nickname) {
return userRepository.findByNickname(nickname)
.orElseThrow(() -> new GlobalException(UserErrorCode.UNAUTHORIZED_USER));
}
}
Java
복사
@RequiredArgsConstructor
@Service
public class ChatRoomServiceImpl implements ChatRoomService {
private final ChatRoomRepository chatRoomRepository;
// 채팅방 생성
@Override
public void createRoom(Long postId) {
ChatRoom newRoom = new ChatRoom(postId);
chatRoomRepository.save(newRoom);
}
// 채팅방 삭제
@Override
public void deleteRoom(Long postId) {
chatRoomRepository.deleteById(postId);
}
}
Java
복사
public interface ChatMessageService {
/**
* @param postId 채팅방 id
* @param sender 채팅 작성자
* @param content 채팅 내용
*/
void saveChatMessage(String postId, String sender, String content);
}
Java
복사
public interface ChatRoomService {
/**
* @param postId : 채팅방 id로 사용할 postId
*/
void createRoom(Long postId);
/**
* @param postId : 채팅방 삭제를 위한 postId
*/
void deleteRoom(Long postId);
}
Java
복사
@RequiredArgsConstructor
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/sub");
config.setApplicationDestinationPrefixes("/pub");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("http://localhost:8080/")
.withSockJS();
}
}
Java
복사
@Controller
@RequiredArgsConstructor
public class ChatFrontController {
@GetMapping("/chat/{postId}")
public String getChatPage(
@PathVariable Long postId,
Model model,
@AuthenticationPrincipal UserDetailsImpl userDetails
) {
model.addAttribute("postId", postId);
model.addAttribute("username", userDetails.getUsername()); // 현재 로그인된 사용자 이름
return "domain/chat/chatroom"; // Thymeleaf 템플릿 이름
}
}
Java
복사