본문 바로가기
1. 개발/1.8. ActiveMQ

Artemis에서 'Database'를 저장소로 쓸 때의 스키마 구조는?

by 엉짱 2026. 4. 3.
반응형

Artemis에서 'Database'를 저장소로 쓸 때의 스키마 구조는?

엔터프라이즈 환경에서 메시지 브로커(ActiveMQ Artemis)를 구축할 때, 데이터의 영속성(Persistence)을 보장하기 위해 기본적으로 로컬 파일 시스템(AIO/NIO 저널)을 사용합니다. 하지만 이중화(HA) 구성을 위한 '공유 스토리지(Shared Store)'가 필요하거나, 사내 인프라 표준화 정책으로 인해 모든 상태 데이터를 관계형 데이터베이스(RDBMS)에 통합해야 하는 경우가 있습니다.

Artemis는 JDBC(Java Database Connectivity) 인터페이스를 통해 Oracle, MySQL, PostgreSQL 등 대부분의 상용 데이터베이스를 메시지 저장소로 활용할 수 있는 강력한 기능을 제공합니다.

많은 엔지니어들이 데이터베이스를 저장소로 쓴다고 하면, MESSAGE 테이블에 SENDER, RECEIVER, PAYLOAD 같은 수많은 컬럼이 예쁘게 정규화되어 있을 것이라 상상합니다. 하지만 브로커가 요구하는 극한의 I/O 속도를 RDBMS에서 뽑아내기 위해, Artemis는 데이터베이스를 전혀 다른 차원의 'Raw 블록 디바이스'처럼 취급합니다. 이 가이드에서는 Artemis가 RDBMS 내부에 구축하는 스키마의 본질적인 구조와 5가지 핵심 테이블의 역할을 상세히 해부합니다.


1. 관계형 매핑(ORM)의 포기와 BLOB 스토리지로의 전환

Artemis JDBC 스토리지 아키텍처의 가장 중요한 핵심은 관계형 데이터 모델링을 철저히 배제했다는 점입니다.

초당 수만 건의 메시지가 쏟아지는 환경에서, 메시지의 헤더(Header)와 속성(Property), 본문(Body)을 일일이 파싱하여 SQL 컬럼에 맞게 INSERT 하는 작업은 심각한 CPU 오버헤드와 데이터베이스 인덱스 병목을 유발합니다.

따라서 Artemis는 메시지 객체 전체를 잘게 부수지 않고, 통째로 직렬화(Serialization)하여 거대한 바이트 배열(Byte Array)로 변환합니다. 그리고 이 바이너리 덩어리를 데이터베이스의 BLOB (Binary Large Object) 컬럼에 그대로 쑤셔 넣습니다. 즉, RDBMS를 사용하지만 내부적으로는 Key-Value(키-값) 저장소처럼 단순 무식하게 동작시켜 디스크 쓰기 속도를 극대화하는 전략을 취합니다.


2. Artemis가 자동 생성하는 5대 핵심 테이블

broker.xml 설정 파일에 JDBC 연결 정보(<database-store>)를 입력하고 브로커를 최초로 기동하면, Artemis는 데이터베이스에 접속하여 다음의 5가지 핵심 테이블을 자동으로 생성(DDL)합니다. 관리자가 별도로 테이블 생성 스크립트를 실행할 필요가 없습니다.

A. 메시지 테이블 (MESSAGE_TABLE)

가장 트래픽이 많고 거대한 테이블입니다. 프로듀서가 보낸 모든 일반적인 영속성(Persistent) 메시지와 컨슈머의 수신 확인(ACK) 상태가 이곳에 기록됩니다.

  • 구조적 특징: 기존 파일 저널(Journal) 방식과 동일하게 'Append-Only(추가 전용)' 방식으로 동작합니다. 메시지의 생성(Add)과 삭제(Delete/ACK)가 각각 개별적인 트랜잭션 레코드로 INSERT 됩니다.
  • 저장 방식: 레코드의 고유 ID와 함께 메시지 페이로드가 BLOB 컬럼에 저장됩니다. 브로커는 백그라운드 스레드를 통해 정기적으로 이 테이블을 쿼리하여, 이미 처리가 완료된(ACK된) 메시지 레코드들을 일괄 삭제(Cleanup)하여 테이블의 크기를 유지합니다.

B. 바인딩 테이블 (BINDINGS_TABLE)

메시지 브로커의 '뇌'에 해당하는 토폴로지 정보를 저장하는 테이블입니다.

  • 구조적 특징: 어떤 큐(Queue)가 생성되어 있는지, 어떤 주소(Address)에 어떤 라우팅 타입(Anycast/Multicast)이 바인딩되어 있는지에 대한 메타데이터를 보관합니다.
  • 운영 특징: 메시지 테이블과 달리 트래픽이 거의 없습니다. 관리자가 새로운 큐를 생성하거나 삭제할 때만 업데이트되므로 사이즈가 매우 작게 유지됩니다.

