일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 스프링부트
- 운영체제
- 프로그래머스
- 도커
- 코딩테스트
- 개발자
- programmers
- 알고리즘
- DPDK
- Kakao
- 네트워크
- 스프링
- C
- 리눅스
- 캐시
- docker
- Elasticsearch
- 자바
- Linux
- Spring
- 엘라스틱서치
- 파이썬
- 백엔드
- springboot
- 쿠버네티스
- 프로그래머스 #카카오 #IT #코딩테스트
- Java
- 카카오
- IT
- Python
- Today
- Total
저고데
[Spring Boot]6. MVC와 웹소켓을 사용한 이벤트 기반 시스템 만들기 본문
어플리케이션을 운영할 때는 다른 어플리케이션이나 서비스와의 최종 사용자 간의 상호작용을 신경써야할 때도 있다.
MVC는 1장에서 언급했듯이, Model, View, Controller를 뜻하며, 어플리케이션을 구현하는 데 중요한 역할을 한다.
스프링 부트 어플리케이션은 백엔드 뿐만 아니라 사용자와의 직접적인 상호작용도 할 수 있다.
JSP는 오래된 기술이고 현재 최근에는 대부분 HTML과 JS를 섞은 조합을 구현하여 프론트엔드와 활용하거나 더 유용한 템플릿 엔진을 사용한다.
먼저, 템플릿 엔진을 알아보자
템플릿 엔진
템플릿 엔진은 사용자의 브라우저에서 실행되고 표시될 최종 페이지를 생성한다.
즉, 눈에 보이는 화면을 만들어낸다.
서버 사이드 어플리케이션을 위한 방법을 제공한다.
그 중에서도 Thymeleaf가 제일 많이 사용되고 스프링 MVC와 스프링 웹플럭스 어플리케이션을 지원한다.
템플릿 파일을 HTML로 제공하기 때문에 서버가 없이도 템플릿을 작성할 수 있다.
스프링 부트와 스프링 MVC, Thymeleaf를 사용해 만든 어플리케이션 코드는 Github에서 볼 수 있다.
다만 특이한 점은 이전에는 @Controller와 @ResponseBody를 합친 @RestController를 사용한 반면, 사용자 인터페이스가 있는 어플리케이션을 만드는 것이기 때문에 @Controller를 사용해서 그 클래스 내의 @RequestMapping 등을 사용한다.
이때, 어노테이션이 달린 메서드는 확장자를 제외한 템플릿 파일명을 문자열 값을 반환한다.
"pageone"을 반환하면 pageone.html 템플릿을 반환한다.
메시징 플랫폼으로 메시지 전달하기
앞서 만든 페이지는 현재 상공에 있는 비행기에 관한 정보를 전달하는 페이지이다.
html 파일에 5초마다 한 번씩 자동으로 새로고침하여 최신 데이터를 전달하게 해주는 기능이 있는데, 잠재적인 문제가 있다.
업데이트된 데이터를 주기적으로 요청한다면 데이터가 여러 번 오가면서 요청과 응답이 다소 빈번해진다는 것이다.
만약 여러 사용자가 요청을 한다면 네트워크 트래픽이 상당해질 것이다.
따라서 pull mode, push model로 전환하는 것이 중요하다.
보통은 메시지가 도착할 때까지 대기하도록 메시지 소비 어플리케이션을 먼저 실행하는 것이 좋다.
그리고 pull 기반을 통해서 http 요청을 수신한 후에 푸시하는 것이 아니라, 독립적으로 앱을 푸시하기 때문에 완전한 이벤트 기반 시스템에 더 가까운 구조를 만들 수 있다.
RabbitMQ와 Kafka 너흰 누구니?
메시징 플랫폼은 어플리케이션 간 메시지를 효율적으로 수락, 라우팅, 전달하기 위해 만들어졌으며, 대표적으로 RabbitMQ, apache kakfa 등이 있다.
메시징 플랫폼은 클라이언트와 서버 간 통신에서 중간 매개체로서 동작하여 효율적이고 확장 가능한 메시지 전달을 제공한다.
클라이언트와 서버가 직접 통신하지 않고 메시징 플랫폼을 통해 메시지를 교환함으로써 여러 가지 이점을 얻을 수 있다.
분산 시스템에서 애플리케이션 간 메시지 교환을 지원하는 하기 때문에 메시징 플랫폼은 메시지 큐를 통해 메시지를 안전하게 전송하고 보관한다.
메시지 큐는 발신자(Producer)가 메시지를 생성하고 수신자(Consumer)가 메시지를 소비할 때까지 중간에 메시지를 보관하는 역할을 한다.
즉, 데이터 스트림(트래픽)이 발생하면 대규모의 양을 분산하여 전달하기 때문에 비동기적이며 효율적으로 작업을 수행한다.
말도 너무나도 어려운 .. 스프링 클라우드 스트림
스프링 부트에는 메시지 파이프라인을 활용하기 위한 옵션이 있는데, 대표적으로 스프링 클라우드 스트림이 있다.
이는 마이크로서비스 아키텍처에서 이벤트 기반 마이크로서비스를 구축하는 데 사용되는 프레임워크이다.
메시지 브로커(예: Apache Kafka, RabbitMQ)를 통해 이벤트를 생성, 소비, 전파하는 추상화를 제공하여 간단하고 확장 가능한 이벤트 기반 아키텍처를 쉽게 구현할 수 있도록 도와준다.
Binder는 메시지 브로커와의 연결을 관리하는 추상화 계층이 필요하며, RabbitMQ, Apache Kafka 등 여러 브로커와 통합할 수 있다.
Binding은 application.properties에서 지정할 수 있으며, in 또는 out에 따라, 채널 번호에 따라서 이름을 사용한다.
뿐만 아니라, 스트리밍 플랫폼 드라이버와 스프링 클라우드 스트림 사이를 Binder가 자동으로 연결해주기 때문에 개발자는 이를 신경 쓸 필요가 없다.
스프링 클라우드 스트림을 사용하면 추상화 수준을 향상할 수 있고 어플리케이션의 속성, 빈, 직접 설정 구성하기를 이용하여 스프링 클라우드 스트림에서 지원하는 플랫폼의 고유 속성에 엑세스할 수 있다.
스프링 크라우드 스트림은 Suppier, Function, Consumer 등의 표준 자바 개념과 인터페이스로 구축된 스프링 클라우드 함수를 토대로 만들어진다.
따라서 불완전한 추상화를 제거하고 핵심 언어 구조로 대체할 수 있다.
Supplier는 데이터를 생성하고 메시지 브로커로 전송하는 역할을 한다.
Function은 입력 데이터를 받아 처리하고 결과를 출력하는 역할을 한다.
즉, 입력과 출력이 모두 있으며, 메시지를 다른 종류로 변환한다.
Consumer는 메시지 브로커로부터 데이터를 수신하고 해당 데이터를 처리하는 역할을 한다.
Consumer Bean은 메시지가 수신될 때마다, 인메모리 데이터 저장소를 접근하여 명령을 수행하는 특징이 있다.
이러한 Supplier, Consumer, Function은 스프링 클라우드 스트림에서 메시지 브로커와 통신하며 마이크로서비스 간에 데이터를 효과적으로 교환할 수 있도록 지원합니다.
Consumer의 그룹을 지정하지 않는다면? Pan-out Pattern
Consumer에 그룹을 지정하지 않으면 어떻게 될까?
물론 그룹을 지정하는 것은 필수가 아니다, 하지만 메시지-컨슈밍 어플리케이션이 그룹을 지정하지 않으면 바인더(kafka, rabbitMQ)는 무작위로 고유한 이름을 만들어서 저장하고, Consumer를 바인더 인스턴스나 클러스터 내의 자동 삭제 큐에 할당한다.
따라서, 생성된 각각의 큐는 오직 단 하나의 Consumer에 의해서 서비스된다.
이를 어떻게 활용할 수 있을까?
메시지가 바인더에 도착할 때마다 메시지의 복사본들이 기본적으로 해당 바인더에 할당된 모든 큐로 자동으로 경로가 지정된다.
바인더에 여러 큐가 있다면, 모든 큐에 동일한 메시지의 복사본이 전송된다는 것이다.
이를 Fan-out Pattern이라고 하는데, 해당 패턴은 다양한 요구사항을 충족하기 위해 각 메시지를 수많은 목적지로 전달할 때 사용된다.
Consumer의 그룹을 지정한다면? Competing Consumer Pattern
그렇다면 이번에는 그룹을 지정한다고 하자.
해당 그룹의 이름은 바인더 내에서 기본적인 큐 이름으로 사용된다.
여러 어플리케이션에서 동일한 그룹 속성을 지정하여 동일한 큐에 연결한다면, 해당 큐에 도착하는 각 메시지를 한 Consumer만이 처리하는 경쟁 컨슈머 패턴을 만든다.
이런 식으로 Consumer의 개수를 조정하여 다양한 양의 메시지(트래픽)를 수용할 수 있다.
웹소켓
앞서 pull 기반으로 만들어진 표준 요청-응답 의미 체계는 수많은 사용 사례에서 훌륭하게 작동하지만, 응답 서버가 요청 서버로부터 요청을 받지 않고 자체적으로 전송을 시작하기엔 역부족이다.
해당 문제점을 해결하기 위해서 사용되는 방법 중에 하나가 바로 웹소켓이다.
웹소켓은 단일 TCP 연결을 통해 두 시스템을 연결하는 양방향 통신 프로토콜이다.
오버헤드(간접비용)가 낮은 브로드캐스트와 채팅 타입의 시스템이 가능해진다.
웹소켓을 사용하면 백엔드 어플리케이션에서 페이지를 새로고침할 필요 없이 브라우저에 자유롭게 업데이트를 푸시하고 정보를 전달할 수 있다.
오늘 구현한 코드의 종류
1. Thymeleaft 뷰 기술과 스프링 부트 기술을 활용한 풀 기반 정적 컨텐츠 처리
2. RabbitMQ를 사용한 풀, 푸시 기반 모델.(프론트엔드 기능은 사용자에게 표시되는 결과를 업데이트하기 위해서는 수동으로 새로고침, 하드코딩 해야함)
3. 웹소켓을 사용한 업데이트 내용 자동 송수신으로 실시간 컨텐츠 처리. (http 통신 시 필요한 요청-응답 패턴 없어도 됨. 오버헤드 낮음.)
'Spring Boot' 카테고리의 다른 글
[Spring Boot]8. 테스트 코드를 작성해보자 (0) | 2023.12.30 |
---|---|
[Spring Boot]7. 스프링 부트에서 리액티브란? (1) | 2023.12.29 |
[Spring Boot]5. 다양한 데이터베이스와 연결하기 (1) | 2023.12.27 |
[Spring Boot]4. Actuator! 환경 설정을 유연하게 만들기 (0) | 2023.12.24 |
[Spring Boot]3. 데이터베이스를 연결해보자 (1) | 2023.12.24 |