항해 99 31일차
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를 유지한다.