반응형
해당 글에서는 시스템을 구축할 때 설계를 하는 소프트웨어 아키텍처의 10가지 패턴에 대해 알아보고 활용되는 예시에 대해 확인해 봅니다.
💡 [참고] 해당 글은 이전에 작성한 글에서 이어집니다.
7) 피어 투 피어 패턴(Peer-to-Peer, P2P)
💡 피어 투 피어 패턴(Peer-to-Peer, P2P)
- 모든 참가자(Peer)는 동등한 위치에 있고 모든 참가자가 서버와 클라이언트 둘 다 역할을 수행할 수 있는 패턴을 의미합니다. 이 패턴은 분산형 네트워크에서 주로 사용되며 각 참가자가 자신의 자원을 공유하고 다른 참가자의 자원을 사용할 수 있습니다.
- 이로 인해 중앙 서버에 의존하지 않고 데이터를 공유하고 전송할 수 있으며 이는 대규모 데이터를 효율적으로 전송하거나 분산된 시스템에서 작동하는데 이상적인 패턴입니다.
💡 피어 투 피어 패턴(Peer-to-Peer, P2P) 처리과정
- 각각의 Peer는 클라이언트와 서버의 역할을 둘 다 수행합니다. 그렇기에 Peer 간의 데이터를 요청하고 응답을 할 수 있습니다.
- 미디어 데이터를 전송하는 주체가 'Publisher'가 되고 미디어 데이터를 수신하는 주체가 'Subscriber'가 됩니다.
1. 피어 투 피어 패턴의 사용 사례 : WebRTC(Web Real-Time Communication)
💡 피어 투 피어 패턴의 사용 사례 : 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는 음성 및 비디오 통화, 텍스트 메시지, 파일 공유 등 다양한 형태의 실시간 통신을 지원합니다. 이 기술의 보안성도 뛰어나, 모든 통신은 기본적으로 암호화됩니다.
8) 이벤트-버스 패턴(Event-Bus Pattern)
💡 이벤트-버스 패턴(Event-Bus Pattern)
- 서로 다른 컴포넌트들 사이에 메시지를 전달하는 매체로 ‘이벤트 버스’를 사용하는 패턴을 의미합니다.
- 이벤트 버스는 중개인 역할을 하며 서로 상호작용을 하는 컴포넌트들 사이에서 직접적인 의존성을 제거하고 유연하고 재 사용 가능한 코드를 작성할 수 있게 돕습니다.
- 이벤트-버스 패턴을 사용하면 한 컴포넌트에서 발생한 이벤트를 다른 컴포넌트에서 구독하고 반응할 수 있습니다. 이는 컴포넌트 간의 강력한 결합을 피하고 코드의 유연성을 높이는데 도움이 됩니다.
- 하지만 이벤트-버스 패턴은 사용에 주의가 필요합니다. 이 패턴을 과도하게 사용하면, 어떤 이벤트가 어디서 발생했는지, 어떤 컴포넌트가 이벤트를 받고 있는지 추적하기 힘들어지고, 코드의 복잡성이 증가할 수 있습니다. 따라서 이벤트-버스 패턴은 적절히 사용해야 합니다.
구성요소 | 설명 |
이벤트 소스(Event Source) | 이벤트를 발생시키는 엔티티로, 이벤트의 상태 변경이나 특정 행동을 통해 이벤트를 생성합니다. |
이벤트 리스너(Event Listener) | 특정 이벤트를 구독하고, 이벤트가 발생하면 반응하여 특정 작업을 수행하는 엔티티입니다. |
채널(Channel) | 이벤트 소스와 이벤트 리스너 사이에서 이벤트를 전달하는 통신 경로입니다. |
이벤트 버스(Event Bus) | 이벤트를 생성하고, 전달하며, 처리하는 중계 역할을 하는 시스템입니다. |
💡 이벤트-버스 패턴(Event-Bus Pattern) 처리과정
1. 게시자(Publisher)
- 이벤트 소스는 특정 조건이 충족되면 이벤트를 생성합니다. 이 이벤트는 일반적으로 상태 변경이나 특정 행동에 의해 발생합니다.
2. 게시자(Publisher) → (Event) → 이벤트 버스(Event Channel)
- 이벤트를 전달 받은 경우 이벤트 버스로 전달이 됩니다. 이 이벤트 버스에서는 특정 이벤트 채널로 라우팅을 수행합니다.
3. 구독자(Subscriber) = 이벤트 리스너(Event Listener)
- 특정 채널만 구독하고 있던 구독자만 반응하여 이벤트가 전달되어, 해당 이벤트를 기반으로 처리를 수행합니다.
4. 이벤트 리스너가 이벤트를 처리한 후, 해당 이벤트는 소멸됩니다.
1. 이벤트-버스 패턴 사용 사례 : FCM Push Notification
💡 이벤트-버스 패턴 사용 사례 : FCM Push Notification
- 해당 패턴을 사용하는 사례는 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 라이브러리를 통해 알람을 통해 푸시 메시지를 띄어줍니다.
💡 [참고] 해당 내용들에 대해 더 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
9) MVC 패턴(Model-View-Controller Pattern)
💡 MVC 패턴(Model-View-Controller Pattern)
- MVC는 Model-View-Controller로 애플리케이션을 세 가지의 계층으로 구분한 방법론을 의미합니다.
- 사용자가 처음 페이지를 출력하는 경우 Controller로 요청이 발생하고 Model에서 데이터를 가져와서 그 정보를 바탕으로 시각적 표현인 View를 그려주는 아키텍처 패턴을 의미합니다.
구성 요소 | 설명 |
모델(Model) | 데이터와 그 데이터를 처리하는 비즈니스 로직을 담당. 데이터를 저장하고, 필요한 데이터를 컨트롤러에게 제공하며, 데이터가 변경 되었을 때 뷰에게 알립니다. |
뷰(View) | 사용자에게 보여지는 UI 부분을 담당. 사용자가 볼 수 있는 화면을 구성하고, 사용자의 입력을 받아 컨트롤러에게 전달합니다. |
컨트롤러(Controller) | 사용자의 입력을 처리하고, 그에 따라 모델과 뷰를 업데이트. 사용자의 요청을 해석하고, 적절한 모델의 메서드를 호출하거나, 뷰를 변경하여 사용자에게 응답합니다. |
1. MVC 패턴 사용사례: 서버 내에서 템플릿 엔진을 이용한 웹 서버 구축
💡 MVC 패턴 사용사례: 서버 내에서 템플릿 엔진을 이용한 웹 서버 구축
1. Client → ControllerController
- 사용자는 클라이언트에 해당하는 브라우저를 접근하여 Controller에게 브라우저 화면을 요청합니다.
2. Controller → Service
- Controller에서는 비즈니스 로직을 처리하는 Service 메서드를 호출합니다.
3. Service → DAO
- Service에서는 DB 데이터 조작을 위한 처리로 DAO를 호출합니다
4. DAO → DB
- DAO는 DB를 접근하여 데이터를 조회에 대한 요청을 합니다
5. DB → DAO
- DAO에서는 DB로 받은 데이터를 반환받습니다
6.DAO → Service
- DAO에서는 DB 데이터를 가공을 하여 Service로 반환해줍니다.
7. Sevice → Controller
- Service에서는 가공된 DB 데이터를 받아서 비즈니스 로직 처리를 한 후 Controller로 반환해줍니다.
8. Controller → View : Server Side Rendering
- Controller에서는 데이터를 전달받아 View에 그려주어서 일괄 출력합니다
9. View → Browser
- View에서는 Browser로 사용자에게 화면을 제공합니다
10) 블랙보드 패턴(Blackboard Pattern)
💡 블랙보드 패턴 (Blackboard Pattern)
- 명확하게 정의되지 않은 문제이거나 복잡한 문제에 대해 각각의 문제를 '서브 문제'로 분할하고 이 서브 문제들을 여러 개의 '독립적인 시스템'을 통하여 동시에 해결하도록 하는 방식으로 동작하는 패턴입니다.
- 이러한 독립적인 시스템에서 해결된 문제는 '블랙보드'에 해결책을 게시합니다.
블랙보드 패턴의 구성요소 | 설명 |
블랙보드(Blackboard) | 지식 소스들이 정보를 공유하고 문제를 해결하기 위한 결과를 저장하는 중앙 장소입니다. 모든 시스템이 접근하고 수정 할 수 있습니다. |
지식 소스(Knowledge Sources) | 문제를 해결하는 데 필요한 전문성을 가진 독립적인 시스템입니다. 각각 지식 소스는 블랙보드에 있는 정보를 사용해서 문제의 일부를 해결하고 결과를 블랙보드에 저장합니다. 이렇게 함으로써 다른 지식 소스들의 결과를 참조하거나 사용할 수 있습니다. |
제어 요소(Controller) | 문제 해결 과정을 조정합니다. 블랙보드에 있는 정보를 바탕으로 어떤 지식 소스가 다음으로 활동할지 결정하며 문제 해결 과정이 유기적으로 진행 될 수 있도록 합니다. |
1. 블랙보드 패턴 사용사례 : 차량 식별 및 추적
💡 블랙보드 패턴 사용사례 : 차량 식별 및 추적
1. 블랙보드 패턴
- 차량 식별 및 추적시스템에서 여러 지식 소스(Knowledge Sources)들이 독립적으로 작동하여 각각의 전문성에 따라 차량을 식별하고 추적 작업을 수행합니다.
2. 지식 소스(Knowledge Sources)
- 하나의 지식 소스는 차량의 번호판을 인식하는 작업을 담당하고 다른 하나는 차량의 모델을 식별하는 작업을 수행하고, 또 다른 하나는 차량의 색상을 식별하는 작업을 각각 수행할 수 있습니다.
- 이러한 각각의 지식소스는 자신의 작업 결과를 블랙보드에 저장하며 이 정보는 다른 지식 소스에게 참조되거나 사용될 수 있습니다.
3. 제어요소(Controller)
- 제어요소에서는 모든 과정을 조정합니다. 블랙보드에 저장된 정보를 바탕으로 어떤 지식 소스가 다음으로 활동할지 결정하며 이러한 방식으로 차량 식별 및 추적 작업이 유기적으로 진행될 수 있게 합니다.
- 주어진 언어에 대해 그 언어의 문법을 위한 표현을 정의하고 이 언어로 작성된 문장을 해석하는 해석기(Interpreter) 사용하여 해당 언어로 작성된 문자을 해석하는 아키텍처 패턴을 의미합니다.
- 주로 문법 트리를 구성하고 이 트리를 통해 문장을 해석하는 데 사용됩니다. 각각 문법 규칙은 고유 클래스로 표현되고 문장의 각 부분은 이 클래스의 인스턴스로 표현이 됩니다.
- 해당 경우는 문제가 간단할 때 사용하는 것이 가장 좋습니다. 복잡한 문제의 경우, 문법 트리가 너무 크고 복잡해져서 관리하기 어려워질 수 있습니다. 따라서 이 패턴은 간단한 문맥에 대한 문법만 필요한 경우, 예를 들어 간단한 계산기나 정규 표현식 등에 적합합니다.
- 이 패턴은 특히 프로그래밍 언어 컴파일러 디자인과 SQL 파싱 같은 언어 기반의 연산에서 사용됩니다.
11) 인터프리터 패턴(Interpreter Pattern)
💡 인터프리터 패턴(Interpreter Pattern)
- 주어진 언어에 대해 그 언어의 문법을 위한 표현을 정의하고 이 언어로 작성된 문장을 해석하는 해석기(Interpreter) 사용하여 해당 언어로 작성된 문자을 해석하는 아키텍처 패턴을 의미합니다.
- 주로 문법 트리를 구성하고 이 트리를 통해 문장을 해석하는 데 사용됩니다. 각각 문법 규칙은 고유 클래스로 표현되고 문장의 각 부분은 이 클래스의 인스턴스로 표현이 됩니다.
- 해당 경우는 문제가 간단할 때 사용하는 것이 가장 좋습니다. 복잡한 문제의 경우, 문법 트리가 너무 크고 복잡해져서 관리하기 어려워질 수 있습니다. 따라서 이 패턴은 간단한 문맥에 대한 문법만 필요한 경우, 예를 들어 간단한 계산기나 정규 표현식 등에 적합합니다.
- 이 패턴은 특히 프로그래밍 언어 컴파일러 디자인과 SQL 파싱 같은 언어 기반의 연산에서 사용됩니다.
구성요소 | 설명 |
추상 표현식 (Abstract Expression) | 모든 노드에 대해 공통의 메서드로 추상 표현식을 정의합니다. interpret()라는 메서드를 통해 해석 작업을 수행하는 메서드를 선언합니다. |
터미널 표현식(Terminal Expression) | 추상 표현식을 상속받아 구현한 클래스로 문법의 ‘가장 작은 단위’를 나타냅니다. |
비터미널 표현식(Nonterminal Expression) | 추상 표현식을 상속받아 구현한 클래스로 문법의 ‘복잡한 부분’을 나타냅니다. 비터미널 표현식은 다른 표현식을 포함할 수 있습니다. |
컨텍스트 (Context) | 표현식을 해석하는데 필요한 정보를 담고 있는 클래스입니다. |
클라이언트 (Client) | 표현식을 구성하고 해석하는 역할을 합니다. |
💡 인터프리터 패턴 처리과정
1. Context 생성
- 정규식을 해석할 Context를 생성합니다.
- Context에는 정규식 문자열이 저장되며, 이 문자열은 인터프리터가 해석할 대상입니다.
2. 표현식 구성(Expression Configuration)
- 정규식을 구성하는 표현식을 생성합니다.
- 이는 터미널 표현식(TerminalExpression)과 비터미널 표현식(NontermianlExpression)의 조합으로 이루어집니다.
- 예를 들어, [0-9]+라는 정규식은 '0-9'라는 터미널 표현식과 '+'라는 비터미널 표현식으로 구성될 수 있습니다.
3. 표현식 해석(Expression Interpreter)
- 생성된 표현식을 사용하여 Context 내의 정규식을 해석합니다.
- 각 표현식은 자신이 해석할 부분을 해석하고, 결과를 반환합니다.
4. 결과 반환
- 마지막으로, 인터프리터는 해석된 결과를 반환합니다.
- 이 결과는 정규식이 매칭되는지 아닌지, 매칭된다면 어떤 부분이 매칭되는지 등의 정보를 포함할 수 있습니다.
1. 인터프리터 패턴 사용사례 : 정규 표현식
💡 인터프리터 패턴 사용사례 : 정규 표현식
1. Expression 클래스
- 추상 클래스로, 모든 표현식이 구현해야 하는 'interpret' 메서드를 정의합니다.
- 이 메서드는 주어진 문자열이 표현식에 맞는지 판단합니다.
2. TerminalExpression 클래스
- 'Expression' 클래스를 상속받은 터미널 표현식 클래스입니다.
- 이 클래스는 생성자로 받은 문자열이 주어진 컨텍스트에 포함되어 있는지를 판단합니다.
3. OrExpression 클래스
- 'Expression' 클래스를 상속받은 비터미널 표현식 클래스입니다.
- 이 클래스는 두 표현식 중 하나라도 주어진 컨텍스트에 맞으면 참을 반환합니다.
4. Client 클래스
- 'Expression' 클래스를 상속받은 표현식들을 생성하고 'interpret' 메서드를 호출하여 결과를 출력하는 클라이언트 클래스입니다.
- 여기서는 '[0-9]' 또는 '+'가 "123+456"에 포함되어 있는지를 확인합니다.
// 추상 표현식
public abstract class Expression {
public abstract boolean interpret(String context);
}
// 터미널 표현식
public class TerminalExpression extends Expression {
private String data;
public TerminalExpression(String data){
this.data = data;
}
public boolean interpret(String context){
if(context.contains(data)){
return true;
}
return false;
}
}
// 비터미널 표현식
public class OrExpression extends Expression {
private Expression expr1 = null;
private Expression expr2 = null;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
// 클라이언트
public class Client {
public static void main(String[] args) {
Expression isNumber = new TerminalExpression("[0-9]");
Expression isPlus = new TerminalExpression("+");
Expression isNumberPlus = new OrExpression(isNumber, isPlus);
System.out.println("Context: 123+456");
System.out.println("Interpreter Result: " + isNumberPlus.interpret("123+456"));
}
}
오늘도 감사합니다. 😀
반응형
'공통 > 아키텍처' 카테고리의 다른 글
[공통/아키텍처] 이벤트 기반 아키텍처(EDA: Event-Driven Architecture) 이해하기 -1 : 정의 및 특징, 주요 모델 (0) | 2024.05.26 |
---|---|
[공통/아키텍처] 소프트웨어 아키텍처 10가지 패턴 -1 : 계층, 클라이언트-서버, 마스터-슬레이브, 파이프-필터, 브로커 패턴 (2) | 2024.03.24 |