Artemis의 Journal 방식이 'Append-only'를 고수하는 이유는?
엔터프라이즈 메시지 브로커의 핵심 경쟁력은 '단 하나의 메시지도 유실하지 않으면서 얼마나 빨리 처리할 수 있는가'에 달려 있습니다. 차세대 고성능 브로커인 ActiveMQ Artemis는 이를 위해 기존의 관계형 데이터베이스(RDBMS)나 기존 메시지 큐와는 궤를 달리하는 독자적인 스토리지 엔진을 구축했습니다.
그 심장부에 있는 것이 바로 'Append-only(추가 전용)' 저널(Journal) 시스템입니다. 데이터를 덮어쓰거나(Overwrite) 중간에 끼워 넣는 행위를 일절 금지하고, 오직 파일의 맨 끝에 새로운 데이터를 이어 붙이기만 하는 이 극단적인 방식은 현대 고성능 분산 아키텍처의 표준으로 자리 잡았습니다. 이 가이드에서는 Artemis가 왜 이러한 단방향 기록 방식을 철저하게 고수하는지, 그 근본적인 아키텍처와 성능적 이점을 해부합니다.

1. 디스크 물리적 한계 돌파: 순차 쓰기(Sequential Write)의 마법
데이터베이스 성능의 가장 큰 병목은 언제나 물리적 저장 매체인 디스크입니다. 기존 시스템처럼 큐의 중간에 있는 데이터를 지우거나 상태를 업데이트하기 위해 해당 디스크 블록을 찾아가는 방식을 랜덤 I/O(Random I/O)라고 합니다.
- 랜덤 I/O의 치명적 단점: HDD(하드 디스크) 환경에서는 데이터를 찾기 위해 물리적인 디스크 헤드가 트랙을 이동하는 탐색 시간(Seek Time)이 발생하여 성능이 수백 배 하락합니다. SSD(SSD) 환경이라 하더라도 물리적 헤드는 없지만, 데이터를 제자리에서 덮어쓰기 위해 '지우고 다시 쓰는(Erase-and-Write)' 과정을 거쳐야 하므로 쓰기 증폭(Write Amplification) 현상이 발생하고 소자의 수명이 단축됩니다.
- Append-only의 순차 쓰기: 반면 데이터를 오직 파일의 끝에 밀어 넣는 방식은 순차 쓰기(Sequential Write)의 극치입니다. 디스크 헤더가 이동할 필요 없이 한 방향으로 물 흐르듯 데이터를 쏟아냅니다. 이로 인해 디스크의 최대 대역폭을 100% 활용할 수 있으며, 실제 벤치마크 테스트에서 순차 디스크 쓰기는 무작위 메모리(RAM) 쓰기 속도를 능가하는 엄청난 초당 처리량(Throughput)을 발휘합니다.
2. 락(Lock) 경합의 원천 차단과 극단적 동시성(Concurrency)
초당 수만 건의 트랜잭션이 인입되는 환경에서 여러 생산자(Producer) 스레드가 동시에 디스크에 기록을 시도한다고 가정해 보겠습니다.
- 동기화 병목: 만약 특정 메시지의 상태를 제자리에서 수정해야 한다면, 데이터 무결성이 깨지는 것을 막기 위해 반드시 해당 데이터 블록이나 테이블에 무거운 동기화 락(Lock)을 걸어야 합니다. 한 스레드가 락을 쥐고 있는 동안 수백 개의 다른 스레드들은 대기열에 갇혀 CPU 자원을 낭비하게 됩니다.
- Lock-Free 아키텍처: Append-only 저널은 기존 데이터를 절대 건드리지 않습니다. 모든 스레드가 파일의 끝자락(Tail)에 자신의 데이터를 순서대로 추가하기만 하면 되므로, 복잡한 락 메커니즘이 필요 없습니다. Artemis는 멀티플렉싱(Multiplexing) 기법을 활용하여 여러 스레드에서 요청한 수백 개의 작은 메시지들을 메모리 버퍼에 묶은 뒤, 단 한 번의 디스크 플러시(Flush) 연산으로 한꺼번에 일괄 기록(Batch Write)하여 동시성 처리 성능을 극대화합니다.
3. 상태 변화의 기록: 원장(Ledger) 패턴과 불변성(Immutability)
메시지가 큐에 추가되고, 컨슈머에게 전달되고, 최종적으로 삭제되는 모든 생명주기는 Artemis의 저널에서 어떻게 관리될까요? 놀랍게도 '수정'이나 '삭제' 연산은 존재하지 않습니다. 모든 행위는 오직 '추가'로만 기록됩니다.
- 메시지 인입: 생산자가 메시지를 보내면 저널 끝에
ADD레코드가 기록됩니다. - 상태 변경 (트랜잭션): 메시지가 트랜잭션에 묶이면
UPDATE성격의 레코드가 새롭게 끝에 추가됩니다. 기존ADD레코드는 그대로 둡니다. - 메시지 소비 완료: 컨슈머가 메시지를 읽고 ACK(수신 확인)를 보내면, 저널에서 메시지를 지우는 것이 아니라 저널 끝에
DELETE(또는ACK) 레코드를 새롭게 이어 붙입니다.
이처럼 데이터의 과거부터 현재까지 모든 이력이 시간순으로 박제되는 것을 소프트웨어 공학에서는 원장(Ledger) 또는 이벤트 소싱(Event Sourcing) 패턴이라고 부릅니다. 데이터가 한 번 기록되면 영원히 변하지 않는 불변성(Immutability)을 확보하게 됩니다.
4. 시스템 붕괴 시의 완벽한 장애 복원력 (Crash Recovery)
서버 전원 차단이나 커널 패닉 등 치명적인 장애가 발생했을 때, Append-only 방식의 진가가 드러납니다.
데이터를 덮어쓰는 도중에 서버가 꺼지면 데이터의 절반은 과거의 것, 절반은 새로운 것으로 섞이는 코럽션(Corruption) 현상이 발생하여 영구적인 파일 손상으로 이어집니다. 하지만 끝에 추가만 하는 방식에서는 장애가 발생하더라도 마지막 쓰기 작업이 완료되지 못하고 잘려 나갈 뿐, 이전에 기록된 원본 데이터는 100% 안전하게 보호됩니다.
브로커가 재부팅되면 Artemis는 복잡한 데이터베이스 복구 절차를 거칠 필요가 없습니다. 단지 남겨진 저널 파일들을 처음부터 끝까지 순서대로 쭉 읽어 들이며(Replay) 메모리 상의 메시지 라우팅 트리를 재구성하기만 하면, 장애 발생 직전의 상태로 완벽하고 신속하게 복원됩니다.
5. 무한 확장 억제를 위한 컴팩션(Compaction) 아키텍처
"계속 추가만 한다면 결국 디스크가 가득 차지 않는가?"라는 아키텍처적 의문이 남습니다. 이를 해결하기 위해 Artemis는 운영체제에 부하를 주지 않는 스마트한 백그라운드 가비지 컬렉션(GC) 시스템을 가동합니다.
- 파일 분할(Rolling): 저널은 하나의 거대한 파일이 아니라, 일정한 크기(예: 10MB)의 파일 여러 개로 분할되어 관리됩니다.
- 파일 드롭(File Drop): 특정 저널 파일 내에 있는 모든
ADD레코드에 대응하는ACK레코드가 다른 파일에 기록되어, 해당 파일의 모든 메시지가 더 이상 유효하지 않게 되면 브로커는 그 저널 파일을 파일 시스템에서 통째로 지워버립니다. - 컴팩션(Compaction): 여러 개의 구형 저널 파일에 아직 소비되지 않은 유효한 메시지가 듬성듬성 흩어져 파편화가 발생했다면, 백그라운드 스레드가 이 유효한 메시지들만 긁어모아 새로운 저널 파일 하나로 깔끔하게 압축(Compact)하여 옮겨 적습니다. 그리고 파편화되어 있던 원본 파일들은 일괄 삭제하여 디스크 공간을 영구적으로 최적화합니다.
결론적으로 Artemis의 Append-only 저널은 타협의 산물이 아닙니다. 디스크의 물리적 한계를 가장 영리하게 이용하고, 락 경합을 제거하여 멀티 코어 CPU의 효율을 극한으로 뽑아내며, 어떠한 재난 상황에서도 데이터를 지켜내기 위해 치밀하게 설계된 현대 메시징 아키텍처의 정수입니다.
'1. 개발 > 1.8. ActiveMQ' 카테고리의 다른 글
| Libaio와 NIO의 OS 수준 인터럽트 처리 방식 차이는? (0) | 2026.03.23 |
|---|---|
| Journal 파일의 'Compaction' 주기가 늦어질 때 발생하는 디스크 부하? (0) | 2026.03.23 |
| 'journalMaxFileLength' 설정이 체크포인트 주기에 미치는 영향은? (0) | 2026.03.23 |
| KahaDB 인덱스 복구(Cleanup) 시 발생하는 성능 지연 시간은? (0) | 2026.03.22 |
| KahaDB가 인덱스를 위해 B-Tree를 사용하는 이유는? (0) | 2026.03.22 |