02. Architecture
목적
APMX를 구성하는 컴포넌트와 각 컴포넌트의 책임 범위, 그리고 컴포넌트 간 통신 방식을 정의한다.
범위
- Java Agent, Collector, Storage, REST API, Console 각각의 책임
- 컴포넌트 간 데이터 흐름
- 장애 격리 원칙 (Agent 장애가 애플리케이션에 영향을 주지 않는 구조)
설계
컴포넌트 책임
- Java Agent:
-javaagent로 대상 애플리케이션에 주입되어 HTTP 요청 단위 Trace를 생성하고, 비동기로 Collector에 전송한다. 애플리케이션 안정성이 최우선이며, 어떤 상황에서도 예외를 애플리케이션 스레드로 던지지 않는다. - Collector: Agent로부터 Trace를 수신(HTTP ingest API), 검증 후 Storage에 저장한다. 통계/분석 로직은 포함하지 않는다.
- Storage: Trace 데이터를 저장한다. MVP는 H2(파일 모드)를 기본으로 하되, Repository/Adapter 구조로 분리되어 있어 PostgreSQL 등으로 교체 가능하다.
- REST API: Collector 프로세스 안에 함께 배포된다(MVP 기준 별도 프로세스 분리 없음). 서비스 목록/통계/Trace 조회 API를 제공한다.
- Console: 조회 API 결과를 시각화하고 계정 관리 등 일부 쓰기 작업도 수행하는 화면 (React + TypeScript + Vite,
console모듈). MVP에서는 Collector와 별도의 독립 dev 서버로만 실행하며, REST API를 CORS로 직접 호출한다 (docs/08-console-design.md참고). - common: Agent와 대상 애플리케이션이 함께 컴파일 시점에 참조하는 극히 가벼운 모듈. 현재는 메서드 호출 스택(Span) 계측 대상을 표시하는
@ApmxTrace어노테이션만 담고 있다 (docs/04-agent-design.md"메서드 호출 스택(Span) 계측" 참고).
프로세스 배치 (MVP)
text
┌─────────────────────┐ ┌───────────────────────────────┐ ┌──────────────┐
│ Target Application │ │ Collector │ │ Console │
│ (example-app 등) │ │ (Spring Boot 단일 프로세스) │ │ (Vite dev │
│ │ │ │ │ 서버, MVP) │
│ ┌────────────────┐ │ HTTP │ ┌───────────┐ ┌────────────┐ │ HTTP │ │
│ │ apmx Agent │──┼───────▶│ │ Ingest API│──▶│ Storage │ │◀───────┼── fetch │
│ │ (javaagent) │ │ │ └───────────┘ │ (H2/PG) │ │ (CORS) │ (GET only) │
│ └────────────────┘ │ │ ┌───────────┐ └────────────┘ │ │ │
│ │ │ │ Query API │◀───────┘ │ │ │
└─────────────────────┘ │ └───────────┘ │ └──────────────┘
└───────────────────────────────┘MVP에서는 REST API를 Collector와 같은 Spring Boot 프로세스에 함께 둔다. AGENTS.md의 "불필요한 마이크로서비스 분리 금지" 원칙에 따른 결정이며, 트래픽이 늘어나면 이후 별도 프로세스로 분리할 수 있도록 ingest 관련 코드(io.apmx.collector.ingest)와 조회 관련 코드 (io.apmx.collector.query)를 패키지 단위로 분리해 두었다.
장애 격리 원칙
- Collector가 죽어도 애플리케이션 요청은 영향받지 않는다 (Agent가 별도 스레드에서 전송).
- Agent 내부 큐가 가득 차면 새 Trace를 버린다 (드롭 정책, 애플리케이션 스레드는 절대 블로킹하지 않음).
- Agent 초기화(premain) 자체가 실패해도 애플리케이션 구동에는 영향을 주지 않는다.
예시
실제 검증한 시나리오: Collector 프로세스를 강제 종료한 상태에서 대상 애플리케이션에 요청을 보내면 정상적으로 응답한다 (요청 처리 시간에 변화 없음). 자세한 내용은 docs/04-agent-design.md의 "장애 격리 검증" 참고.
TODO
- Collector를 ingest/query 두 개의 배포 단위로 분리하는 옵션 검토
- Console 정적 빌드 결과물을 Collector(또는 별도 정적 호스팅)에 배포하는 옵션 검토 (현재는 독립 dev 서버로만 실행)
- Python/Node Agent를 위한 공통 ingest 프로토콜 문서화