주식앱 ADR 인덱스

새 과제 착수 전 관련 카테고리를 먼저 확인한다.
결정 요약은 각 ADR의 ## 결정 섹션 첫 줄이다.


아키텍처 / 서비스 분리

ADR결정 요약
Aggregator 서비스 분리 방식 선택신규 aggregator/ Spring Boot(:8090)를 FE 진입점으로 배치, BE(8080) 수정 없음
시그널 서비스 언어·프레임워크 선택ml/ FastAPI(:8000)로 분리, 코어 BE(:8080)와 독립 배포
아키텍처 패턴 선택Hexagonal — presentation→application→domain←infrastructure, OutputPort 패턴 미사용
개인계좌·주문 기능 도메인 패키지 분리 구조 결정account / order / holding 3개 패키지 분리, TradeHistory는 holding 패키지
수동 포트폴리오 도메인 분리 방식 선택portfolio 패키지에 ManualHolding 도메인 신설, manual_holdings 테이블 분리
AI 프레임워크 선택Spring AI 1.0.x — MCP Server 용도만, ChatClient/Anthropic 스타터 미포함
ADR-001 KRX 수집 코드 위치 선택BE(Kotlin)에서 수집·MySQL 영속화, infrastructure/krx 어댑터 (ml은 stateless)
ADR-003 도메인 패키지 구조 선택marketflow 단일 패키지에 팩터별 5개 Entity 분리 (KRX는 infra 어댑터명)
ADR-008 예측 갱신 실행 주체별도 worker 서버(:8091) 신설 — stateless 오케스트레이션 전담
ADR-010 worker 재계산 책임 경계worker는 오케스트레이션만 (입력=BE, 계산=ml, 영속화=BE)

캐시 / 저장소 선택

ADR결정 요약
ML 응답 캐시 저장소 선택Redis, symbol 키, TTL 600초
시그널 응답 캐시 저장소 선택in-memory TtlCache, 종목별 TTL 600초 (SIGNAL_CACHE_TTL)
뉴스 스냅샷 캐시 저장소 선택BE news_snapshots 테이블에 영속화
현재가(실시간) 처리 저장소 선택SSE + BE 스케줄러
대화 히스토리 저장소 선택ConcurrentHashMap<sessionId, List> 인메모리, 히스토리는 시스템 프롬프트로 prepend
신호 영속화 저장소 선택BE signal_snapshots 테이블 + BeSignalSnapshotRepositoryImpl으로 교체 (Redis 제거)
Toss API 인증 토큰 영속화 저장소 선택MySQL toss_tokens 테이블, expires_at 기반 재발급
ML in-memory TtlCache 제거 여부 결정ml/ TtlCache 완전 제거, LLM 결과는 MySQL 영속화로 전환
SSE payload 변경 저장소 선택SSE event data를 JSON 배열로 변경 (refresh 문자열 제거)

외부 API / Rate Limiting

ADR결정 요약
Rate Limiter 라이브러리 선택Resilience4j (resilience4j-spring-boot3 + resilience4j-kotlin)
CircuitBreaker 적용 범위 선택단일 toss CircuitBreaker — 모든 Gateway에 공유
RateLimiter Gateway 적용 방식 선택명시적 래핑 — TossRateLimiterFacade.execute(group) { … }
RateLimiter 한도 초과 시 대기 vs 즉시 실패 선택timeout-duration: 0ms (즉시 실패)
429 응답의 CircuitBreaker 실패 기록 여부 선택429를 CircuitBreaker failure로 기록 — TossRateLimitException을 record-exceptions에 등록
CUD 요청의 Toss와 MySQL 처리 순서 결정Toss API 호출 → 성공 시 MySQL 저장, @Transactional은 MySQL 단계에만
보유종목·거래내역 읽기 동기화 방식 선택조회 요청마다 Toss API 호출 + unique 제약으로 upsert, 별도 스케줄러 없음
ADR-004 KRX 접근 방식과 사이드 이펙트 통제MDC 스크래핑(OTP+getJsonData)으로 시작, rate 통제·백오프, 차단 시 유료벤더 재검토

AI · ML 모델 선택

