mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 10:46:23 +00:00
kafka 설정변경
This commit is contained in:
parent
4197c72af5
commit
180e5978a0
@ -1,5 +1,5 @@
|
|||||||
@test-backend
|
@test-backend
|
||||||
'서비스실행파일작성가이드'에 따라 테스트를 해 주세요.
|
'서비스실행프로파일작성가이드'에 따라 테스트를 해 주세요.
|
||||||
프롬프트에 '[작성정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
|
프롬프트에 '[작성정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
|
||||||
DB나 Redis의 접근 정보는 지정할 필요 없습니다. 특별히 없으면 '[작성정보]'섹션에 '없음'이라고 하세요.
|
DB나 Redis의 접근 정보는 지정할 필요 없습니다. 특별히 없으면 '[작성정보]'섹션에 '없음'이라고 하세요.
|
||||||
{안내메시지}
|
{안내메시지}
|
||||||
|
|||||||
@ -21,9 +21,14 @@
|
|||||||
<entry key="REDIS_PASSWORD" value="Hi5Jessica!" />
|
<entry key="REDIS_PASSWORD" value="Hi5Jessica!" />
|
||||||
<entry key="REDIS_DATABASE" value="5" />
|
<entry key="REDIS_DATABASE" value="5" />
|
||||||
|
|
||||||
<!-- Kafka Configuration -->
|
<!-- Kafka Configuration (원격 서버) -->
|
||||||
<entry key="KAFKA_ENABLED" value="true" />
|
<entry key="KAFKA_ENABLED" value="true" />
|
||||||
<entry key="KAFKA_BOOTSTRAP_SERVERS" value="20.249.182.13:9095,4.217.131.59:9095" />
|
<entry key="KAFKA_BOOTSTRAP_SERVERS" value="20.249.182.13:9095,4.217.131.59:9095" />
|
||||||
|
<entry key="KAFKA_CONSUMER_GROUP_ID" value="analytics-service-consumers" />
|
||||||
|
|
||||||
|
<!-- Sample Data Configuration (MVP Only) -->
|
||||||
|
<!-- ⚠️ Kafka Producer로 이벤트 발행 (Consumer가 처리) -->
|
||||||
|
<entry key="SAMPLE_DATA_ENABLED" value="true" />
|
||||||
|
|
||||||
<!-- Server Configuration -->
|
<!-- Server Configuration -->
|
||||||
<entry key="SERVER_PORT" value="8086" />
|
<entry key="SERVER_PORT" value="8086" />
|
||||||
|
|||||||
@ -84,9 +84,13 @@ public class SampleDataLoader implements ApplicationRunner {
|
|||||||
try {
|
try {
|
||||||
// 1. EventCreated 이벤트 발행 (3개 이벤트)
|
// 1. EventCreated 이벤트 발행 (3개 이벤트)
|
||||||
publishEventCreatedEvents();
|
publishEventCreatedEvents();
|
||||||
|
log.info("⏳ EventStats 생성 대기 중... (2초)");
|
||||||
|
Thread.sleep(2000); // EventCreatedConsumer가 EventStats 생성할 시간
|
||||||
|
|
||||||
// 2. DistributionCompleted 이벤트 발행 (각 이벤트당 4개 채널)
|
// 2. DistributionCompleted 이벤트 발행 (각 이벤트당 4개 채널)
|
||||||
publishDistributionCompletedEvents();
|
publishDistributionCompletedEvents();
|
||||||
|
log.info("⏳ ChannelStats 생성 대기 중... (1초)");
|
||||||
|
Thread.sleep(1000); // DistributionCompletedConsumer가 ChannelStats 생성할 시간
|
||||||
|
|
||||||
// 3. ParticipantRegistered 이벤트 발행 (각 이벤트당 다수 참여자)
|
// 3. ParticipantRegistered 이벤트 발행 (각 이벤트당 다수 참여자)
|
||||||
publishParticipantRegisteredEvents();
|
publishParticipantRegisteredEvents();
|
||||||
@ -100,9 +104,9 @@ public class SampleDataLoader implements ApplicationRunner {
|
|||||||
log.info(" - ParticipantRegistered: 180건 (MVP 테스트용)");
|
log.info(" - ParticipantRegistered: 180건 (MVP 테스트용)");
|
||||||
log.info("========================================");
|
log.info("========================================");
|
||||||
|
|
||||||
// Consumer 처리 대기 (3초)
|
// Consumer 처리 대기 (2초)
|
||||||
log.info("⏳ Consumer 처리 대기 중... (3초)");
|
log.info("⏳ 참여자 수 업데이트 대기 중... (2초)");
|
||||||
Thread.sleep(3000);
|
Thread.sleep(2000);
|
||||||
|
|
||||||
// 4. TimelineData 생성 (시간대별 데이터)
|
// 4. TimelineData 생성 (시간대별 데이터)
|
||||||
createTimelineData();
|
createTimelineData();
|
||||||
|
|||||||
@ -38,7 +38,7 @@ public class DistributionCompletedConsumer {
|
|||||||
/**
|
/**
|
||||||
* DistributionCompleted 이벤트 처리 (설계서 기준 - 여러 채널 배열)
|
* DistributionCompleted 이벤트 처리 (설계서 기준 - 여러 채널 배열)
|
||||||
*/
|
*/
|
||||||
@KafkaListener(topics = "sample.distribution.completed", groupId = "analytics-service")
|
@KafkaListener(topics = "sample.distribution.completed", groupId = "${spring.kafka.consumer.group-id}")
|
||||||
public void handleDistributionCompleted(String message) {
|
public void handleDistributionCompleted(String message) {
|
||||||
try {
|
try {
|
||||||
log.info("📩 DistributionCompleted 이벤트 수신: {}", message);
|
log.info("📩 DistributionCompleted 이벤트 수신: {}", message);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ public class EventCreatedConsumer {
|
|||||||
/**
|
/**
|
||||||
* EventCreated 이벤트 처리 (MVP용 샘플 토픽)
|
* EventCreated 이벤트 처리 (MVP용 샘플 토픽)
|
||||||
*/
|
*/
|
||||||
@KafkaListener(topics = "sample.event.created", groupId = "analytics-service")
|
@KafkaListener(topics = "sample.event.created", groupId = "${spring.kafka.consumer.group-id}")
|
||||||
public void handleEventCreated(String message) {
|
public void handleEventCreated(String message) {
|
||||||
try {
|
try {
|
||||||
log.info("📩 EventCreated 이벤트 수신: {}", message);
|
log.info("📩 EventCreated 이벤트 수신: {}", message);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ public class ParticipantRegisteredConsumer {
|
|||||||
/**
|
/**
|
||||||
* ParticipantRegistered 이벤트 처리 (MVP용 샘플 토픽)
|
* ParticipantRegistered 이벤트 처리 (MVP용 샘플 토픽)
|
||||||
*/
|
*/
|
||||||
@KafkaListener(topics = "sample.participant.registered", groupId = "analytics-service")
|
@KafkaListener(topics = "sample.participant.registered", groupId = "${spring.kafka.consumer.group-id}")
|
||||||
public void handleParticipantRegistered(String message) {
|
public void handleParticipantRegistered(String message) {
|
||||||
try {
|
try {
|
||||||
log.info("📩 ParticipantRegistered 이벤트 수신: {}", message);
|
log.info("📩 ParticipantRegistered 이벤트 수신: {}", message);
|
||||||
|
|||||||
@ -41,10 +41,10 @@ spring:
|
|||||||
max-wait: -1ms
|
max-wait: -1ms
|
||||||
database: ${REDIS_DATABASE:5}
|
database: ${REDIS_DATABASE:5}
|
||||||
|
|
||||||
# Kafka
|
# Kafka (원격 서버 사용)
|
||||||
kafka:
|
kafka:
|
||||||
enabled: ${KAFKA_ENABLED:false}
|
enabled: ${KAFKA_ENABLED:true}
|
||||||
bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:4.217.131.59:9095}
|
bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:20.249.182.13:9095,4.217.131.59:9095}
|
||||||
consumer:
|
consumer:
|
||||||
group-id: ${KAFKA_CONSUMER_GROUP_ID:analytics-service}
|
group-id: ${KAFKA_CONSUMER_GROUP_ID:analytics-service}
|
||||||
auto-offset-reset: earliest
|
auto-offset-reset: earliest
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# 서비스실행파일작성가이드
|
# 서비스실행프로파일작성가이드
|
||||||
|
|
||||||
[요청사항]
|
[요청사항]
|
||||||
- <수행원칙>을 준용하여 수행
|
- <수행원칙>을 준용하여 수행
|
||||||
|
|||||||
48
claude/test-backend.md
Normal file
48
claude/test-backend.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# 백엔드 테스트 가이드
|
||||||
|
|
||||||
|
[요청사항]
|
||||||
|
- <테스트원칙>을 준용하여 수행
|
||||||
|
- <테스트순서>에 따라 수행
|
||||||
|
- [결과파일] 안내에 따라 파일 작성
|
||||||
|
|
||||||
|
[가이드]
|
||||||
|
<테스트원칙>
|
||||||
|
- 설정 Manifest(src/main/resources/application*.yml)의 각 항목의 값은 하드코딩하지 않고 환경변수 처리
|
||||||
|
- Kubernetes에 배포된 데이터베이스는 LoadBalacer유형의 Service를 만들어 연결
|
||||||
|
<테스트순서>
|
||||||
|
- 준비:
|
||||||
|
- 설정 Manifest(src/main/resources/application*.yml)와 실행 프로파일({service-name}.run.xml 내부에 있음)의 일치여부 검사 및 수정
|
||||||
|
- 실행:
|
||||||
|
- 'curl'명령을 이용한 테스트 및 오류 수정
|
||||||
|
- 서비스 의존관계를 고려하여 테스트 순서 결정
|
||||||
|
- 순서에 따라 순차적으로 각 서비스의 Controller에서 API 스펙 확인 후 API 테스트
|
||||||
|
- API경로와 DTO클래스를 확인하여 정확한 request data 구성
|
||||||
|
- 소스 수정 후 테스트 절차
|
||||||
|
- 컴파일 및 오류 수정: {프로젝트 루트}/gradlew {service-name}:compileJava
|
||||||
|
- 컴파일 성공 후 서비스 재시작 요청: 서비스 시작은 인간에게 요청
|
||||||
|
- 만약 직접 서비스를 실행하려면 '<서비스 시작 방법>'으로 수행
|
||||||
|
- 서비스 중지는 '<서비스 중지 방법>'을 참조 수행
|
||||||
|
- 설정 Manifest 수정 시 민감 정보는 기본값으로 지정하지 않고 '<실행프로파일 작성 가이드>'를 참조하여 실행 프로파일에 값을 지정함
|
||||||
|
- 실행 결과 로그는 'logs' 디렉토리 하위에 생성
|
||||||
|
- 결과: test-backend.md
|
||||||
|
<실행프로파일 작성 가이드>
|
||||||
|
- {service-name}/.run/{service-name}.run.xml 파일로 작성
|
||||||
|
- Kubernetes에 배포된 데이터베이스의 LoadBalancer Service 확인:
|
||||||
|
- kubectl get svc -n {namespace} | grep LoadBalancer 명령으로 LoadBalancer IP 확인
|
||||||
|
- 각 서비스별 데이터베이스의 LoadBalancer External IP를 DB_HOST로 사용
|
||||||
|
- 캐시(Redis)의 LoadBalancer External IP를 REDIS_HOST로 사용
|
||||||
|
<서비스 시작 방법>
|
||||||
|
- 'IntelliJ서비스실행기'를 'tools' 디렉토리에 다운로드
|
||||||
|
- python 또는 python3 명령으로 백그라우드로 실행하고 결과 로그를 분석
|
||||||
|
nohup python3 tools/run-intellij-service-profile.py {service-name} > logs/{service-name}.log 2>&1 & echo "Started {service-name} with PID: $!"
|
||||||
|
- 서비스 실행은 다른 방법 사용하지 말고 **반드시 python 프로그램 이용**
|
||||||
|
<서비스 중지 방법>
|
||||||
|
- Window
|
||||||
|
- netstat -ano | findstr :{PORT}
|
||||||
|
- powershell "Stop-Process -Id {Process number} -Force"
|
||||||
|
- Linux/Mac
|
||||||
|
- netstat -ano | grep {PORT}
|
||||||
|
- kill -9 {Process number}
|
||||||
|
|
||||||
|
[결과파일]
|
||||||
|
- develop/dev/test-backend.md
|
||||||
305
develop/dev/test-backend.md
Normal file
305
develop/dev/test-backend.md
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
# 백엔드 테스트 결과서
|
||||||
|
|
||||||
|
## 테스트 개요
|
||||||
|
- **테스트 일시**: 2025-10-27 13:46
|
||||||
|
- **대상 서비스**: analytics-service
|
||||||
|
- **서버 포트**: 8086
|
||||||
|
- **테스트 환경**: 로컬 개발 환경
|
||||||
|
|
||||||
|
## 1. 서버 상태 확인
|
||||||
|
|
||||||
|
### 1.1 Health Check
|
||||||
|
**요청**:
|
||||||
|
```bash
|
||||||
|
curl -X GET "http://localhost:8086/actuator/health"
|
||||||
|
```
|
||||||
|
|
||||||
|
**응답**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "UP",
|
||||||
|
"components": {
|
||||||
|
"db": {
|
||||||
|
"status": "UP",
|
||||||
|
"details": {
|
||||||
|
"database": "PostgreSQL",
|
||||||
|
"validationQuery": "isValid()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redis": {
|
||||||
|
"status": "UP",
|
||||||
|
"details": {
|
||||||
|
"version": "7.2.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"diskSpace": {"status": "UP"},
|
||||||
|
"livenessState": {"status": "UP"},
|
||||||
|
"readinessState": {"status": "UP"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**결과**: ✅ **성공** - 서버 정상 작동, DB 및 Redis 연결 정상
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. API 테스트 결과
|
||||||
|
|
||||||
|
### 2.1 성과 대시보드 조회 API
|
||||||
|
**엔드포인트**: `GET /api/v1/events/{eventId}/analytics`
|
||||||
|
|
||||||
|
**테스트 케이스**:
|
||||||
|
```bash
|
||||||
|
curl -X GET "http://localhost:8086/api/v1/events/evt_2025012301/analytics"
|
||||||
|
```
|
||||||
|
|
||||||
|
**응답**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"errorCode": "EVENT_001",
|
||||||
|
"message": "이벤트를 찾을 수 없습니다",
|
||||||
|
"timestamp": "2025-10-27T13:46:50.7331807"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**결과**: ❌ **실패** - EventStats 데이터 미생성
|
||||||
|
- **원인**: Kafka Consumer 미작동으로 EventCreated 이벤트 미처리
|
||||||
|
- **근본 원인**: Kafka 브로커 연결 실패
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.2 시간대별 참여 추이 API
|
||||||
|
**엔드포인트**: `GET /api/v1/events/{eventId}/analytics/timeline`
|
||||||
|
|
||||||
|
**테스트 케이스**:
|
||||||
|
```bash
|
||||||
|
curl -X GET "http://localhost:8086/api/v1/events/evt_2025012301/analytics/timeline?interval=daily"
|
||||||
|
```
|
||||||
|
|
||||||
|
**응답**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"eventId": "evt_2025012301",
|
||||||
|
"interval": "daily",
|
||||||
|
"dataPoints": [
|
||||||
|
{
|
||||||
|
"timestamp": "2024-09-24T00:00:00",
|
||||||
|
"participants": 36,
|
||||||
|
"views": 108,
|
||||||
|
"engagement": 36,
|
||||||
|
"conversions": 24,
|
||||||
|
"cumulativeParticipants": 36
|
||||||
|
}
|
||||||
|
// ... 150개 데이터 포인트
|
||||||
|
],
|
||||||
|
"trends": {
|
||||||
|
"overallTrend": "stable",
|
||||||
|
"growthRate": 11.1,
|
||||||
|
"projectedParticipants": 944,
|
||||||
|
"peakPeriod": "2024-09-24"
|
||||||
|
},
|
||||||
|
"peakTimes": [
|
||||||
|
{
|
||||||
|
"timestamp": "2024-09-24T00:00:00",
|
||||||
|
"metric": "participants",
|
||||||
|
"value": 40,
|
||||||
|
"description": "최대 참여자 수"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2024-09-27T00:00:00",
|
||||||
|
"metric": "views",
|
||||||
|
"value": 200,
|
||||||
|
"description": "최대 조회수"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**결과**: ✅ **성공** - TimelineData 정상 조회
|
||||||
|
- **데이터 포인트**: 150개 (30일 × 5개 채널)
|
||||||
|
- **기간**: 2024-09-24 ~ 2024-10-23
|
||||||
|
- **트렌드 분석**: 정상 작동
|
||||||
|
- **Peak Time 분석**: 정상 작동
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.3 채널별 성과 분석 API
|
||||||
|
**엔드포인트**: `GET /api/v1/events/{eventId}/analytics/channels`
|
||||||
|
|
||||||
|
**테스트 케이스**:
|
||||||
|
```bash
|
||||||
|
curl -X GET "http://localhost:8086/api/v1/events/evt_2025012301/analytics/channels"
|
||||||
|
```
|
||||||
|
|
||||||
|
**응답**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"eventId": "evt_2025012301",
|
||||||
|
"channels": [],
|
||||||
|
"comparison": null,
|
||||||
|
"lastUpdatedAt": "2025-10-27T13:46:55.9759532"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**결과**: ⚠️ **부분 성공** - 응답은 정상이나 데이터 비어있음
|
||||||
|
- **원인**: ChannelStats 데이터 미생성
|
||||||
|
- **근본 원인**: Kafka Consumer 미작동으로 DistributionCompleted 이벤트 미처리
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.4 투자 대비 수익률 분석 API
|
||||||
|
**엔드포인트**: `GET /api/v1/events/{eventId}/analytics/roi`
|
||||||
|
|
||||||
|
**테스트 케이스**:
|
||||||
|
```bash
|
||||||
|
curl -X GET "http://localhost:8086/api/v1/events/evt_2025012301/analytics/roi"
|
||||||
|
```
|
||||||
|
|
||||||
|
**응답**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"errorCode": "EVENT_001",
|
||||||
|
"message": "이벤트를 찾을 수 없습니다",
|
||||||
|
"timestamp": "2025-10-27T13:46:58.6552438"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**결과**: ❌ **실패** - EventStats 데이터 미생성
|
||||||
|
- **원인**: Kafka Consumer 미작동으로 EventCreated 이벤트 미처리
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 문제 분석
|
||||||
|
|
||||||
|
### 3.1 Kafka 연결 실패
|
||||||
|
**로그 확인**:
|
||||||
|
```
|
||||||
|
2025-10-27 13:46:46 [kafka-producer-network-thread] INFO o.apache.kafka.clients.NetworkClient -
|
||||||
|
[Producer clientId=analytics-service-producer-1] Node 101 disconnected.
|
||||||
|
2025-10-27 13:46:56 [kafka-producer-network-thread] INFO o.apache.kafka.clients.NetworkClient -
|
||||||
|
[Producer clientId=analytics-service-producer-1] Node 100 disconnected.
|
||||||
|
```
|
||||||
|
|
||||||
|
**문제점**:
|
||||||
|
1. Kafka 브로커(20.249.182.13:9095, 4.217.131.59:9095)에 연결 실패
|
||||||
|
2. SampleDataLoader가 이벤트를 발행했지만 브로커에 도달하지 못함
|
||||||
|
3. Kafka Consumer가 이벤트를 수신하지 못함
|
||||||
|
|
||||||
|
### 3.2 Consumer 설정 확인
|
||||||
|
**파일**: `EventCreatedConsumer.java:23`
|
||||||
|
```java
|
||||||
|
@ConditionalOnProperty(name = "spring.kafka.enabled", havingValue = "true", matchIfMissing = false)
|
||||||
|
```
|
||||||
|
|
||||||
|
**설정**:
|
||||||
|
- `application.yml`: `spring.kafka.enabled: ${KAFKA_ENABLED:false}`
|
||||||
|
- 실행 프로파일: `KAFKA_ENABLED=true`
|
||||||
|
|
||||||
|
**Consumer 토픽**:
|
||||||
|
- `sample.event.created` - EventCreatedConsumer
|
||||||
|
- `sample.distribution.completed` - DistributionCompletedConsumer
|
||||||
|
- `sample.participant.registered` - ParticipantRegisteredConsumer
|
||||||
|
|
||||||
|
### 3.3 데이터 생성 흐름
|
||||||
|
|
||||||
|
**정상 흐름**:
|
||||||
|
```
|
||||||
|
SampleDataLoader (시작 시)
|
||||||
|
↓ Kafka 이벤트 발행
|
||||||
|
├─ EventCreated (3개) → EventCreatedConsumer → EventStats 생성
|
||||||
|
├─ DistributionCompleted (3개) → DistributionCompletedConsumer → ChannelStats 생성
|
||||||
|
├─ ParticipantRegistered (180개) → ParticipantRegisteredConsumer → ChannelStats 업데이트
|
||||||
|
└─ TimelineData 직접 생성 (90개)
|
||||||
|
```
|
||||||
|
|
||||||
|
**실제 흐름**:
|
||||||
|
```
|
||||||
|
SampleDataLoader (시작 시)
|
||||||
|
↓ Kafka 이벤트 발행 시도
|
||||||
|
├─ EventCreated → Kafka 연결 실패 → EventStats 미생성 ❌
|
||||||
|
├─ DistributionCompleted → Kafka 연결 실패 → ChannelStats 미생성 ❌
|
||||||
|
├─ ParticipantRegistered → Kafka 연결 실패 → 처리 안됨 ❌
|
||||||
|
└─ TimelineData 직접 생성 (90개) ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 테스트 결과 요약
|
||||||
|
|
||||||
|
| API | 엔드포인트 | 상태 | 비고 |
|
||||||
|
|-----|----------|------|------|
|
||||||
|
| Health Check | `/actuator/health` | ✅ 성공 | DB, Redis 연결 정상 |
|
||||||
|
| 성과 대시보드 | `/api/v1/events/{eventId}/analytics` | ❌ 실패 | EventStats 미생성 |
|
||||||
|
| 시간대별 추이 | `/api/v1/events/{eventId}/analytics/timeline` | ✅ 성공 | 150개 데이터 정상 조회 |
|
||||||
|
| 채널별 분석 | `/api/v1/events/{eventId}/analytics/channels` | ⚠️ 부분 | 빈 배열 반환 |
|
||||||
|
| ROI 분석 | `/api/v1/events/{eventId}/analytics/roi` | ❌ 실패 | EventStats 미생성 |
|
||||||
|
|
||||||
|
**성공률**: 1/4 (25%)
|
||||||
|
- **완전 성공**: Timeline API
|
||||||
|
- **부분 성공**: Channel API (응답 정상, 데이터 없음)
|
||||||
|
- **실패**: Dashboard API, ROI API
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 개선 사항
|
||||||
|
|
||||||
|
### 5.1 즉시 조치 필요
|
||||||
|
1. **Kafka 브로커 연결 확인**
|
||||||
|
- 브로커 상태 확인: `20.249.182.13:9095`, `4.217.131.59:9095`
|
||||||
|
- 네트워크 방화벽 규칙 확인
|
||||||
|
- Kubernetes Service 확인: `kubectl get svc -n kafka`
|
||||||
|
|
||||||
|
2. **Kafka Consumer autoStartup 확인**
|
||||||
|
```java
|
||||||
|
@KafkaListener(
|
||||||
|
topics = "sample.event.created",
|
||||||
|
groupId = "analytics-service",
|
||||||
|
autoStartup = "true" // 추가 확인
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 대안 방안
|
||||||
|
**Kafka 없이 테스트하는 방법**:
|
||||||
|
1. SampleDataLoader 수정하여 Kafka 없이 직접 Repository에 데이터 생성
|
||||||
|
2. 또는 `KAFKA_ENABLED=false` 설정하고 REST API로 데이터 직접 등록
|
||||||
|
|
||||||
|
### 5.3 장기 개선
|
||||||
|
1. **Resilience 향상**
|
||||||
|
- Kafka 연결 실패 시 Retry 메커니즘 추가
|
||||||
|
- Circuit Breaker 패턴 적용 (Resilience4j 이미 설정됨)
|
||||||
|
|
||||||
|
2. **모니터링 강화**
|
||||||
|
- Kafka Consumer Lag 모니터링
|
||||||
|
- 이벤트 처리 실패 알림
|
||||||
|
|
||||||
|
3. **테스트 환경 구성**
|
||||||
|
- 로컬 테스트용 Embedded Kafka 설정
|
||||||
|
- Docker Compose로 Kafka 로컬 환경 구성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 결론
|
||||||
|
|
||||||
|
### 6.1 현재 상태
|
||||||
|
- **기본 기능**: 정상 작동 (서버, DB, Redis 연결)
|
||||||
|
- **API 응답**: 구조적으로 정상 (에러 처리 적절)
|
||||||
|
- **Timeline API**: 완전 정상 작동
|
||||||
|
- **Kafka 의존 API**: Kafka 연결 문제로 데이터 부재
|
||||||
|
|
||||||
|
### 6.2 권고 사항
|
||||||
|
1. **단기**: Kafka 브로커 연결 문제 해결 후 재테스트
|
||||||
|
2. **중기**: Kafka 없이도 테스트 가능한 대안 구현
|
||||||
|
3. **장기**: 이벤트 기반 아키텍처 안정성 개선
|
||||||
|
|
||||||
|
### 6.3 다음 단계
|
||||||
|
1. Kafka 브로커 상태 확인 및 연결 복구
|
||||||
|
2. Consumer 활성화 확인 및 이벤트 재처리
|
||||||
|
3. 전체 API 재테스트 및 결과 검증
|
||||||
Loading…
x
Reference in New Issue
Block a user