항해 99(9기)/항해 일일

항해 99 31일차

jossiya 2022. 10. 19. 15:28

SPRING 5.0 을 이용한 채팅 서버 만들어 보기

 

기존에 사용하던 JPA로 하고 싶어서 이것저것 셋팅해보다가 안되서 포기했지만 클론코딩인 만큼 여러가지 찾아본 거 기입해보았다.

Spring WebFlux

기존에 사용하던 Spring MVC 와 별개로 reactive 하게 요청을 처리할 수 있도록 Spring 5 에서 추가된 모듈이다.

 

R2DBC

Spring Framework 에서 database 연결은 동기로 사용하던 것을 비동기로 요청을 처리할 수 있도록 지원해주는 모듈이다. 현재는 데이터베이스에 따라서 지원하는게 각각 다르다.

 

차이점

                                 SQL 데이터베이스                                            NoSQL 데이터베이스

데이터 스토리지 모델 고정 행과 열이 있는 테이블 문서: JSON 문서, 키-값: 키-값 쌍, 와이드 열: 행과 동적 열이 있는 테이블, 그래프: 노드 및 가장자리
개발 연혁 데이터 중복을 줄이는 데 중점을 둔 1970년대에 개발 2000년대 후반에 개발되어 민첩한 및 DevOps 관행에 따라 확장과 신속한 애플리케이션 변경을 가능하게 합니다.
예제 Oracle, MySQL, Microsoft SQL Server 및 PostgreSQL 문서: MongoDB 및 CouchDB, 키-값: Redis and DynamoDB, 와이드 컬럼: 카산드라와 HBase, 그래프: Neo4j 및 Amazon Neptune
기본 목적 범용 문서: 범용, 키-값: 간단한 조회 쿼리로 대량의 데이터, 와이드 컬럼: 예측 가능한 쿼리 패턴을 가진 대량의 데이터, 그래프: 연결된 데이터 간의 관계 분석 및 트래버스잉
스키마 딱딱한 유연한
스케일링 수직(더 큰 서버로 확장) 수평(상용 서버 간 확장)
다중 기록 ACID 거래 지원 대부분은 다중 레코드 ACID 트랜잭션을 지원하지 않습니다. 그러나 MongoDB와 같은 일부는 그렇게합니다.
조인 일반적으로 필수 일반적으로 필요하지 않음
데이터-객체 매핑 ORM(객체-관계형 매핑) 필요 많은 사람들이 ORM을 필요로하지 않습니다. MongoDB 문서는 가장 널리 사용되는 프로그래밍 언어의 데이터 구조에 직접 매핑됩니다.

 

Netty

네티는 이벤트를 Inbound 이벤트, Outbound 이벤트로 구분한다.

클라이언트로 부터 데이터 수신할 때 발생하는 이벤트에 관심이 있다면, Inbound 이벤트 중 하나인 '데이터 수신 이벤트'를 담당하는 메서드에 원하는 로직을 넣으면 된다.

네티는 기본적으로, 적절한 추상화 모델을 제공하여 개발자가 간단한 코드작성만으로 안정적이고 빠른 네트워크 어플리케이션을 개발할 수 있게 도와준다.

 

웹소켓과 SSE(Server-Sent-Event)에 차이점

 

Socket과 SSE에 가장 큰 차이점을 하나 말해보라고 한다면 Socket은 양방향(bidirectional)으로 데이터를 주고 받을 수 있지만 SSE(Server-Sent-Event)를 사용하게 되면 클라이언트는 데이터를 받을 수만(mono-directional) 있게 됩니다. 그러니까 어떤 기능이 필요한지에 따라서 뭐를 사용할지 결정하면 된다. 

웹소켓과 SSE에 가장 큰 차이점은 통신 방향이다.!

  Socket Server-Sent-Event
브라우저 지원 대부분 브라우저에서 지원  대부분 모던 브라우저 지원(polyfills 가능)
통신 방향 양방향 일방향(서버에서 클라이언트로)
리얼타임 Yes Yes
데이터 형태 Binary, UTF-8 UTF-8
자동 재접속 No Yes(3초마다 제시도)
최대 동시 접속 수 브라우저 연결 한도는 없지만 서버 셋업에 따라 다름  HTTP를 통해서 할 때는 브라우저당 6개 까지 가능 / HTTP2로는 100개가 기본
프로토콜 websocket HTTP
베터리 소모량 작음
Firewall 친화적 Nope Yes

 

import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.data.mongodb.repository.Tailable;
import reactor.core.publisher.Flux;

public interface ChatRepository extends ReactiveMongoRepository<Chat,String> {

    @Tailable // 커서를 안닫고 계속 유지한다.
    @Query("{sender:?0,receiver:?1}") // MongoDB 문법
    Flux<Chat> mFindBySender(String sender, String receiver); // Flux(흐름) response를 유지하면서 데이터를 계속 흘려보내기
}

 

일반적인 Http 프로토콜을 사용하면 예를들어 데이터가 1,2,3 건 있을때 이것들을 한번에 모아 처리한다.


하지만 채팅은 이렇게 하면 안되고 데이터가 요청될때마다 응답해야하므로 SSE 프로토콜을 사용한다.

 

 

@Tailable은 데이터를 하나 보낸 후에 닫는게 아니라 계속 커서를 유지해서 데이터가 들어오면 받게 한다.

 

Flux(흐름 )는 데이터를 한번만 받고 닫는게 아니라 들어오는 대로 계속 흘려보내 response를 유지한다.