ADR결정 요약
LLM 오케스트레이터 선택claude -p CLI를 subprocess로 실행 (Anthropic API 직접 호출 미사용)
감성 분석 수행 방식 선택subprocess.run([“claude”, “-p”, prompt]), timeout 120s, JSON 강제, 실패 시 NEUTRAL 폴백
per-headline 감성 분석 호출 방식 선택claude -p 단일 배치 호출로 감성·번역·요약 일괄 처리
해외 뉴스 번역 처리 방식 선택번역·감성·요약을 단일 claude -p 프롬프트에서 처리
단기 가격 예측 곡선 모델 선택선형회귀 기울기 + momentum_score 가중
단기·중기·장기 예측 모델 선택기존 build_prediction에 horizon 파라미터 확장, sigma × sqrt(d)로 불확실성 표현
매도 추천 시점 산출 방식 선택horizon별 예측 포인트 중 최고값 주차를 매도 추천 주차로 선정
후보군 스코어링 실행 방식 선택ThreadPoolExecutor(max_workers=5) 병렬 실행, 실패 종목 제외 (부분 실패 허용)
백테스트 방식 및 감성 포함 여부 선택룩어헤드 배제, 기술 모멘텀만 검증, 뉴스 감성 미포함
웹 서치 MCP 서버 선택Brave Search MCP 서버 (Tavily 미사용, BRAVE_API_KEY 환경변수 필요)

도메인 로직 / 비즈니스 규칙

ADR결정 요약
OrderStatus 전이 규칙 배치 위치 결정OrderStatus.canTransitTo() 메서드로 캡슐화, Order Entity 내부에서 검증
활성 계좌 단일 선택 강제 방식 결정accounts.selected TINYINT(1), 단일 트랜잭션에서 기존 0→신규 1, Account.select()/deselect() Entity 메서드
watchlist 상태 조회 시 도메인 경계 처리 방식 선택ListStocksUseCase에서 WatchlistDomainService.findAll() → symbol set 교차 조회
종합 시그널 점수 가중치 결정composite = 0.6×sentiment + 0.4×momentum, [-1,1] 클램핑, 5단계 라벨
시그널 결과물의 성격 정의참고용 명시, 백테스트로 한계 노출
목표가 알림 발송 횟수 정책 선택도달 시 TRIGGERED 전이 (터미널), 이력은 alert_history 별도 적재
진입가 산출 방식 선택현재가 ≤ MA20 → 즉시 분할 매수, 현재가 > MA20 → max(MA20, 최근저점) 눌림목 대기
추천 후보군 모집단 구성 방식 선택watchlist ∪ CURATED_SYMBOLS(KR 8 + US 4), BE 조회 실패 시 빈 리스트로 graceful
ADR-005 공매도 공시 시차 기준일 처리공매도 trade_date·disclosed_date 분리 저장, 팩터 조회·정렬은 trade_date 기준

네트워크 / 통신 경로

ADR결정 요약
FE → Aggregator 포트 전환 전략 선택FE NEXT_PUBLIC_API_BASE_URL → 8090, BE(8080)는 유지
Reverse Proxy 구현 방식 선택Spring RestClient로 헤더·본문·상태코드 그대로 전달, Spring Cloud Gateway 미도입
MCP 트랜스포트 방식 선택spring-ai-starter-mcp-server-webmvc (SSE 트랜스포트), localhost:8080/mcp/sse
FE의 ML 서비스 호출 경로 결정시그널/추천은 ML(:8000) 직접, watchlist/alert는 BE(:8080) 직접
Aggregator의 Backend·ML 호출 방식 선택코루틴 async/await로 BE 손익 조회와 ML 예측을 병렬 호출
LLM 호출 트리거 방식 선택 (TTL 자동 vs 사용자 명시적 새로고침)TTL 자동 갱신 제거, 사용자 명시적 refresh=true로만 LLM 호출

데이터 수집 / 동기화

