3.1 설계 방향
AI 서버 영역은 대량의 로그를 안정적으로 처리하고, AI 기반 분석 인프라를 제공하는 것을 목표로 설계했습니다.
3.1.1. 핵심 설계 원칙
1) 확장 가능한 파이프라인 구조 고객 수와 로그량이 증가해도 처리 성능이 저하되지 않도록 확장성을 우선했습니다.
- Kafka: 로그를 버퍼링하여 트래픽 급증에도 안정적
- Logstash: Worker 수평 확장으로 처리량 증가
- OpenSearch: 클러스터링으로 스토리지 및 검색 성능 확장
2) 고객 서버와의 역할 분리 고객 서버에서는 최소한의 처리만 수행하고, 복잡한 작업은 AI 서버에서 담당합니다.
- 고객 서버: 로그 생성 → 기본 파싱 → Kafka 전송
- AI 서버: 2차 정규화 → 인덱싱 → AI 분석 → 대시보드 제공
3) 실시간 분석과 안정성의 균형 실시간 검색을 제공하면서도, 장애 시 데이터 유실이 없도록 설계했습니다.
- Kafka 보관 기간: 7일 → 장애 발생 시 재처리 가능
- OpenSearch refresh interval: 5초 → 준실시간 검색 제공
- 백업 설계 → 필요 시 인덱스를 장기 보관 스토리지로 이관 가능
3.2 구성 요소
3.2.1 Kafka
고객 서버와 AI 서버 사이에서 로그를 안정적으로 전달하는 메시지 큐입니다.
Kafka를 선택한 이유
| 비교 항목 | Kafka | RabbitMQ | Redis Streams |
|---|---|---|---|
| 처리량 | 매우 높음 (수백만 msg/s) | 보통 | 높음 |
| 메시지 보관 | 설정 가능 (7일) | 소비 후 삭제 | 제한적 |
| 확장성 | 파티션 기반 수평 확장 | 제한적 | 제한적 |
| 재처리 | 오프셋 기반 재소비 | 불가 | 가능하지만 복잡 |
Kafka는 대량의 로그를 고속으로 처리하면서도, 장애 시 재처리가 가능하므로 로그 수집 파이프라인에 적합합니다.
역할
Fluent Bit (고객 서버)
→ Kafka Producer
→ application-logs 토픽
→ 최대 7일간 보관
→ Logstash ConsumerKRaft 모드 도입 Zookeeper 없는 KRaft 모드를 사용해 구성 요소를 단순화했습니다.
- 관리 포인트 감소
- 장애 복구 속도 향상
- 운영 비용 절감
실제 운영 설정 예시
KAFKA_LOG_RETENTION_HOURS: 168 # 7일간 보관
KAFKA_ADVERTISED_LISTENERS:
- PLAINTEXT://kafka:19092 # 내부 통신
- PLAINTEXT_HOST://ai.loglens.store:9092 # 외부 통신 (고객 서버)- 내부 통신: AI 서버 내부에서는
kafka:19092사용 (Logstash ↔ Kafka) - 외부 통신: 고객 서버에서는
ai.loglens.store:9092사용 (Fluent Bit → Kafka)
3.2.2 Logstash
Kafka에서 전달된 로그를 읽어 2차 정규화 후 OpenSearch로 저장합니다.
2차 정규화가 필요한 이유:
고객 서버의 Fluent Bit에서 기본 정규화를 수행하지만,
더 복잡한 구조 변환은 AI 서버에서 처리하는 것이 효율적입니다.
Logstash에서 수행하는 주요 작업
1) 복잡한 필드 변환
- 중첩 JSON(log_details) 파싱
- Java Map → JSON 변환
- Response 로그에서 HTTP 정보 추출
2) 고유 log_id 생성
중복 인덱싱을 방지하기 위해 고유 식별자를 생성합니다.
hash_input = "#{project_uuid}-#{timestamp}-#{message}" log_id = Digest::SHA256.hexdigest(hash_input).to_i(16) % (2**63)3) 고객별 인덱스 라우팅
고객 프로젝트를 구분하기 위해 인덱스를 분리합니다.
index => "%{safe_project_uuid}_%{+YYYY_MM}"Pipeline 구조
Kafka Consumer
→ 필드 정리 및 변환
→ log_id 생성
→ 인덱스 결정
→ OpenSearch Bulk Insert리소스 설정
LS_JAVA_OPTS: -Xmx4g -Xms4g
PIPELINE_WORKERS: 4메모리가 많이 필요한 특성을 고려해 적절한 힙 메모리를 확보했습니다.
3.2.3 OpenSearch
정규화된 로그를 저장·검색·집계하는 검색 엔진입니다.
OpenSearch를 선택한 이유
| 비교 항목 | OpenSearch | Elasticsearch | MongoDB |
|---|---|---|---|
| 검색 성능 | 매우 빠름 | 매우 빠름 | 보통 |
| 전문 검색 | 강력 | 강력 | 제한적 |
| 집계 쿼리 | 강력 | 강력 | 보통 |
| KNN Vector | 지원 (AI 분석) | 지원 | 미지원 |
| 라이선스 | Apache 2.0 (오픈소스) | SSPL (제한적) | SSPL |
OpenSearch는 오픈소스 기반이면서, AI 분석에 필요한 KNN 벡터 검색을 지원한다는 점이 강점입니다.
인덱싱 전략
1) 프로젝트별 + 월별 인덱스 생성
${projectA_UUID}_2025_01
${projectA_UUID}_2025_02
${projectB_UUID}_2025_01- 고객 데이터 격리
- 특정 기간만 검색해 성능 향상
- 삭제/백업이 월 단위로 쉬움
2) Refresh Interval
refresh_interval: 5s검색 속도와 인덱싱 부하 사이에서 적절한 균형을 맞췄습니다.
KNN Vector 지원
AI 기반 로그 분석을 위해 OpenSearch의 KNN(K-Nearest Neighbors) Vector 기능을 활용합니다.
"log_vector": {
"type": "knn_vector",
"dimension": 1536,
"method": {
"name": "hnsw",
"space_type": "innerproduct",
"engine": "faiss"
}
}LLM 기반 분석을 위해 벡터 검색을 활용합니다.
(유사 로그 검색, 패턴 분석 등)
3.3 AI 서버 관점의 이점
3.3.1 고객 서버와의 완전한 분리
- AI 서버 장애가 고객 서버 동작에 영향을 주지 않음
- Kafka 버퍼링으로 장시간 장애에도 데이터 유실 없음
- 중앙 집중적 운영으로 관리 효율성 향상
Fluent Bit이 파일 기반 offset을 관리하므로,
AI 서버가 다운되더라도 고객 서버는 그대로 로그를 저장·전송할 준비를 유지합니다.
3.3.2 수평 확장 가능한 구조
필요에 따라 각 컴포넌트를 독립적으로 확장할 수 있습니다.
Kafka: 파티션 증설
Logstash: Worker/인스턴스 수평 확장
OpenSearch: 노드 & 샤드 증가또한 Kafka UI, OpenSearch Dashboards를 통해 병목 구간을 쉽게 파악할 수 있습니다.
3.3.3 AI 분석 인프라 제공
OpenSearch + FastAPI 기반으로 AI 분석 기능을 제공합니다.
- 벡터 검색 기반 유사 로그 추천
- LLM 기반 에러 원인 분석
- 패턴 기반 이상 탐지
FastAPI 덕분에 Python 생태계(OpenAI, LangChain 등)를 유연하게 연결할 수 있으며,
AI 분석 로직을 독립적으로 발전시킬 수 있습니다.
3.4 설계 트레이드오프
3.4.1 Kafka 보관 기간
선택: 7일
장점
- 최대 7일간 재처리 가능
- Logstash 장애에도 데이터 유실 없음
단점
- 저장 공간 증가
- 오래된 데이터 read 시 성능 저하
보완책
- 디스크 사용량 모니터링
- 지연 시 알림
3.4.2 OpenSearch 인덱스 전략
선택: 고객별 + 월별 인덱스
장점
- 고객 데이터 분리
- 검색 성능 향상
- 삭제·백업 쉬움
단점
- 인덱스 수 증가
- 관리 복잡성 증가
보완책
- ILM 정책 적용
- 오래된 인덱스 Cold Storage로 이동 가능
3.4.3 Logstash vs Kafka Streams
선택: Logstash
| 항목 | Logstash | Kafka Streams |
|---|---|---|
| 러닝커브 | 낮음 | 높음 |
| 개발 속도 | 빠름 | 느림 |
| OpenSearch 연동 | 공식 지원 | 직접 구현 |
| 디버깅 | 쉬움 | 복잡 |
LogLens의 로그 처리량은 Logstash로 충분히 감당할 수 있으며,
빠른 개발·유지보수 관점에서 Logstash가 적합했습니다.
단점
- Ruby 기반이라 메모리 사용량이 많음
- 초고성능 환경에서는 Kafka Streams보다 느릴 수 있음
보완책
- 충분한 메모리 할당
- 필요 시 수평 확장