WebSocket은 클라이언트 서버간 양방향 통신이 가능하지만, 다음과 같은 이슈가 있다. 1. websocket미지원 웹 브라우저가 있다는 점 2. 웹 브라우저 이외의 클라이언트 지원(서버 입장에서는 클라이언트는 웹 브라우저뿐만이 아님)
WebSocket
WebSocket 동작 순서
Http의 특징 중 하나는 단방향 통신이다. 클라이언트와 서버간의 통신은 단건으로 이루어지며 하나의 요청(통신)이 끝나게 되면 클라이언트와 서버는 아무런 관계가 없어지게된다. 이 말은 서버입장에서 클라이언트로부터 요청이 있기전까지는 어떤 데이터도 전송할 수 없다는 것이다. 이런 문제를 해결하기 위해 양방향 통신이 생겨나게 되었고, WebSocket으로 구현하게 되었다.
WebSocket은 Http를 통해 작동하도록 설계되었으며, Http Header에 특정 값("websocket")을 명시함으로써 WebSocket 프로토콜로 전환하는 요청으로 시작된다.
STOMP
스트리밍 텍스트 지향 메시지 프로토콜
STOMP는 Simple/Stream Text Oriented Message Protocol의 약자로, 메시지 브로커의 역할을 한다.
메시지 전송을 효율적으로 처리하기 위한 프로토콜
STOMP는 WebSocket 기반으로 동작하며 pub/sub 구조로 되어 있다. pub/sub 구조는 쉽게 말해 편지를 쓰는 사람(Publisher)이 편지함에 편지를 넣어두면 그걸 기다리고 있던 편지를 받는 사람(Subscriber)이 편지를 받고 읽는 구조이다.
즉, WebSocket 위에서 동작하는 프로토콜로써 클라이언트와 서버가 전송할 메시지의 유형, 형식, 내용들을 정의하는 메커니즘이다.
Stomp를 사용하는 이유
STOMP 를 사용하여 WebSocket만 사용할 때보다 더 다채로운 모델링을 할 수 있다.
Messaging Protocol을 만들고 메세지 형식을 커스터마이징 할 필요가 없다.
RabbitMQ, ActiveMQ 같은 Message Broker를 이용해, Subscription(구독)을 관리하고 메세지를 브로드캐스팅할 수 있다.
WebSocket 기반으로 각 Connection(연결)마다 WebSocketHandler를 구현하는 것 보다 @Controller 된 객체를 이용해 조직적으로 관리할 수 있다.
즉, 메세지는 STOMP의 "destination" 헤더를 기반으로 @Controller 객체의 @MethodMapping 메서드로 라우팅 된다.
STOMP의 "destination" 및 Message Type을 기반으로 메세지를 보호하기 위해 Spring Security를 사용할 수 있다.
SockJS
WebSocket은 upgrade Header를 이용하여 Socket연결을 하고, 통신을 진행한다. 이 과정에서 여러가지 이유로 소켓연결이 불가능하게 될 경우가 있는데 이럴 경우 Http기반의 다른 기술로 전환하여 다시 연결을 시도해야할 필요가 있다. 이 때 사용하시는 것이 'WebSocket Emulation'이다. 그리고 Spring에서는 Emulation을 위해 'SockJS' 라이브러리를 지원한다.
SockJS는 다양한 기술을 이용해 웹소켓을 지원하지 않는 브라우저에서 정상 작동하도록도와주는데.
WebSocket
HTTP Streaming
HTTP Long Polling 세가지 타입을 이용한다.
Redis
레디스(Redis)는 Remote Dictionary Server의 약자로서, "키-값" 구조의 비정형 데이터를 저장하고 관리하기 위한오픈 소스기반의 비관계형데이터베이스 관리 시스템(DBMS)이다.
redis를 사용하는 이유?
1.놀라울 정도로 빠른 성능
Redis와 같은 인 메모리 데이터베이스는 디스크에 액세스해야 할 필요를 없앰으로써 검색 시간으로 인한 지연을 방지하고 CPU 명령을 적게 사용하는 좀 더 간단한 알고리즘으로 데이터에 액세스할 수 있다.
2. 인메모리 데이터 구조
Redis를 사용하면 사용자가 다양한 데이터 유형에 매핑되는 키를 저장할 수 있다.
3. 다양성과 사용 편의성
Redis는 개발과 운영을 좀 더 쉽고 좀 더 빠르게 수행할 수 있는 여러 가지 도구를 제공한다. Pub/Sub는 메시지를 채널에 게시하며, 채널에서 구독자에게 전달된다. 채팅과 메시징 시스템에 매우 적합하다.
4. 복제 및 지속성
Redis는 마스터-슬레이브 아키텍처를 사용하며 비동기식 복제를 지원하여 데이터가 여러 슬레이브 서버에 복제될 수 있다. 이렇게 하면 주 서버에 장애가 발생하는 경우 요청이 여러 서버로 분산될 수 있으므로 향상된 읽기 성능과 복구 기능을 모두 제공할 수 있다.
5. 선호하는 개발 언어 지원
Redis 개발자는 백 개가 넘는 오픈 소스 클라이언트를 사용할 수 있으며, Java, Python, PHP, C, C++, C#, JavaScript, Node.js, Ruby, R, Go를 비롯한 다수의 언어가 지원된다.
Spring 채팅기능에 관련해 찾아보니 WebSocket과 WebRTC 두가지 키워드가 등장했다.
다음은 WebSoket과 WebRTC에 대한 간략한 정리이다.
WebRTC vs WebSockets: What are the key differences?
WebSocket provides aclient-servercomputer communication protocol, whereas WebRTC offers apeer-to-peer protocol and communication capabilitiesfor browsers and mobile apps.
While WebSocket works only over TCP, WebRTC is primarily used over UDP (although it can work over TCP as well).
WebSocket is a better choice when data integrity is crucial, as you benefit from the underlying reliability of TCP. On the other hand, if speed is more important and losing some packets is acceptable, WebRTC over UDP is a better choice.
WebRTC is primarily designed for streaming audio and video content. It is possible to stream media with WebSockets too, but the WebSocket technology is better suited for transmitting text/string data using formats such as JSON.
TCP와 UDP의 차이점은 ?
TCP는 연결 지향 프로토콜인 반면 UDP는 비연결 프로토콜입니다. TCP가 UDP보다 비교적 느리기 때문에 TCP와 UDP의 주요 차이점은 속도입니다. 전반적으로 UDP는 훨씬 빠르고 간단하며 효율적인 프로토콜이지만 손실된 데이터 패킷의 재전송은 TCP를 통해서만 가능합니다.
TCP와 UDP의 또 다른 주목할 만한 차이점은 TCP는 사용자에서 서버로(또는 그 반대로) 데이터를 순서대로 전달하는 반면 UDP는 종단 간 통신 전용이 아니며 수신자의 준비 상태를 확인하지도 않는다는 것입니다.
When to use WebRTC?
WebRTC is a good choice for the following use cases:
Audio and video communications, such as video calls, video chat, video conferencing, and browser-based VoIP.
File sharing apps.
Screen sharing apps.
Broadcasting live events (such as sports events).
IoT devices (e.g., drones or baby monitors streaming live audio and video data).
When to use WebSockets?
We can broadly group Web Sockets use cases into two distinct categories:
Realtime updates, where the communication is unidirectional, and the server is streaming low-latency (and often frequent) updates to the client. Think of live score updates or alerts and notifications, to name just a few use cases.
Bidirectional communication, where both the client and the server send and receive messages. Examples include chat, virtual events, and virtual classrooms (the last two usually involve features like live polls, quizzes, and Q&As). WebSockets can also be used to underpin multi-user synchronized collaboration functionality, such as multiple people editing the same document simultaneously.
[ 정리 ]
WebSocket은 데이터 무결성이 중요한 경우 TCP의 기본 안정성을 활용하므로 더 나은 선택
반면에 속도가 더 중요하고 일부 패킷 손실이 허용되는 경우 UDP를 통한 WebRTC가 더 나은 선택
[ 결론 ] : 두 가지 모두 사용 ?
WebSocket : 게임과 채팅 구현을 위해 실시간성을 보장하는 통신 방식. HTTP에서도 실시간성을 보장하는 반이중 기법들(polling, long polling, streaming)이 존재하나, 실시간성이 떨어지거나 서버 부하가 올라갈 수 있다는 단점이 있어서, 하나의 TCP 연결을 통해 양방향 통신을 제공하는 Websocket을 선택.
WebRTC : 화상/보이스 채팅 기능을 위해 카메라와 마이크 등의 미디어 자원을 통해 실시간으로 소통할 수 있는 기술이 필요. WebRTC는 브라우저에서 지원하는 프레임워크로 많이 사용되어 안정성이 검증되어있고, 별도의 플러그인 없이 사용이 가능하여 User 경험에 유리하다.
이번 프로젝트땐 아마 일반 채팅엔 WebSocket을, 그리고 화상/음성 채팅엔 WebRTC를 사용할 것 같다 : )
Optional은 null 또는 값을 감싸서 NPE(NullPointerException)로부터 부담을 줄이기 위해 등장한 Wrapper 클래스이다.
Optional은 값을 Wrapping하고 다시 풀고, null 일 경우에는 대체하는 함수를 호출하는 등의 오버헤드가 있으므로 잘못 사용하면 시스템 성능이 저하된다.
그렇기 때문에 메소드의 반환 값이 절대 null이 아니라면 Optional을 사용하지 않는 것이 좋다. 즉, Optional은 메소드의 결과가 null이 될 수 있으며, null에 의해 오류가 발생할 가능성이 매우 높을 때 반환값으로만 사용되어야 한다.
Optional은 반환 타입으로써 에러가 발생할 수 있는 경우에 결과 없음을 명확히 드러내기 위해 만들어졌으며, Stream API와 결합되어 유연한 체이닝 api를 만들기 위해 탄생한 것이다. 예를 들어 Stream API의 findFirst()나 findAny()로 값을 찾는 경우에 어떤 것을 반환하는게 합리적일지 Java 언어를 설계하는 사람이 되어 고민해보자. 언어를 만드는 사람의 입장에서는 Null을 반환하는 것보다 값의 유무를 나타내는 객체를 반환하는 것이 합리적일 것이다. Java 언어 설계자들은 이러한 고민 끝에 Optional을 만든 것이다. 그러므로 Optional이 설계된 목적에 맞게 반환 타입으로만 사용되어야 한다.
※ Null string은 언제나 비어있지만, Empty string은 null이 아닐 수도 있다.
http vs https
HTTPS(https://)는 SSL(Secure Socket Layer) 인증서를 사용하는 HTTP(http://)입니다. SSL(또는 TLS) 인증서는 일반 HTTP 요청 및 응답을 암호화합니다. 따라서 HTTPS는 HTTP보다 더 안전한 보안용 프로토콜이라고 할 수 있습니다.
HTTP와 HTTPS의 유일한 차이점은 HTTPS를 사용한 웹 페이지를 통해 전송되는 모든 데이터는 추가적인 보안 계층이 있습니다. 이를 TLS(전송 계층 보안) 프로토콜이라고 합니다. 모든 유형의 데이터는 변경되거나 손상될 수 없는 HTTPS 사이트를 통해 전달되며 제3자로부터 보호됩니다.
※ HTTPS 확인 방법 : 도메인 이름 앞에 자물쇠 아이콘이 있으면 당신의 사이트는 HTTPS로 인해 안전한 것입니다.
지연로딩 vs 즉시로딩 (FetchType.LAZY or EAGER)
JPA에서는 데이터를 조회할 때즉시 로딩(EAGER)과 지연 로딩(LAZY) 두 가지 방식이 있다.
이 두 가지 방식을 간단하게 설명하면 즉시 로딩은 데이터를 조회할 때 연관된 데이터까지 한 번에 불러오는 것이고, 지연 로딩은 필요한 시점에 연관된 데이터를 불러오는 것이라고 할 수 있다.
비지니스 로직 상 Member 데이터가 필요한 곳에 대부분 Team의 데이터 역시 같이 사용 할 필요가 있다면 어떨까? FetchType을 EAGER로 설정하여 항상 Member와 Team을 같이 조회해오는 것이 더 좋을 것이다.
Member를 사용하는 곳 대부분에서 Team 데이터가 필요하지 않다면? FetchType을 LAZY로 설정하여 Member만 조회하고, 드물게 Team이 필요할 땐 그 때 Team에 대한 쿼리를 한번 더 날려 조회하는것이 좋을 것이다.
※ 실무에서는 EAGER LOADING을 사용하지 않는 것을 권장한다.
이유는?
즉시 로딩에서는 Member와 연관된 Team이 1개여서 Team을 조회하는 쿼리가 1개 나갔지만, 만약 Member를 조회하는 JPQL을 날렸는데 연관된 Team이 1000개라면? Member를 조회하는 쿼리를 하나 날렸을 뿐인데 Team을 조회하는 SQL 쿼리 1000개가 추가로 나가게 된다. 그렇기 때문에가급적이면 기본적으로 지연 로딩을 사용하는 것이 좋다.