ADR결정 요약
뉴스 수집 소스 선택KR=Google News RSS(ko), US=GDELT(폴백 Google News en-US)
종목 마스터 동기화 전략 선택DB 우선 + Toss API fallback + 스케줄러 3가지 병행
시세 수집 방식 선택@Scheduled 30초 주기 폴링, 주기는 alert.polling.interval-ms 프로퍼티 외부화
중소형주 후보군 관리 방식 선택CURATED_SYMBOLS dict에 large/mid/small 카테고리 키 추가
테마 연관 종목 매핑 방식 선택v1: 정적 JSON 매핑, v2에서 Claude 동적 보완 예정
ADR-002 수집 주기 선택장 마감 후 1일 1배치 수집 (실시간 폴링 미수행, EOD 확정치)

알림 / 이벤트 발송

ADR결정 요약
멀티 채널 알림 발송 구조 선택NotificationGateway 인터페이스 + 채널별 구현체 + CompositeNotificationGateway(@Primary), 채널 on/off 환경변수
추천 진입가 알림 등록 방식 선택FE에서 POST /api/v1/alerts (targetPrice=entry, direction=BELOW), 신규 BE 없음
ADR-007 수집 결과 전파 방식수집 후 marketflow.collected.v1 Kafka 이벤트 발행 (동기 호출·outbox 미도입)
ADR-009 이벤트 단위배치당 1건(collected.v1, payload=기준일) — 종목별 이벤트 미사용

검색 / 조회 / 확장

ADR결정 요약
종목 검색 구현 방식 선택하이브리드 — DB 우선 + Toss API fallback
커스텀 필드 확장 전략 선택단일 stocks 테이블 + nullable 컬럼 (별도 테이블 미분리)

배포 / 인프라

ADR결정 요약
CI·CD 플랫폼 선택GitHub Actions
Docker 이미지 저장소 선택GitHub Container Registry (ghcr.io)
E2E 테스트 도구 선택Playwright
E2E CI 실행 환경 선택GitHub Actions service 컨테이너 + bootRun
프로덕션 배포 전략 선택Docker Compose + SSH 배포
로컬 DB 환경 및 포트 선택docker-compose.yml MySQL 8.0, 호스트 포트 3308, Flyway 관리
DB 컬럼 타입 제약 정책 선택FK 컬럼 없음, 상태/방향은 VARCHAR, 날짜는 DATETIME(6)

Git Hook / 자동화

ADR결정 요약
AI 리뷰 fallback 순서 선택Claude 1차, Codex fallback
AI 전체 실패 시 push·PR 허용 여부 결정경고 출력 후 허용
Claude 토큰 한도 감지 방법 선택출력에 “context length” / “token limit” / “rate limit” / “maximum context” 포함 여부 또는 출력 완전 비어있음으로 감지
commit-msg 훅의 사용자 입력 보호 정책 결정커밋 메시지 파일이 비어있을 때만 Codex가 생성

옵저버빌리티 / 모니터링

ADR결정 요약
ADR-001 옵저버빌리티 백엔드 스택 선택PoC 측정 완료, Grafana 우위 권고이나 당분간 양 스택(Grafana·SigNoz) 병행 운영 (Collector fan-out)
ADR-002 계측 표준 선택전 서비스 계측을 벤더 중립 OpenTelemetry(OTLP)로 통일
ADR-003 텔레메트리 라우팅 구조 선택중앙 OTel Collector 게이트웨이가 SigNoz·Grafana로 fan-out
ADR-004 Spring 계측 방식 선택backend·aggregator는 OTel Java agent 자동계측(무코드)
ADR-005 인프라 메트릭 수집 방식 선택mysqld/kafka/redis exporter + Prometheus·Collector scrape
ADR-006 compose 구성 분리 전략 선택앱/Grafana/SigNoz/Collector를 별도 compose 파일로 분리
ADR-007 메시지 소비 트레이스 검증 방식 선택검증 전용 최소 샘플 Kafka produce→consume 경로로 검증
ADR-006 배치 모니터링과 청크 전환 시그널@Scheduled 유지 + collect_log·Discord·Micrometer 3층, 임계 초과 시 Spring Batch 전환 신호

보안 / 설정

ADR결정 요약
민감 정보 주입 방식 선택~/.zshrc 환경변수만 (TOSS_API_KEY, DISCORD_WEBHOOK_URL), 코드·설정파일 하드코딩 금지