C. 대용량 메시지 테이블 (LARGE_MESSAGE_TABLE)

Artemis의 메모리 한계를 초과하는 수십, 수백 메가바이트짜리 대용량 파일(Large Message)을 처리하기 위한 전용 테이블입니다.

  • 구조적 특징: 1GB짜리 메시지를 하나의 레코드로 DB에 넣으면 데이터베이스의 트랜잭션 로그가 터지거나 Out Of Memory가 발생할 수 있습니다. 따라서 이 테이블은 거대한 메시지를 100KB 등의 작은 청크(Chunk) 단위로 쪼개어 여러 개의 로우(Row)로 분산 저장하는 구조를 가집니다.
  • 장점: 컨슈머가 이 대용량 메시지를 다운로드할 때, 브로커는 DB에서 청크를 순차적으로 스트리밍하여 메모리 고갈 없이 안전하게 전달할 수 있습니다.

D. 페이징 테이블 (PAGE_STORE_TABLE)

브로커의 메모리가 가득 차서 더 이상 메시지를 수용할 수 없을 때, 시스템 붕괴를 막기 위해 임시로 메시지를 디스크로 밀어내는 '페이징(Paging)' 작업에 사용되는 테이블입니다.

  • 구조적 특징: 메모리에 있어야 할 비영속(Non-Persistent) 메시지들까지도 이 테이블의 BLOB 영역으로 피신하게 됩니다. 큐의 메모리에 여유가 생기면(Depaging), 브로커는 이 테이블에서 데이터를 다시 읽어 들인 후 레코드를 삭제합니다.

E. 노드 매니저 테이블 (NODE_MANAGER_STORE_TABLE)

데이터베이스 공유(Shared Store) 방식을 통해 고가용성(HA) 클러스터를 구성할 때, '스플릿 브레인(Split Brain)' 현상을 완벽하게 방어하는 가장 핵심적인 테이블입니다.

  • 구조적 특징: 이 테이블에는 마스터(Primary) 브로커와 슬레이브(Backup) 브로커 간의 상태 정보를 동기화하는 데 필요한 고유 Node ID가 저장됩니다.
  • 동작 원리 (DB Lock): 클러스터가 구동되면 마스터 브로커가 이 테이블의 특정 로우(Row)에 대해 데이터베이스 레벨의 배타적 락(Exclusive Row Lock)을 획득합니다. 백업 브로커는 이 락을 얻기 위해 끝없이 대기(Polling)합니다. 만약 마스터 서버가 죽어 데이터베이스 커넥션이 끊어지면, RDBMS는 자동으로 해당 락을 해제합니다. 그 순간 대기하던 백업 브로커가 락을 쟁취하고 새로운 마스터로 승격(Failover)합니다.

3. JDBC 스토어 아키텍처 적용 시 주의사항 (Best Practices)

데이터베이스를 브로커의 저장소로 사용할 때, 파일 시스템 기반의 저널보다 필연적으로 디스크 I/O 속도가 느려질 수밖에 없음을 아키텍트는 반드시 인지해야 합니다. 성능 저하를 방어하기 위해 다음과 같은 튜닝이 필수적입니다.

  1. Connection Pooling 최적화: 브로커 내부적으로 데이터베이스와 통신하기 위해 커넥션을 맺고 끊는 오버헤드를 없애야 합니다. Artemis 설정에서 JDBC 네트워크 지연을 최소화할 수 있도록 충분한 크기의 커넥션 풀(Connection Pool)을 구성하고 유지해야 합니다.
  2. 네트워크 지연(Network Latency) 최소화: 브로커 서버와 RDBMS 서버는 물리적으로 가장 가까운 네트워크 스위치에 위치해야 합니다. 브로커가 DB의 ACK 응답을 기다리는 시간이 길어질수록 전체 시스템의 메시지 처리량(TPS)은 곤두박질칩니다.
  3. DB 레벨의 Vacuum / 튜닝: MESSAGE_TABLE은 쉴 새 없이 INSERTDELETE가 반복되는 가혹한 환경입니다. PostgreSQL의 Auto-vacuum 주기를 타이트하게 잡거나, Oracle의 Undo 테이블스페이스를 넉넉히 확보하여 테이블 단편화(Fragmentation)로 인한 성능 하락을 OS와 RDBMS 레벨에서 방어해야 합니다.

결론적으로 Artemis의 JDBC 스토리지는 RDBMS를 마치 거대한 외장 하드디스크의 블록 스토리지처럼 사용하는 극단적이고 영리한 아키텍처입니다. 테이블의 관계형 구조를 분석하려 하기보다는, 브로커가 BLOB 데이터와 DB 락(Lock)을 활용하여 어떻게 성능과 가용성을 동시에 쟁취하는지 그 메커니즘을 이해하는 것이 인프라 운영의 핵심입니다.

반응형