FireDrago
[치즈픽] 하이브리드 아키텍쳐 도입기 (OCI + Home Server) 본문

치지직의 상위 N개의 방송을 동적으로 인식하고, 자동으로 하이라이트 타임스탬프를 찍는 '치즈픽' 서비스를 배포했다.
실시간 방송 채팅 데이터를 수집하고 분석하는 엔진 특성상 Kafka와 Redis를 구동하고 연산을 처리하기 위해 꽤 큰 메모리와 CPU 성능이 필요했다. AWS 에서 구동하기 위해서는 꽤 큰 비용이 예상됐다. 그래서 역할별로 모듈을 구분하고, 홈서버와 오라클 클라우드에 나누어 배치했다. 그 과정을 알아보자
1. 인프라 역할 분리 (Cloud vs On Premise)
핵심은 모듈간의 역할을 분리하는 것이다.
- Engine (Home Server): 웹소켓 채팅 수집, Kafka 메시지 큐잉, 실시간 화력 분석 등 메모리와 연산이 많이 필요한 무거운 작업은 로컬 홈 서버(On-Premise)에 배치하여 인프라 비용을 줄였다. 30초 마다 치지직 API를 호출하여 최신 방송 정보를 호출하고, 이를 기반으로 웹소켓을 연결하여 3초마다 채팅을 카프카에 큐잉한다. 이벤트 기반 구조로 분리된 분석단은 레디스를 이용하여, 채팅의 화력을 분석하고 하이라이트를 감지하여 3초마다 하트비트의 형식으로 API-Server에 Push 한다.
- API-Server (Oracle Cloud): 분석이 끝난 데이터를 서빙하고, 유저 트래픽을 직접 받아내는 API 서버는 24시간 안정적으로 돌아가야 한다. 따라서 높은 가용성을 보장하는 OCI(Oracle Cloud Infrastructure) 무료 티어에 배치했다. Engine으로 부터 전송받은 실시간 방송 정보, 채팅 화력 수치, 하이라이트 여부를 DB에 저장하고 클라이언트에게 전달하는 역할을 한다.
이렇게 모듈을 분리하여 인프라 유지비용을 0으로 줄이면서도, 높은 트래픽과 리소스 성능을 확보할 수 있었다.
물론 집 노트북 전기세가 있긴하지만 저전력 12코어 CPU를 사용하고, 리눅스 설치, 배터리 최적화를 통해 클라우드에 비해 높은 리소스 성능을 활용할수 있었다.
2. 온 프레미스 환경의 보안 (Cloudflare Tunnel)
물리적으로 분리된망 (집 < -> 클라우드)에서 데이터를 안전하게 넘길지도 중요한 문제였다. ` 두가지 취약점이 있는데, 홈 서버의 네트워크 개방과 데이터 전송 구간의 탈취 위험이다. 통신사 환경은 IP가 고정되지 않는 문제와 외부 노출이라는 보안 위험을 해결하기위해 인프라와 애플리케이션 구 가지 계층에서 보안을 구축했다.
인바운드 통제 : Cloudflare 터널과 Zero Trust

일반적으로 외부에서 홈 서버에 접속하려면 공유기의 포트를 열고 기다리는 포트포워딩이 필수적이다. 하지만 전세계에 우리집 네트워크 문을 열어놓는 것과 같다. 이를 해결하기 위해 `Cloudflare Tunnel`을 도입했다.
이 기술의 핵심은 외부의 '인바운드'를 기다리는 대신, 홈 서버 내부에 설치된 데몬이 Cloudflare의 글로벌 엣지 네트워크를 향해 먼저 '아웃바운드' 터널을 뚫어 연결을 유지하는 것이다. 결과적으로 공유기의 포트를 하나도 열지 않아도 된다. 모든 외부 접근은 홈서버가 아닌 cloudflare 엣지 서버로 향하며, 유동 IP 문제와 물리적 IP 노출을 완벽하게 제거할 수 있다. 심지어 무료티어로 이 기능을 사용할 수 있다.
3. 망 분리 환경의 데이터 전송 보안 (Engine -> Api-Server)
아웃바운드 및 데이터 전송 방어: HTTPS와 커스텀 시크릿 헤더
홈 서버를 보호했다면, 다음은 `Engine`이 3초마다 분석 결과를 OCI의 `API-Server`로 전송하는 구간의 보안이다. 이 과정에서 보안 처리가 없으면, 허가받지 않은 제3의 사용자가 API 서버의 엔드포인트를 알아내어 가짜 분석 데이터를 전송할 위험이 있다. 이를 해결하기 위해 먼저 API 서버의 수신 엔드포인트 URL을 환경변수 (env)로 숨기고, 전송 구간 전체에 HTTPS를 적용했다. 중간에 누군가가 패킷을 가로채어 훔쳐 볼 수 없다록 했다.
다음으로 애플리케이션 계층에서 검증을 구축했다. `Engine`이 API 서버로 보낼 때, 사전에 서버 간에 약속된 '보안 헤더'를 패킷에 포함하도록 설계했다. `API-Server`는 필터를 통해 이 헤더를 검사하고 고유한 헤더값이 없거나 일치하지 않는 외부의 요청은 비지니스 로직에 도달하기 전에 필터 단에서 차단하도록 했다.
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String requestPath = request.getRequestURI();
if (pathMatcher.match(signalPath + "/**", requestPath) ||
pathMatcher.match(syncPath + "/**", requestPath)) {
String requestToken = request.getHeader(headerName);
if (requestToken == null || !requestToken.equals(expectedSecret)) {
log.warn("유효하지 않은 토큰 접근 차단 : {}", requestPath);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "권한없는 엔진 접근");
return;
}
}
filterChain.doFilter(request, response);
}
4. 통합 모니터링 구축


인프라가 두 군데로 나뉘어 있다 보니 모니터링이 파편화되는 문제가 발생했다. 이를 해결하기 위해 OCI와 홈 서버 각각에 Grafana Alloy를 수집기로 설치했다. 각 서버의 시스템 지표(CPU, RAM), JVM 지표(가상 스레드, 힙 메모리, HikariCP), 그리고 애플리케이션 에러 로그들을 모두 Grafana Cloud로 던져 하나의 Grafana 환경에서 통합 관리 할 수 있도록 구축했다. 모니터링 DB를 직접 띄우지 않아 자원을 아낄 수 있었다.
마무리하며
클라우드와 온프레미스를 결합한 이 하이브리드 아키텍처를 통해 성능, 비용 절감, 보안, 가용성이라는 네 마리 토끼를 모두 잡을 수 있었다. 제한된 자원 속에서도 엔터프라이즈 환경에서 고민할 법한 네트워크 보안과 인프라 분리를 직접 설계하고 많은 것을 배웠다.
'프로젝트' 카테고리의 다른 글
| [치즈픽] 치지직 채팅 화력분석 알고리즘 개선기 (0) | 2026.03.19 |
|---|---|
| [Kafka] Kafka를 사용할때 살펴봐야할 6가지 (2) (0) | 2026.03.03 |
| [Kafka] Kafka를 사용할때 살펴봐야할 6가지 (1) (0) | 2026.02.28 |
| [트러블 슈팅] 비동기 코드가 동기적으로 처리되는 이유 (Java Stream, CompletableFuture) (0) | 2026.02.14 |
| Spring Boot 4.0 & Kafka 4.x NoClassDefFoundError 해결하기 (0) | 2026.02.07 |
