💡 피어 투 피어 패턴의 사용 사례 : WebRTC(Web Real-Time Communication)
1. 시스널링(Singnaling)
- 웹 서버를 통해서 상대방의 IP 주소, 포트정보, 통신에 필요한 '메타데이터를 교환'하는 시그널링 과정을 거칩니다. - 해당 과정에서는 WebRTC 프로토콜은 포함되어 있지 않습니다.
2. SDP(Session Description Protocol) 교환
- 시그널링 과정을 통해 Peer A와 Peer B를 서로 찾으면 SDP를 이용하여 미디어 통신을 위한 '세션을 협상'합니다. - SDP는 미디어 포맷, 전송 프로토콜, IP 주소, 포트 번호 등을 포함합니다.
3. ICE(Interactive Connectivity Establishment) 프레임워크를 통한 NAT/Firewall 우회 - 실제 인터넷 환경에서는 NAT(Network Address Translation)이나 Firewall 때문에 직접 통신이 어려울 수 있습니다. - 이를 해결하기 위해 ICE 프레임워크를 사용하여 STUN(Server Traversal Utilities for NAT) 서버나 TURN(Traversal Using Relays around NAT) 서버를 이용하여 NAT/Firewall를 우회하게 됩니다.
4. 미디어 통신
- 이렇게 연결이 완료되면, Peer A와 Peer B는 서로에게 Audio, Video, Data를 직접 전송할 수 있게 됩니다. - 이 과정에서는 RTP(Real-time Transport Protocol)를 사용하여 실시간으로 미디어 데이터를 전송합니다.
[ 더 알아보기 ] 💡 WebRTC(Web Real-Time Communication)
- 웹 브라우저 간에 실시간 통신을 가능하게 하는 오픈 소스 프로젝트입니다. - 기술은 피어 투 피어 연결을 통해 데이터를 직접 교환하므로 중간에 서버를 거치지 않고 빠르게 데이터를 전송할 수 있습니다. 이로 인해 지연 시간이 크게 감소하며, 서버 비용도 절약할 수 있습니다. - 또한, WebRTC는 음성 및 비디오 통화, 텍스트 메시지, 파일 공유 등 다양한 형태의 실시간 통신을 지원합니다. 이 기술의 보안성도 뛰어나, 모든 통신은 기본적으로 암호화됩니다.
- 서로 다른 컴포넌트들 사이에 메시지를 전달하는 매체로 ‘이벤트 버스’를 사용하는 패턴을 의미합니다.
- 이벤트 버스는 중개인 역할을 하며 서로 상호작용을 하는 컴포넌트들 사이에서 직접적인 의존성을 제거하고 유연하고 재 사용 가능한 코드를 작성할 수 있게 돕습니다. - 이벤트-버스 패턴을 사용하면 한 컴포넌트에서 발생한 이벤트를 다른 컴포넌트에서 구독하고 반응할 수 있습니다. 이는 컴포넌트 간의 강력한 결합을 피하고 코드의 유연성을 높이는데 도움이 됩니다. - 하지만 이벤트-버스 패턴은 사용에 주의가 필요합니다. 이 패턴을 과도하게 사용하면, 어떤 이벤트가 어디서 발생했는지, 어떤 컴포넌트가 이벤트를 받고 있는지 추적하기 힘들어지고, 코드의 복잡성이 증가할 수 있습니다. 따라서 이벤트-버스 패턴은 적절히 사용해야 합니다.
구성요소
설명
이벤트 소스(Event Source)
이벤트를 발생시키는 엔티티로, 이벤트의 상태 변경이나 특정 행동을 통해 이벤트를 생성합니다.
이벤트 리스너(Event Listener)
특정 이벤트를 구독하고, 이벤트가 발생하면 반응하여 특정 작업을 수행하는 엔티티입니다.
채널(Channel)
이벤트 소스와 이벤트 리스너 사이에서 이벤트를 전달하는 통신 경로입니다.
이벤트 버스(Event Bus)
이벤트를 생성하고, 전달하며, 처리하는 중계 역할을 하는 시스템입니다.
💡 이벤트-버스 패턴(Event-Bus Pattern) 처리과정
1. 게시자(Publisher)
- 이벤트 소스는 특정 조건이 충족되면 이벤트를 생성합니다. 이 이벤트는 일반적으로 상태 변경이나 특정 행동에 의해 발생합니다.
2. 게시자(Publisher) → (Event) → 이벤트 버스(Event Channel)
- 이벤트를 전달 받은 경우 이벤트 버스로 전달이 됩니다. 이 이벤트 버스에서는 특정 이벤트 채널로 라우팅을 수행합니다.
3. 구독자(Subscriber) = 이벤트 리스너(Event Listener)
- 특정 채널만 구독하고 있던 구독자만 반응하여 이벤트가 전달되어, 해당 이벤트를 기반으로 처리를 수행합니다.
- 해당 패턴을 사용하는 사례는 A라는 모바일 기기에 B라는 모바일 기기로 FCM 푸시 메시지 전송하는 과정에서 나타납니다.
- FCM 메시지를 전송할 때는 상대방의 FCM ID를 기반으로 다른 디바이스로 전송을 합니다. 이 전송 과정에서 채널이 생성이 되고, 전송받는 디바이스에서는 이벤트 리스너를 통해 이벤트가 들어오기를 기다리고 있습니다. 그리고 이벤트가 들어오게 되면 상대방에게 푸시 메시지가 전송이 됩니다.
💡 전송 처리 과정 - A Mobile이 Publisher가 되어서 푸시 알림을 전송하는 주체가 됩니다.
1. A Mobile은 앱을 실행하여 FCM 메시지를 전송하는 버튼을 누릅니다 : Publisher
2. 서버의 특정 엔드포인트로 호출이 되어서 해당 메시지가 서버에서 처리가 됩니다.
3. 리스너에서는 Publisher로 부터 이벤트(메시지)를 전달 받으면 FCM 메시지를 출력 할 수 있도록 이벤트를 수신하고 있습니다.
💡 수신 처리 과정(대기)
- B Mobile은 FCM 메시지를 전송받기 위한 Subscriber가 되어서 앱의 리스너를 등록하고 푸시 알람을 받는 주체가 됩니다.
1. B Mobile은 앱을 실행하여 채널을 생성합니다.
2. 채널을 기반으로 Subscribe Listener를 등록합니다.
3. 리스너에서는 이벤트(메시지)를 전달받으면 FCM 메시지를 출력할 수 있는 Notifee를 이벤트로 등록해 둡니다.
💡 수신 처리 과정(수신 완료 및 메시지 출력)
- B Mobile에서 대기 상태에 이벤트(메시지)를 받기 위해 리스너를 등록하였습니다. 이 상태에서 A Mobile에서 전송한 FCM 메시지를 수신받으면 이에 따라 등록한 이벤트를 수행합니다.
1. B Mobile은 대기 상태로 있다가 FCM 메시지를 전송받으면 이벤트를 수행합니다.
2. 이벤트로 구성해 두었던 Notifee 라이브러리를 통해 알람을 통해 푸시 메시지를 띄어줍니다.
- 차량 식별 및 추적시스템에서 여러 지식 소스(Knowledge Sources)들이 독립적으로 작동하여 각각의 전문성에 따라 차량을 식별하고 추적 작업을 수행합니다.
2. 지식 소스(Knowledge Sources)
- 하나의 지식 소스는 차량의 번호판을 인식하는 작업을 담당하고 다른 하나는 차량의 모델을 식별하는 작업을 수행하고, 또 다른 하나는 차량의 색상을 식별하는 작업을 각각 수행할 수 있습니다. - 이러한 각각의 지식소스는 자신의 작업 결과를 블랙보드에 저장하며 이 정보는 다른 지식 소스에게 참조되거나 사용될 수 있습니다.
3. 제어요소(Controller)
- 제어요소에서는 모든 과정을 조정합니다. 블랙보드에 저장된 정보를 바탕으로 어떤 지식 소스가 다음으로 활동할지 결정하며 이러한 방식으로 차량 식별 및 추적 작업이 유기적으로 진행될 수 있게 합니다.
- 주어진 언어에 대해 그 언어의 문법을 위한 표현을 정의하고 이 언어로 작성된 문장을 해석하는 해석기(Interpreter) 사용하여 해당 언어로 작성된 문자을 해석하는 아키텍처 패턴을 의미합니다.
- 주로 문법 트리를 구성하고 이 트리를 통해 문장을 해석하는 데 사용됩니다. 각각 문법 규칙은 고유 클래스로 표현되고 문장의 각 부분은 이 클래스의 인스턴스로 표현이 됩니다. - 해당 경우는 문제가 간단할 때 사용하는 것이 가장 좋습니다. 복잡한 문제의 경우, 문법 트리가 너무 크고 복잡해져서 관리하기 어려워질 수 있습니다. 따라서 이 패턴은 간단한 문맥에 대한 문법만 필요한 경우, 예를 들어 간단한 계산기나 정규 표현식 등에 적합합니다. - 이 패턴은 특히 프로그래밍 언어 컴파일러 디자인과 SQL 파싱 같은 언어 기반의 연산에서 사용됩니다.
- 주어진 언어에 대해 그 언어의 문법을 위한 표현을 정의하고 이 언어로 작성된 문장을 해석하는 해석기(Interpreter) 사용하여 해당 언어로 작성된 문자을 해석하는 아키텍처 패턴을 의미합니다.
- 주로 문법 트리를 구성하고 이 트리를 통해 문장을 해석하는 데 사용됩니다. 각각 문법 규칙은 고유 클래스로 표현되고 문장의 각 부분은 이 클래스의 인스턴스로 표현이 됩니다. - 해당 경우는 문제가 간단할 때 사용하는 것이 가장 좋습니다. 복잡한 문제의 경우, 문법 트리가 너무 크고 복잡해져서 관리하기 어려워질 수 있습니다. 따라서 이 패턴은 간단한 문맥에 대한 문법만 필요한 경우, 예를 들어 간단한 계산기나 정규 표현식 등에 적합합니다. - 이 패턴은 특히 프로그래밍 언어 컴파일러 디자인과 SQL 파싱 같은 언어 기반의 연산에서 사용됩니다.
구성요소
설명
추상 표현식 (Abstract Expression)
모든 노드에 대해 공통의 메서드로 추상 표현식을 정의합니다. interpret()라는 메서드를 통해 해석 작업을 수행하는 메서드를 선언합니다.
터미널 표현식(Terminal Expression)
추상 표현식을 상속받아 구현한 클래스로 문법의 ‘가장 작은 단위’를 나타냅니다.
비터미널 표현식(Nonterminal Expression)
추상 표현식을 상속받아 구현한 클래스로 문법의 ‘복잡한 부분’을 나타냅니다. 비터미널 표현식은 다른 표현식을 포함할 수 있습니다.
- 정규식을 구성하는 표현식을 생성합니다. - 이는 터미널 표현식(TerminalExpression)과 비터미널 표현식(NontermianlExpression)의 조합으로 이루어집니다. - 예를 들어, [0-9]+라는 정규식은 '0-9'라는 터미널 표현식과 '+'라는 비터미널 표현식으로 구성될 수 있습니다.
3. 표현식 해석(Expression Interpreter)
- 생성된 표현식을 사용하여 Context 내의 정규식을 해석합니다. - 각 표현식은 자신이 해석할 부분을 해석하고, 결과를 반환합니다.
4. 결과 반환
- 마지막으로, 인터프리터는 해석된 결과를 반환합니다. - 이 결과는 정규식이 매칭되는지 아닌지, 매칭된다면 어떤 부분이 매칭되는지 등의 정보를 포함할 수 있습니다.