채팅 서버 만들기 2

바그다드·2023년 4월 11일
0

채팅 서버 만들기

목록 보기
2/4
  • 이제 본격적으로 채팅 서버를 만들어보자!

Chat 클래스 생성

  • 간단한 구현이니 따로 패키지를 생성하지 않고 클래스를 작성하자
@Data
@Document(collection = "chat")
public class Chat {
    @Id
    private String id;
    private String msg;
    private String sender; // 보내는 사람
    private String receiver; // 받는 사람

    private LocalDateTime createdAt;
}
  • @Document는 컬렉션 내의 하나의 Document에 대응한다. RDBMS로 따지면 테이블 내의 하나의 row에 해당한다.
  • 위의 코드에서는 chat이라는 컬렉션에 대응하는 document라고 생각하면 된다.

ChatRepository

public interface ChatRepository extends ReactiveMongoRepository<Chat, String> {

    @Tailable // 커서를 안닫고 계속 유지한다.
    @Query("{sender:?0,receiver:?1}")
    Flux<Chat> mFindBySender(String sender, String receiver); //Flux(흐름) response를 유지하면서 데이터를 계속 흘려보내기
}
  • 사용자1의 요청에 의해 @Tailable을 사용해 {'sender':'ssar'} 이라는 조건으로 데이터를 요청하면 db에서 데이터를 조회하여 클라이언트에게 반환을 하고 커넥션을 유지한다. 이 때 사용자2가 DB에 {sender:'ssar',msg:'반가워'}라는 데이터를 입력하면 앞에서 @Tailable 때문에 커넥션이 유지되어 있기 때문에 사용자1에게 이 데이터가 그대로 반환이 된다.
  • 컨트롤러는 이 데이터를 Flux라는 데이터 형태로 반환한다.
  • 그런데 이처럼 실시간 통신을 할 때 http프로토콜을 사용을 하게 되면 데이터를 모아 한번에 전송하고 연결을 끊어버린다. 하지만 우리는 요청을 필요할 때만 연결하지만 응답은 유지하여 새로운 데이터가 생길 때마다 지속적으로 반환을 해줘야한다. 따라서 여기에서는 SSE프로토콜을 사용할 예정이다.
  • 웹소켓 방식과 SSE 방식의 차이점

ChatController 생성

  • 이제 컨트롤러를 만들어보자
@RequiredArgsConstructor
@RestController
public class ChatController {

    private final ChatRepository chatRepository;

    // 데이터를 지속적으로 리턴을 할 경우
    @GetMapping(value = "/sender/{sender}/receiver/{receiver}", 
    produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Chat> getMsg(@PathVariable String sender, @PathVariable String receiver) {
        return chatRepository.mFindBySender(sender, receiver)
                .subscribeOn(Schedulers.boundedElastic());
    }

    // Mono : 데이터를 한번만 리턴할 경우
    @PostMapping("/chat")
    public Mono<Chat> setMsg(@RequestBody Chat chat) {
        chat.setCreatedAt(LocalDateTime.now());
        return chatRepository.save(chat);
    }
}
  • Flux와 Mono는 스프링5에 새로 추가된 webflux모듈에서 지원한다. 이것도 파보려면 꽤 깊이 들어가야해서 일단은 flux는 0개~n개의 데이터를 전달할 때 사용하고, Mono는 0~1개의 데이터 전달할 때 사용한다는 것만 알아두자.
  • 이제 프로젝트를 실행하고 포스트맨을 이용해 메세지를 전송해보면 위와 같이 db에 반영이 되고 id값이 부여되어 돌아온 것을 확인할 수 있다.
  • 하지만 브라우저에서 localhost:8080/sender/{sender}/receiver/{receiver} 페이지로 접속을 시도하면 에러페이지가 뜨고 콘솔에는 아래와 같은 메세지가 뜰 것인데, 이는 배치사이즈가 부족하여 발생하는 에러라고 한다.
Caused by: com.mongodb.MongoQueryException: Query failed with error code 2 and error message 'error processing query: ns=chatdb.chat batchSize=32Tree: $and
  • mongoDB에 아래와 같은 명령어를 입력하고
db.runCommand({convertToCapped:'chat',size:8192});
  • 다시 페이지에 접근을 시도하면 아래와 같이 정상적으로 정보가 뜨는 것을 확인할 수 있다.
    그리고 연결이 유지되기 때문에 왼쪽 위에 계속 원이 돌아가고 있는 것을 확인할 수 있다.
  • 이제 vs를 이용해 화면을 디자인해보자!
profile
꾸준히 하자!

0개의 댓글