14일차

2024. 8. 7. 18:22FCB2O4

기존에 쓰던 자동 스크롤 내리기 때문에 엔터키를 누를 때마다 웹페이지 전체의 스크롤이 아래로 내려가는 현상이 발생

 

useEffect(() => {
if (messagesContainerRef.current) {
  messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight;
}
}, [messages]);

 

scrollTop : 요소의 수직 스크롤 위치. 숫자가 클 수록 스크롤이 아래에 있음

scrollHeight : 요소의 전체 콘텐츠 높이

 

messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight

 

채팅창의 스크롤이 가장 아래로 이동

 -> 요소의 스크롤 위치를 전체 콘텐츠의 높이로 설정하여, 새로운 메시지가 추가될 때 자동으로 스크롤을 아래쪽으로 이동

 

이제 DB와 연결할 시간.

 

먼저 DTO, Mapper, Service, Mapper.xml 등을 작성

 

ChatLog(DTO)

package b2o4.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ChatLog {

	private int msgNo;
	private int memberNo;
	private String memberId;
	private String msgContent;
}

 

ChatMapper

package b2o4.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.web.bind.annotation.RequestBody;

import b2o4.dto.ChatLog;

@Mapper
public interface ChatMapper {
	
	//채팅 기록 저장
	void recordChatMessage(@RequestBody ChatLog log);
	
	//채팅 기록 삭제
	void deleteChatMessage(int msgNo);
}

 

ChatService + ChatServiceImpl

package b2o4.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import b2o4.dto.ChatLog;
import b2o4.mapper.ChatMapper;

@Service
public class ChatServiceImpl implements ChatService{

	@Autowired
	private ChatMapper mapper;
	
	@Override
	public void recordChatMessage(ChatLog log) {
		System.out.println(log.toString());
		mapper.recordChatMessage(log);
	}
	
	@Override
	public void deleteChatMessage(int msgNo) {
		System.out.println("삭제할 채팅 번호" + msgNo);
		mapper.deleteChatMessage(msgNo);
	}
}

 

ChatMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="b2o4.mapper.ChatMapper">

	<!-- 채팅 기록 DB에 넣기 -->
    <insert id="recordChatMessage" parameterType="b2o4.dto.ChatLog" useGeneratedKeys="true" keyProperty="msgNo">
        INSERT INTO LiveChatMessage(memberNo, msgContent, msgAt) VALUES (#{memberNo}, #{msgContent}, now())
    </insert>
	
	<!-- 채팅 삭제 -->
	<delete id="deleteChatMessage" parameterType="int">
		DELETE FROM LiveChatMessage WHERE msgNo = #{msgNo}
	</delete>

</mapper>

 

ChatController

package b2o4.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import b2o4.dto.ChatLog;
import b2o4.service.ChatService;
import b2o4.vo.ChatMessage;

@RestController
public class ChatController {

    @Autowired
    private ChatService chatService;
    
    //채팅 주고받게 하기
    @MessageMapping("/chat.send")
    @SendTo("/topic/messages")
    public ChatMessage send(ChatMessage message) {
    	ChatLog log = new ChatLog();
    	log.setMemberNo(1);
    	log.setMsgContent(message.getContent());
    	
    	System.out.println("리액트에서 들어온 메시지 : " + message.getContent());
    	System.out.println("임시 멤버 번호 : " + log.getMemberNo());
    	System.out.println("로그로 들어온 메시지 : " + log.getMsgContent());
    	
    	chatService.recordChatMessage(log);
        return message;
    }
    
    //채팅 DB에 넣기
    @PostMapping("/chat")
    public void recordChatMessage(@RequestBody ChatLog log) {
    	chatService.recordChatMessage(log);
    }
    
    //채팅 내역 불러오기
    
    //삭제할 채팅
    @DeleteMapping("/chat")
    public void deleteChatMessage(@RequestParam("msgNo") int msgNo) {
    	chatService.deleteChatMessage(msgNo);
    }
    
}

 

일단 로그인 정보를 가져온 게 아니기 때문에 멤버 번호를 1로 임시로 지정하고

 

log.setMsgContent(message.getContent()) 를 통해 채팅 메시지를 dto의 msgContent에 저장.

 

채팅창에 입력
DB에 메시지가 들어감을 확인

 

삭제 기능은 아직 임시로 구현했고, DB에 있는 메시지 삭제 기능은 아직 미구현.

 

추가로 모든 채팅창 동결 기능 구현

 

LiveChat.js

//const client .. onConnect function에 다음 구문 추가

client.subscribe('/topic/freezeChat', (response) => {
  console.log(freezeChat);
  setFreezeChat(JSON.parse(response.body));
});

//handleFreezeChat 함수 수정

const handleFreezeChat = () => {
  if (stompClient) {
    stompClient.publish({
      destination: '/app/chat.freezeChat'
    });
    stompClient.subscribe('/topic/freezeChat', (response) => {
      const newFreezeChatState = JSON.parse(response.body);
      setFreezeChat(newFreezeChatState);
    });
  }
}

 

그리고 Controller에 다음 구문을 추가하면 끝.

    // 채팅 동결
    @MessageMapping("/chat.freezeChat")
    @SendTo("/topic/freezeChat")
    public boolean chatFreezing() {
        freezeChat = !freezeChat;
        return freezeChat;
    }

    // 채팅창 동결 상태 가져오기
    @GetMapping("/chat/freezeChat")
    public boolean getChatFreezing() {
        return freezeChat;
    }

 

메시지를 주고 받는 것 처럼 동결 상태도 주고 받는 것처럼 구현하는 것이었다.

 

이는 나중에 스트리밍 시작 / 종료도 모든 사용자들에게 영향을 주도록 할 때 다시 응용할 예정.

'FCB2O4' 카테고리의 다른 글

16일차  (0) 2024.08.12
15일차  (0) 2024.08.08
13일차  (0) 2024.08.06
12일차  (0) 2024.08.05
11일차  (0) 2024.08.02